多列上的MySQL索引

3

我有一个查询语句,需要包含以下列(几乎是表中的所有列):

SELECT  ANI,CALL_ID, DATE_TIME, ABANDON_RATE, CALL_TYPE, CAMPAIGN, CAMPAIGN_TYPE, CUSTOMER_NAME, DISPOSITION, DNIS, LIST_NAME, 
        SESSION_ID, SKILL, AGENT_EMAIL, AGENT_GROUP, THIRD_PARTY_TALK_TIME, AFTER_CALL_WORK_TIME, HOLD_TIME, CALL_TIME, HANDLE_TIME, IVR_TIME,
        MANUAL_TIME, TALK_TIME, QUEUE_WAIT_TIME, advertiserName, affiliateName, callerID, campaignName, ChargentSFA__Biling_Phone__c, CONTACT_CREATE_TIMESTAMP,
        CONTACT_ID, CONTACT_MODIFIED_TIMESTAMP, Date_Added, destinationPhoneNumber, leadsource, number1, salesforce_id, source, transactionID,
        IVR_PATH 
FROM call_data_report 
WHERE ANI= '123456' OR DNIS = '123456' 
ORDER BY DATE_TIME desc;

这个查询执行时间太长了(超过3分钟)。为了提高查询性能,我已经在where子句中使用的列ANI和DNIS上创建了索引。

create index ani_idx on call_data_report(ANI,DNIS)

但是,当我检查上述选择查询的EXPLAIN输出时,它显示它没有使用索引。这是因为所有这些列吗?我需要创建什么类型的索引来改善以上查询的性能。

注意:ANI和DNIS在列中具有NULL值。

谢谢!

2个回答

7

当你使用 AND 联合测试时,组合索引才有用,而不是 OR。当存在 OR 条件时,必须独立测试每列,但组合索引是一个树形结构,其中包含所有相关的 ANI 内的 DNIS 值。因此,您应该为每一列创建单独的索引。

MySQL 通常不擅长优化 OR 查询。如果将其拆分成两个查询,并使用 UNION 组合,则可能效果更好:

SELECT ...
FROM call_data_report
WHERE ANI = 123456
UNION
SELECT ...
FROM call_data_report
WHERE DNIS = 123456

嗨@Barmar,感谢您关于查询优化的信息。我已经在ANI和DNIS上创建了两个单独的索引。但是,当我执行EXPLAIN SELECT ... FROM call_data_report WHERE ANI=12345时,它给出以下输出。id | select_type | table | type | possible_keys | keys | key_len | ref | rows | Extra =>1 | SIMPLE | call_data_report | ALL | ani_idx | NULL | NULL | NULL | 2995289|Using where这是否意味着它仍然没有使用索引? - Subhash Deshmukh
这就是它的意思。我不知道为什么它没有使用索引。 - Barmar
如果这两个字段是varchar类型,是否会有任何问题? - Subhash Deshmukh
如果是varchar类型,请尝试引用该值:WHERE ANI = '12345' - Barmar
我想我错过了引号部分。谢谢。解释输出表明它现在正在使用索引。 - Subhash Deshmukh

1
在你的情况下,你可以尝试使用两个单列索引..
create index ani_idx1 on call_data_report(ANI);

create index ani_idx2 on call_data_report(DNIS); 

因为未使用您的复合索引ani_idx的第二个键DNIS..


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接