前言:在工作过程中,本人在处理天眼查数据时遇到了不少慢SQL的问题。此外,也结合同事工作中遇到的问题,在如何优化大数量查询时积累了一点点经验,做一些整理,不足之处,希望一起探讨改进。
(1)设置开启:SET GLOBAL slow_query_log = 1; #默认未开启,开启会影响性能,mysql重启会失效
(2)查看是否开启:SHOW VARIABLES LIKE '%slow_query_log%';
(3)设置阈值:SET GLOBAL long_query_time=3;
(4)查看阈值:SHOW 【GLOBAL】 VARIABLES LIKE 'long_query_time%'; #重连或新开一个会话才能看到修改值
(5)通过修改配置文件my.cnf永久生效,在[mysqld]下配置:
[mysqld]
slow_query_log = 1; #开启
slow_query_log_file=/var/lib/mysql/atguigu-slow.log #慢日志地址,缺省文件名host_name-slow.log
long_query_time=3; #运行时间超过该值的SQL会被记录,默认值>10
log_output=FILE
错误示例
<if test="begin != null and begin != '' and end != null and end != ''" >
t.`year_month` between #{begin,jdbcType=VARCHAR} AND #{end,jdbcType=VARCHAR}
</if>
<if test="mobileNumber != null and mobileNumber != ''">
AND mobile_number = #{mobileNumber,jdbcType=VARCHAR}
</if>
正确示例
<if test="mobileNumber != null and mobileNumber != ''">
mobile_number = #{mobileNumber,jdbcType=VARCHAR}
</if>
<if test="begin != null and begin != '' and end != null and end != ''" >
AND (t.`year_month` between #{begin,jdbcType=VARCHAR} AND #{end,jdbcType=VARCHAR})
</if>
全文索引建立方式:MySQL版本应在5.6及以上
CREATE FULLTEXT INDEX ft_email_name ON `student` (`name`)
全文索引使用方式:
SELECT * FROM `student` WHERE MATCH(`name`) AGAINST('聪')
网上经常能看到一些文章总结在 mysql 中不能命中索引的各种情况,其中有一种说法就是指使用了 or 的语句都不能命中索引。
这种说法其实是不够正确的,正确的结论应该是,从 mysql5.0 后,如果在 or 连接的字段上都有独立的索引的话,是可以命中索引的,这里就是用到了 index_merge 特性。
在 mysql5.0 版本以前一条 sql 只能选择使用一个索引,而且如果 sql 中使用了 or 关键字,那么已有的索引就会失效,会走全表扫描。因为无论走哪个索引,mysql 都不能一次性查找出符合条件的数据,所以只能放弃索引。
索引最左前缀(多列索引)遇到范围查询后,后面的字段不走索引。如果每列都建立索引,范围查询后的索引字段也是可以生效的。
比如,你查询的是SELECT * FROM T WHERE Y=XXX;假如你的T表上有一个包含Y值的组合索引,但是优化器会认为需要一行行的扫描会更有效,这个时候,优化器可能会选择TABLE ACCESS FULL,但是如果换成了SELECT Y FROM T WHERE Y = XXX,优化器会直接去索引中找到Y的值,因为从B树中就可以找到相应的值。
explain命令用来查看一个SQL语句的执行计划,查看该SQL语句有没有使用上索引,有没有做全表扫描。expain出来的信息有10列,分别是
id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra
常用的类型有: ALL, index, range, ref, eq_ref, const, system, NULL(从左到右,性能从差到好)
ALL
Full Table Scan, MySQL将遍历全表以找到匹配的行
range
只检索给定范围的行,使用一个索引来选择行
const、system
当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的情况下,使用system
如果该列是NULL,则没有相关的索引。如果是这样,创造一个适当的索引并且再次用EXPLAIN检查查询
key列显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL。
表示MySQL根据表统计信息及索引选用情况,估算找到所需的记录所需要读取的行数