笔者现在遇到这么一个场景,
一个单表中包含有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数据
-
count(*)
耗时 1539.499s -
count(1)
耗时 907.581s -
count(A)
对索引进行count. -
count(test6)
对主键进行count.
无一例外,由于这个表没有优化好上面无论哪一种都需要几千秒的时间,这个是我们无法忍受的.
下面我们开始着手分析处理这个问题.
预期整个表的count(*)
应该在200s以内为正常,100以内为良好,50以内为优秀.
首先我将里面test6
抽取了出来,单独形成了一个表.对其进行操作.
共计61500000数据
-
count(*)
耗时10.238s -
count(1)
耗时8.710s -
count(test6)
对主键进行count.耗时12.957s
其中count(1)
的效率最高,比最慢count(pk)
速度提升了52.0%.
将你能确定的字段改为最优值,例如:
-
varchar
更为char
.虽然varchar
可以自动分配存储空间的大小但是.varchar
需要使用1到2个额外的字节来记录字符串的长度,增加它的update
的操作时间, -
datetime
改为timestamp
后者在1978-2038年之间
最后使用count(1)
检验的时候最快耗时,168s.虽然有些慢但是可以接受.
总结:
- 重新设计你表中的字段,尽量优化它的长度.不要一味使用过多的
varchar
. - 使用
count(1)
而不是count(*)
来检索.