MySQL性能优化(二)

一、聚簇索引的页分裂过程

数据有规律在叶子节点下,当插入不规则数据时,它会打散数据节点重新排序,导致叶子节点拖着沉重的数据来回走动,这就是页分裂。

二、索引覆盖

索引覆盖是指如果查询的列恰好是索引的一部分,那么查询只需要索引文件上进行,不需要回行到磁盘再找数据。这种查询非常快,称为“索引覆盖”。

三、理想的索引

1、查询频繁; 2、区分度高;3、长度小;4、尽量能覆盖常用查询字段。

区分度高:100万用户,性别基本上男/女各为50W,区分度就低。

索引长度直接影响索引文件的大小,影响增删改的速度,并间接影响查询速度(占用内存大)。

扫描二维码关注公众号,回复: 2647236 查看本文章

针对列中的值,从左往右截取部分,来建索引

1、截取的越短,重复度越高,区分的越小,索引效果不好;

2、截取的越长,重复度越低,区分度越大,索引效果越好,但带来的影响也越大,增删改慢并间接影响查询速度。

所以我们要在 区分度+长度 两者上取得一个平衡。

惯用的手法:截取不同的长度并测试其区分度。

四、伪哈希索引

例如:在对url列建立索引时,使用hash算法算出一个哈希值,用这个哈希值来创建索引,而不是直接用url来建索引。

五、多列索引的原则

多列索引的考虑因素--列的查询频率,列的区分度,列的查询顺序,注意一定要结合实际业务场景。

六、索引与排序

排序可能发生2种情况:

1、对于覆盖索引,直接在索引上查询时,就是有序的,unsing index,在innodb引擎中,沿着索引字段排序,也是自然有序的。对于myisam引擎,如果按某索引字段排序,如id,但取出的字段中,未有索引字段,如goods_name,myisam的做法,不是 索引->回行,而是先取出所有行,再进行排序。

2、先取出数据,形成临时表做filesort(文件排序,但文件可能在磁盘上,也可能在内存中)

我们的争取目标:取出来的数据本身就是有序的。要利用索引排序。

七、重复索引和冗余索引

重复索引:是指 在同一个列(如age),或 顺序相同的几个列(age,school),建立多个索引,称为重复索引,重复索引没有任何帮助,只会增大索引文件,拖慢更新速度。

冗余索引:是指2个索引覆盖的列有重叠。

八、索引的碎片与维护

在长期的数据更改过程中,索引文件和数据文件,都将产生空洞形成碎片。我们可以通过一个nop操作(不产生对数据实质影响的操作),来修改表。比如:表的引擎为innodb,可以

alter table xxx engine innodb;

optimize table 表名,也可以修复。

注意:修复表的数据及碎片就会把所有的数据文件重新整理一遍,使之对齐。这个过程,如果表的行数比较大,也是非常耗费资源的操作,所以不能频繁的修复。

如果表的update操作很频繁,可以按月来修复。如果不频繁可以更长的周期来做维护。

九、SQL语句优化

1、sql语句时间花在哪?花在了等待时间和执行时间上。这两个时间并非孤立,如果单条语句执行快了,对其他语句的锁定的时间也就减少。

2、sql语句的执行时间又花在哪?a)查询--沿着索引查找,慢者可能全表扫描;b)取出--查到行后,把数据区出来(sendingdata)

如何查询块:

1)查询的快 -- 联合索引的顺序,区分度,长度

2)取出快--索引覆盖

3)传输的少,更少的行和列

切分查询:按数据拆成多次

例如:100000行数据,每1000条为单位,插件。

分解查询:按逻辑把多表连接查询分成多个简单sql。

3、sql语句的优化思路

不查->少查->高效的查

不查:通过业务逻辑来计算,比如论坛的注册会员数,我们可以根据前3个月统计的每天注册数,用程序来估算。

少查:尽量精准数据,少取行。我们观察新闻网站,评论内容等,一般一次性取列表 10-30条左右。

必须查,尽量走索引上查询。

取时尽量少的列。例如:

select * from tableA 取出所有的列,不建议。

select * from tableA, tableB 取出A,B表的所有列。

十、count和union

count()优化

误区:

1、myisam的count()非常快

是比较块,但仅限于查询表的所有行比较快,因为myisam对行数进行了存储,一旦有条件的查询,速度就不再快了,尤其是where条件的列上没有索引。

2、假如,id<100的商家都是我们内部测试的,我们想查询真实的商家有多少?

select count(*) from lx_com where id>=100;(1000多万行用了6.X秒)

小技巧:

select count(*) from lx_com; 快

select count(*) from lx_com where id < 100;快

select count(*) from lx_com - select count(*) from lx_com where id < 100;快

3、group by

注意:

1) 分组用于统计,而不用于筛选重复数据。

不重复的行,分组统计数据,而不要让查询产生N多重复数据,比如1->N连接时,栏目--左连接-->商品表,将会产生重复行用group去重效率很低。

比如:统计统计平均分,最高分,适合,但用于筛选重复数据则不适合。以及用索引来避免临时表和文件排序。

group by 的列要有索引,可以避免临时表和文件排序。

order by 的列要和group by的一致,否则也会引起临时表。

(原因是因为order by 和group by 都需要排序,所以如果两者的列不一致,那么必须经过至少1次排序)。

2) 以A,B表连接为例,主要查询A表的列,那么group by ,order by的列尽量相同,而且列应该显示申明为A的列:select A.id,A.cat_id from A inne join B group by A.cat_id order by A.cat_id

4、union优化

union 总是要生产临时表,对union的优化比较棘手。注意union的子句条件要尽量具体,即查询更少的行;子句的结果在内存里并成结果集需要去重复,去重复就得先排序。

十一、limit翻页优化

limit offset,N,当offset非常大时,效率极低。原因是mysql并不是跳过offset行然后单取N行,而是取offset+N行,返回 放弃前offset行,返回N行,效率较低,当offset越大时,效率越低。

优化办法:

1、从业务上去解决。办法:不允许翻页过100页,以百度为例,一般翻页到70页左右。

2、不用offset,用条件查询,例:

select id,name from x_com limit 5000000,10;

改:select id,name from x_com where id>5000000 limit 10;

猜你喜欢

转载自blog.csdn.net/qun_y/article/details/81208002