MySQL的SQL分析及索引使用
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
SQL 性能分析
SQL 执行频率
MySQL 客户端连接成功后通过 show [session|global] status 命令可以提供服务器状态信息。通过如下指令可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次
-- session 是查看当前会话 ;
-- global 是查询全局数据 ;
SHOW GLOBAL STATUS LIKE 'Com_______';
慢查询日志
慢查询日志记录了所有执行时间超过指定参数long_query_time单位秒默认10秒的所有 SQL语句的日志。MySQL的慢查询日志默认没有开启我们可以查看一下系统变量 slow_query_log。
show variables like 'slow_query_log';
如果要开启慢查询日志需要在MySQL的配置文件/etc/my.cnf中配置如下信息配置完毕之后需要重新启动MySQL服务器。
# 开启MySQL慢日志查询开关
slow_query_log=1
# 设置慢日志的时间为2秒SQL语句执行时间超过2秒就会视为慢查询记录慢查询日志
long_query_time=2
profile详情
show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。通过have_profiling参数能够看到当前MySQL是否支持profile操作。
SELECT @@have_profiling;
如果MySQL是支持 profile操作的但是开关是关闭的可以通过set语句在session/global级别开启profiling。
SET profiling = 1;
当执行一系列的业务SQL的操作后可以通过如下指令查看指令的执行耗时
-- 查看每一条SQL的耗时基本情况
show profiles;
-- 查看指定query_id的SQL语句各个阶段的耗时情况
show profile for query query_id;
-- 查看指定query_id的SQL语句CPU的使用情况
show profile cpu for query query_id;
explain
EXPLAIN 或者 DESC命令获取 MySQL 如何执行 SELECT 语句的信息包括在 SELECT 语句执行过程中表如何连接和连接的顺序。
-- 直接在select语句之前加上关键字 explain / desc
EXPLAIN SELECT 字段列表 FROM 表名 WHERE 条件 ;
Explain 执行计划中各个字段的含义:
id
select查询的序列号表示查询中执行select子句或者是操作表的顺序(id相同执行顺序从上到下id不同值越大越先执行)。
select_type
表示 SELECT 的类型常见的取值有 SIMPLE简单表即不使用表连接或者子查询、PRIMARY主查询即外层的查询、UNIONUNION 中的第二个或者后面的查询语句、SUBQUERYSELECT/WHERE之后包含了子查询等
type
表示连接类型性能由好到差的连接类型为NULL、system、const、eq_ref、ref、range、 index、all 。
possible_key
显示可能应用在这张表上的索引一个或多个。
key
实际使用的索引如果为NULL则没有使用索引。
key_len
表示索引中使用的字节数 该值为索引字段最大可能长度并非实际使用长度在不损失精确性的前提下 长度越短越好 。
rows
MySQL认为必须要执行查询的行数在innodb引擎的表中是一个估计值可能并不总是准确的。
filtered
表示返回结果的行数占需读取行数的百分比 filtered 的值越大越好。
索引使用
最左前缀法则
如果索引关联了多列联合索引要遵守最左前缀法则最左前缀法则指的是查询从索引的最左列开始并且不跳过索引中的列。如果跳跃某一列索引将部分失效后面的字段索引失效。
范围查询
联合索引中出现范围查询(>,<)范围查询右侧的列索引失效。所以在业务允许的情况下尽可能的使用类似于 >= 或 <= 这类的范围查询而避免使用 > 或 <
索引失效情况
索引列运算
不要在索引列上进行运算操作 索引将失效
字符串不加引号
字符串类型字段使用时不加引号索引将失效
模糊查询
如果仅仅是尾部模糊匹配索引不会失效。如果是头部模糊匹配索引失效
or连接条件
用or分割开的条件 如果or前的条件中的列有索引而后面的列中没有索引那么涉及的索引都不会被用到
数据分布影响
如果MySQL评估使用索引比全表更慢则不使用索引
SQL提示
当我们在查询的时候自己要指定使用哪个索引时此时就可以借助于MySQL的SQL提示来完成。
SQL提示是优化数据库的一个重要手段简单来说就是在SQL语句中加入一些人为的提示来达到优化操作的目的。
use index
建议MySQL使用哪一个索引完成此次查询仅仅是建议mysql内部还会再次进行评估。
ignore index
忽略指定的索引。
force index
强制使用索引。
覆盖索引
尽量使用覆盖索引减少select *。覆盖索引是指查询使用了索引并且需要返回的列在该索引中已经全部能够找到 。
当返回列没在索引里就需要拿到主键id再去扫描聚集索引再获取额外的数据了这个过程就是回表。 而我们如果一直使用select * 查询返回所有字段值很容易就会造成回表查询除非是根据主键查询此时只会扫描聚集索引。
前缀索引
当字段类型为字符串varchartextlongtext等时有时候需要索引很长的字符串这会让索引变得很大查询时浪费大量的磁盘IO 影响查询效率。此时可以只将字符串的一部分前缀建立索引这样可以大大节约索引空间从而提高索引效率。
create index idx_xxxx on table_name(column(n));
单列索引与联合索引
单列索引即一个索引只包含单个列。
联合索引即一个索引包含了多个列。
在业务场景中如果存在多个查询条件考虑针对于查询字段建立索引时建议建立联合索引而非单列索引。
索引设计原则
针对于数据量较大且查询比较频繁的表建立索引。
针对于常作为查询条件where、排序order by、分组group by操作的字段建立索引。
尽量选择区分度高的列作为索引尽量建立唯一索引区分度越高使用索引的效率越高。
如果是字符串类型的字段字段的长度较长可以针对于字段的特点建立前缀索引。
尽量使用联合索引减少单列索引查询时联合索引很多时候可以覆盖索引节省存储空间避免回表提高查询效率。
要控制索引的数量索引并不是多多益善索引越多维护索引结构的代价也就越大会影响增删改的效率。
如果索引列不能存储NULL值请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时它可以更好地确定哪个索引最有效地用于查询。