mysql 大表中count() 使用方法以及性能优化.

笔者如今遇到这么一个场景,sql

一个单表中包含有6000w+的数据,然而你又不能拆分.须要分别统计表中有多少数据,A产品有多少,B产品有多少这几个数据.优化

在为优化以前.表结构以下,为了隐藏内容我将相应字段作了模糊化处理.设计

CREATE TABLE `xxxx` (
  `link` varchar(200) DEFAULT NULL,
  `test0` varchar(500) DEFAULT NULL,
  `test1` varchar(50) DEFAULT NULL,
  `test2` int(11) DEFAULT NULL,
  `test3` varchar(20) DEFAULT NULL,
  `test4` varchar(50) DEFAULT NULL,
  `test5` varchar(50) NOT NULL,
  `inserttime` datetime DEFAULT NULL,
  `test6` bit(1) NOT NULL DEFAULT b'0',
  `A` bit(1) NOT NULL DEFAULT b'0',
  `B` bit(1) NOT NULL DEFAULT b'0' ,
  PRIMARY KEY (`test5`),
  KEY `test6` (`test6`) USING BTREE,
  KEY `A` (`A`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这个一个常规的InnoDB的表格,因此它的count(*)比起MyISAM的效率慢不少,InnoDB所显示的row的行数不很准确,因此在这这里我须要统计一下.有这么几个策略.
共计61500000数据code

  • count(*) 耗时 1539.499s
  • count(1) 耗时 907.581s
  • count(A) 对索引进行count.
  • count(test6) 对主键进行count.

无一例外,因为这个表没有优化好上面不管哪种都须要几千秒的时间,这个是咱们没法忍受的.索引

下面咱们开始着手分析处理这个问题.字符串

预期整个表的count(*)应该在200s之内为正常,100之内为良好,50之内为优秀.产品

首先我将里面test6抽取了出来,单独造成了一个表.对其进行操做.
共计61500000数据it

  • count(*) 耗时10.238s
  • count(1) 耗时8.710s
  • count(test6) 对主键进行count.耗时12.957s

其中count(1)的效率最高,比最慢count(pk)速度提高了52.0%.class

将你能肯定的字段改成最优值,例如:test

  • varchar更为char.虽然varchar能够自动分配存储空间的大小可是.varchar须要使用1到2个额外的字节来记录字符串的长度,增长它的update的操做时间,
  • datetime改成timestamp后者在1978-2038年之间

最后使用count(1)检验的时候最快耗时,168s.虽然有些慢可是能够接受.

总结:

  • 从新设计你表中的字段,尽可能优化它的长度.不要一味使用过多的varchar.
  • 使用count(1)而不是count(*)来检索.
相关文章
相关标签/搜索