MySQL超大表如何提高count速度


經常用到count統計記錄數,表又超級大,這時候sql執行很慢,就是走索引,也是很慢的,怎么辦呢?

1.這個時候我們就要想為什么這么慢:根本原因是訪問的數據量太大,就算只計算記錄數也是很慢的。

2.如何解決?減少數據訪問量。

3.怎么才能減少訪問量呢?更小的索引。

4.怎么能使索引更小呢?創建前綴索引。

 

至此我們的方案出來了!下面看看具體的:

表結構:

CREATE TABLE `sbtest3` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`k` int(11) NOT NULL DEFAULT '0',
`c` char(120) NOT NULL DEFAULT '',
`pad` char(60) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `k_3` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=5000001 DEFAULT CHARSET=latin1;

執行count花費3.58秒,不能接受!!!!!!
select count(*) from sbtest3;
+----------+
| count(*) |
+----------+
| 5000000 |
+----------+
1 row in set (3.58 sec)

看看執行計划,走的是k_3索引。

explain select count(*) from sbtest3;
+----+-------------+---------+-------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | sbtest3 | index | NULL | k_3 | 4 | NULL | 4804854 | Using index |
+----+-------------+---------+-------+---------------+------+---------+------+---------+-------------+

創建一個短索引。

create index idx_sbt3_c on sbtest3(c(1));

看執行計划選擇了這個短索引。

explain select count(*) from sbtest3;
+----+-------------+---------+-------+---------------+------------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+------------+---------+------+---------+-------------+
| 1 | SIMPLE | sbtest3 | index | NULL | idx_sbt3_c | 1 | NULL | 4804854 | Using index |
+----+-------------+---------+-------+---------------+------------+---------+------+---------+-------------+

執行一下sql花費0.59秒,還能接受。

select count(*) from sbtest3;
+----------+
| count(*) |
+----------+
| 5000000 |
+----------+
1 row in set (0.59 sec)

 

現實環境如果帶where條件怎么辦?

如下我想獲得id>10000的記錄數,花費2.55秒,不可接受!!!!

select count(*) from sbtest3 where id>10000;
+----------+
| count(*) |
+----------+
| 4990000 |
+----------+
1 row in set (2.55 sec)

可以換種思路:

先得到相反條件過濾數據多的記錄數,然后再獲得總數,然后相減,速度也是有很大的提高。

select count(*) from sbtest3 where id<=10000;
+----------+
| count(*) |
+----------+
| 10000 |
+----------+
1 row in set (0.08 sec)

 

select count(*) from sbtest3;
+----------+
| count(*) |
+----------+
| 5000000 |
+----------+
1 row in set (0.59 sec)

 

select 5000000 - 10000;
+----------------+
| 5000000 - 9999 |
+----------------+
| 49900010|
+----------------+
1 row in set (0.00 sec)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM