高性能MySQL读后感高性能的索

李从悠 https://www.sohu.com/a/330332735_120224920

对于一条SQL,开发同学最先关心的啥?我觉得还不到这个SQL在数据库的执行过程,而是这条SQL是否能尽快的返回结果,在SQL的生命周期里,每一个环节都有足够的优化空间,但是我们有没有想过,SQL优化的本质是啥?终极目标又是啥?其实优化本质上就是减少SQL对资源的消耗和依赖,正如数据库优化的终极目的是Donothingindatabase一样,SQL优化的终极目的是Consumenoresource。

数据库资源有两个特性:

首先资源是有限的,大家都抢着用就会有瓶颈的,所以SQL的瓶颈可能是由资源紧张产生的。

其次资源是有代价的,并且代价各异,比如内存的时延ns,SSDus,SAS盘10ms,网络更高,那么访问CPUL1/L2/L3cache的代价就比访问内存的要低,访问内存资源的代价要比访问硬盘资源的代价,所以SQL的瓶颈也可能是访问了代价比较高的资源导致的。

现代计算机体系下,机器上粗粒度的资源就那么几种,无非是CPU,内存,硬盘,和网络。那么我们来看下SQL需要消耗哪些资源:

比较、排序、SQL解析、函数或逻辑运算需要用到CPU;

缓存数据访问,临时数据存放需要用到内存;

冷数据读取,大数据量的排序和关联,数据写入落盘,需要访问硬盘;

SQL请求交互,结果集返回需要网络资源。

那么SQL优化思路自然是减少SQL的解析,减少复杂的运算,减少数据处理的规模,减少对物理IO的依赖,减少服务器和客户端的网络交互,本文的每一节都解决上面的一两点,索引策略的组合最大化提升SQL优化性能:

独立的列:减少SQL的解析

前缀索引和索引选择性:减少数据处理的规模,减少对物理IO的依赖

多列索引:减少对物理IO的依赖

选择和是的索引列顺序:减少数据处理的规模,减少对物理IO的依赖

聚簇索引:减少数据处理的规模,减少对物理IO的依赖

覆盖索引:减少对物理IO的依赖

使用索引扫描来做排序:减少复杂的运算

返回必要的列:减少对物理IO的依赖,减少服务器和客户端的网络交互

在学习MySQL索引之前,最好先学习MySQL索引背后的数据结构及算法原理。

独立的列

独立的列是指索引列不能是表达式的一部分,也不能是函数的参数。

例如:下面这个查询无法使用actor_id列的索引:

mysqlexplainselectactor_idfromactorwhereactor_id+1=5;+----+-------------+-------+-------+---------------+---------------------+---------+------+------+--------------------------+

id

select_type

table

type

possible_keys

key

key_len

ref

rows

Extra

+----+-------------+-------+-------+---------------+---------------------+---------+------+------+--------------------------+

1

SIMPLE

actor

index

NULL

idx_actor_last_name

NULL

Usingwhere;Usingindex

+----+-------------+-------+-------+---------------+---------------------+---------+------+------+--------------------------+

凭肉眼容易看出where的表达式其实等价于actor_id=4,但是MySQL无法自动解析这个函数。所以应该简化where条件:始终将索引列单独放在比较符号的一侧,使用索引的正确写法如下,此时使用主键索引:

mysqlexplainselectactor_idfromactorwhereactor_id=4;+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+

id

select_type

table

type

possible_keys

key

key_len

ref

rows

Extra

+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+

1

SIMPLE

actor

const

PRIMARY

PRIMARY

2

const

1

Usingindex

+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+

下面是另外一个常见的错误:

mysqlselect...whereto_days(current_date)-to_days(date_col)=10;

前缀索引和索引选择性

有时候索引很长的字符列,让索引变得大且慢。通常索引开始的部分字符,可以大大节约索引空间,从而提高索引效率。但这样也会降低索引的选择性。索引的选择性是指:不重复的索引值(也称为基数,Cardinality)和数据表的记录总数(#T)的比值,范围是1/#T~1。索引的选择性越高则查询效率越高,因为选择性高的索引让MySQL在查找时过滤掉更多的行。唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。

一般情况下某个列前缀的选择性如果足够高,也是可以满足查询性能。对于BLOB、TEXT或者很长的VARCHAR类型的列,必须使用前缀索引,因为MySQL不允许索引这些列的完整长度。如下所示,varchar()类型的


转载请注明:http://www.aierlanlan.com/rzdk/4274.html