专题描述:修改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', '00000000-X755DCALENOVO201505300031LENOVO15060212405482ERP订单类型2015-06-02 14:18:23订单状态预留字段预留字段预留字段预留字段预留字段预留字段预留字段预留字段行号商品编码5000050002015-06-022015-06-22 14:18:23库存状态LQY_00012015-06-02 14:18:23批号属性1批号属性2批号属性3批号属性4批号属性5批号属性6预留字段预留字段预留字段预留字段预留字段预留字段预留字段预留字段ser00001', 14, 1, 0, '0', 0, '2015-06-20 17:15:39.471', 'push', '2015-06-20 17:15:39.471', 'push', 1419);

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语句性能。