划重点:
建表时考虑怎么查询,给必要的字段创建索引可以提升查询效率,减小加锁的范围,降低加锁的时间
使用explain解释sql语句可以查看是否使用了索引
索引不仅仅为了提高查询速度,使用索引避免全表锁可以提高查询、更新操作的效率
最近一段时间涉及的ES的查询任务都变的异常慢,很多定时任务都比原来多出几个小时的执行时间。一直在排查ES的问题,但是没有找到哪个新增的操作会导致ES性能下降。由于有一台服务器部署了2个ES节点和一个mysql,这台服务器的负荷一直以来都比较高,当看到这台服务器高负荷时并没有终点关注。后来,使用top命令查看进程时,发现mysql占用了800%的cpu时间,意识到是mysql的哪个操作出现问题了。排查步骤如下:
- show porcesslist
使用show porcesslist
,看看有没有长时间执行的任务。发现有好几条查询语句处于sending data
状态持续了2000多秒,第一反应就是这个表没有索引。一查表结构果然如此,分析一下查询语句添加索引吧。
问题又来了,添加索引的语句执行了半天没有反应,show porcesslist
发现语句正在获取锁。无奈至下把关于这个表的所有任务都kill掉,然后再创建索引,然后成功了,添加索引后原来执行30分钟的任务只需要5秒。
回过头来再分析一下原因,我挑了设计改表的2个sql语句,如下:
UPDATE
`iptv_alarm`
SET
olt_ip = '{ip}'
WHERE dev_code = '{code}'
AND olt_ip is NULL
SELECT
*
FROM
`iptv_alarm` A
WHERE eventtime =
(SELECT
MAX(eventtime)
FROM
`iptv_alarm` B
WHERE A.dev_code = B.dev_code
AND A.clearancereportflag = 0
AND A.dev_type = 2
AND gte_five = 0
AND rk_time > '{start_time}'
AND rk_time <= '{end_time}'
AND dev_code IN ({olt_list})) ;
上面一个是更新语句,下面一个是查询语句。由于没有索引,每次查询时创建共享锁(表锁),每次更新时创建排它锁(表锁)。由于两个语句执行都比较频繁,mysql就疲于申请锁、加锁、释放锁之间,cpu都被它吃了。再看添加索引后,我新增了rk_time,dev_code两个字段的索引,实际查询时只使用了dev_code
的索引。有了索引之后,查询和更新语句都可以申请行锁,而不用对整个表加锁,另外查询效率也快了,整体效率自然提升上去了。
另外,整个表只有3万条数据,数据量并不大。所以无论数据量大小,建表时一定要考虑好整个表要怎么使用,创建必要的索引。
推荐阅读:
网友评论