筆者現在遇到這麼一個場景,
一個單表中包含有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(*)
來檢索.