Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2268357
  • 博文数量: 293
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2170
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-31 14:30
个人简介

自己慢慢积累。

文章分类

全部博文(293)

分类: Mysql/postgreSQL

2018-07-03 18:15:43

转自:

https://www.cnblogs.com/katec/p/9259517.html
博主文章很不错,大家可以去看看。

经常用到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)

阅读(1679) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~