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(*)來檢索.
相關文章
相關標籤/搜索