- 开发无止境 -
Data: 2018-10-21 12:54:55Form: JournalClick: 9
近来有个一情况非常奇怪 查询limit 10 竟然非常慢,而且都where中的两个字段和order by 的一个字段都有索引, 这个表有1200W的数据,update比较多,但压力还OK,
profiles 查看使用的时间
profile 能查看到 执行中的时间长短
select t.* from t_user t where 1=1
and t.channel= 'scb_weixin'
order by t.update_time DESC limit 10 ;
结果:
169 0.00231675 SHOW STATUS
170 0.00251925 SELECT QUERY_ID, SUM(DURATION) AS SUM_DURATION FROM INFORMATION_SCHEMA.PROFILING GROUP BY QUERY_ID
171 0.00085025 SELECT STATE AS `状态`, ROUND(SUM(DURATION),7) AS `期间`, CONCAT(ROUND(SUM(DURATION)/0.001298*100,3), '%') AS `百分比` FROM INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID=168 GROUP BY STATE ORDER BY SEQ
172 0.000857 SELECT * FROM `t_pdb`.`t_user` LIMIT 0
173 0.00316375 SHOW COLUMNS FROM `t_pdb`.`t_user`
show PROFILE for QUERY <从上面一个语句中找到,如 172>
checking permissions 6.7E-5
Creating sort index 33.105645
logging slow query 0.000112
show status 查看
select t.* from t_user t where 1=1
and t.channel= 'scb_weixin'
order by t.update_time DESC limit 10 ;
show status where variable_name like 'handler%' or variable_name like 'created%';
结果:
Created_tmp_disk_tables 0
Handler_read_next 15239952
Handler_savepoint_rollback 0
上面的几个count很大,网上找了下,应该是和order有关
执行计划
select t.* from t_user t where 1=1
and t.channel= 'scb_weixin'
order by t.update_time DESC limit 10 ;
结果:
1 SIMPLE t index_merge idx_channel,idx_logintype idx_channel,idx_logintype 99,99 3083430 100 Using intersect(idx_channel,idx_logintype); Using where; Using filesort
1
情况分析,
时间都花费在 Creating sort index,这是和order有关的语句,
把order 给去掉,或者order by id desc 则还是很快,说明貌似是 和update_time有关
解决办法:
一,修改mysql的部分参数:
myisam_max_sort_file_size=100G
myisam_sort_buffer_size=175M
下面是参数详解
如果 Qcache_hits 的值非常大,则表明查询缓冲使用非常频繁,如果该值较小反而会影响效率,那么可以考虑不用查询缓冲; Qcache_free_blocks,如果该值非常大,则表明缓冲区中碎片很多。
memlock
紧张的时候,数据在内存中保持锁定并且防止可能被 swapping out,此选项对于性能有益
这不会有明显的性能提升.)服务器线程缓存这个值表示可以重新利用保存在缓存中线程的数量,当断开连接时如果缓存中还有空间,那么客户端的线程将被放到缓存中,如果线程重新被请求,那么请求将从缓存中读取,如果缓存中是空的或者是新的请求,那么这个线程将被重新创建,
如果有很多新的线程,增加这个值可以改善系统性能.通过比较 Connections 和 Threads_created 状态的变量,可以看到这个变量的作用
myisam_max_sort_file_size=100G
重建索引时允许使用的临时文件最大大小(myisam_max_sort_file_size)
myisam_sort_buffer_size=175M
MyISAM 设置恢复表之时使用的缓冲区的尺寸,当在REPAIR TABLE 或用 CREATE INDEX 创建索引或 ALTER TABLE 过程中排序 MyISAM 索引分配的缓冲区(myisam_sort_buffer_size)
read_rnd_buffer_size = 8M
mysql配置对应,这一步修改配置 打开 https://blog.csdn.net/qq_27229113/article/details/91866071
二,增加order by 的参数的 where xxx is not null
select t.* from t_user t where 1=1
and t.channel= 'scb_weixin'
and t.update_time is not null
order by t.update_time DESC limit 10 ;
附录
表结构
`id` int(11) NOT NULL AUTO_INCREMENT,
`scb_user_id` varchar(256) DEFAULT NULL COMMENT '',
UNIQUE KEY `ukey_login_name_type` (`login_name`,`logintype`,`channel`),
KEY `idx_device_guid` (`device_guid`),
KEY `idx_update_time` (`update_time`),
KEY `idx_channel` (`channel`),
KEY `idx_logintype` (`logintype`),
KEY `idx_scb_user_id` (`scb_user_id`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB AUTO_INCREMENT=12915154 DEFAULT CHARSET=utf8;
结尾记录下,复制大佬的,添加自己的,保证自己每一篇博客都测试过,原文地址:https://blog.csdn.net/mingover/article/details/79066064#commentsedit