专题描述:修改OMS系统之push_tb_wait_send_data表的索引提高SQL性能
问题提出:通过慢查询日志抓取慢查询SQL。
分析过程:
1慢查询日志显示下列SQL执行时间较长:
2[SQL1]
Count: 5506 Time=0.58s (3200s) Lock=0.00s (0s) Rows=0.0 (0), oms1[oms1]@3hosts
insert into push_tb_wait_send_data
(INT_CODE, DATA_ID, DATA_FROM, COMPANY_CODE, BUSINESS_DATA, SEND_CONFIG_ID, SEND_STATUS, SEND_COUNT, SERVER_ID, IF_ORDER, CREATE_TM, CREATE_EMP, UPDATE_TM, UPDATE_EMP, XML_SRC_LENGTH)
values ('S', N, 'S', 'S', 'S', N, N, N, 'S', N, 'S', 'S', 'S', 'S', N)
[Example]
# Query_time: 0.528362 Lock_time: 0.000198 Rows_sent: 0 Rows_examined: 0
insert into push_tb_wait_send_data
(INT_CODE, DATA_ID, DATA_FROM, COMPANY_CODE, BUSINESS_DATA, SEND_CONFIG_ID, SEND_STATUS, SEND_COUNT, SERVER_ID, IF_ORDER, CREATE_TM, CREATE_EMP, UPDATE_TM, UPDATE_EMP, XML_SRC_LENGTH)
values ('PURCHASE_ORDER_INBOUND_PUSH_SERVICE', ×××, 'wom_tb_receipt_push', 'HF002', '
3[SQL2]
Count: 189 Time=4.27s (806s) Lock=0.49s (93s) Rows=0.0 (0), oms1[oms1]@3hosts
update push_tb_wait_send_data t set t.server_id = 'S' where t.server_id ='S' and t.if_order = N limit N
[Example]
# Query_time: 1.422388 Lock_time: 0.000063 Rows_sent: 0 Rows_examined: 10000
update push_tb_wait_send_data t set t.server_id = '10.202.26.498080' where t.server_id ='0' and t.if_order = 0 limit 5000;
4[SQL3]
Count: 187 Time=1.48s (277s) Lock=0.01s (1s) Rows=0.0 (0), oms1[oms1]@3hosts
update push_tb_wait_send_data t set t.send_status = N ,read_time = SYSDATE(), update_tm = SYSDATE() where t.id in (t.id list)
[Example]
# Query_time: 0.684818 Lock_time: 0.005607 Rows_sent: 0 Rows_examined: 22535
update push_tb_wait_send_data t set t.send_status = 2 ,read_time = SYSDATE(), update_tm = SYSDATE() where t.id in (t.id list)
5[SQL4]
Count: 2 Time=53.24s (106s) Lock=0.00s (0s) Rows=0.5 (1), oms1[oms1]@[10.118.60.148]
select count(*) from push_tb_wait_send_data
6[SQL5]
Count: 92 Time=0.95s (87s) Lock=0.00s (0s) Rows=5000.0 (460000), oms1[oms1]@3hosts
select * from push_tb_wait_send_data where ( send_status = N or ( send_status = N and read_time < 'S' )) and
send_count < N and if_order = N and server_id = 'S' and update_tm > 'S'
limit N
[Example]
select * from push_tb_wait_send_data where ( send_status = 1 or ( send_status = 4 and read_time < '2015-06-20 13:48:55.894' )) and
send_count < 5 and if_order = 0 and server_id = '10.202.26.508080' and update_tm > '2015-06-13 13:49:55.894'
limit 5000;
问题原因 :索引设置不合理,具体修改原因见下文“解决方案”
解决方案
1建议删除idx_wait_send_data_3:
原因:
KEY `idx_wait_send_data_3` (`server_id`) USING BTREE,
KEY `idx_wait_send_data_4` (`server_id`,`main_id`,`if_order`) USING BTREE,
两个索引server_id列重叠,故建议删除idx_wait_send_data_3,SQL语句:
ALTER TABLE push_tb_wait_send_data DROP INDEX idx_wait_send_data_3;
2建议删除KEY `idx_wait_send_data_1` (`company_code`) USING BTREE,
原因:
KEY `idx_wait_send_data_1` (`company_code`) USING BTREE,
KEY `idx_wait_send_data_2` (`company_code`,`send_status`,`server_id`) USING BTREE,
idx_wait_send_data_1为idx_wait_send_data_2的最左前缀,且idx_wait_send_data_1不作为约束存在,故建议删除idx_wait_send_data_1,SQL语句:
ALTER TABLE push_tb_wait_send_data DROP INDEX idx_wait_send_data_1;
3对于索引KEY `idx_wait_send_data_5` (`update_tm`),当前表25206239条数据,而update_tm的基数为4160
从慢查询中没有看到基于update_tm条件的SQL语句,但是对于update push_tb_wait_send_data t set t.send_status = N ,read_time = SYSDATE(), update_tm = SYSDATE() where t.id in (t.id list)
这种查询的语句,更新的同时也会更新该索引`idx_wait_send_data_5` (`update_tm`),进而影响该语句的执行时间,请抉择是否需要该索引。
4对于KEY `idx_wait_send_data_4` (`server_id`,`main_id`,`if_order`) 通过慢查询日志的SQL语句,建议修改索引列的顺序为(server_id,if_order,main_id)使[2]、[5]语句能够走上(server_id,if_order)索引列。SQL语句为:
ALTER TABLE push_tb_wait_send_data DROP INDEX idx_wait_send_data_4;
ALTER TABLE push_tb_wait_send_data ADD INDEX idx_wait_send_data_4(server_id,if_order,main_id);
知识点
1没有使用到的索引会增加更新该列数据的SQL语句响应时间。
2联合索引中列的顺序需要和查询语句where子句中列的顺序保持一致,可以让SQL语句使用到该索引。
3当某一单列索引为另一联合索引最左前缀,且该索引不为主键和约束条件时,有SQL使用到联合索引时,删除该单列索引,提高插入修改SQL语句性能。