[英]Mysql not using right index
我有一個生成SQL的框架。 查詢之一正在使用我的索引“ A”,並在7秒內返回結果。 我看到可以對其進行優化,並創建了索引“ B”。
現在,如果我運行“解釋我的查詢”,它仍然使用我的索引A。但是,如果我強制使用索引B,則我將在1秒內得到結果(快7倍)
因此很明顯我的索引B比我的索引A快。我無法使用“強制索引”或“使用索引”命令,因為我的sql是從不支持此功能的框架生成的。
因此,為什么mysql不自然地使用最快的索引。 並且有一種方法可以告訴mysql始終使用特定索引,而無需添加“ use”或“ force”。
查詢:
SELECT *
FROM soumission
LEFT OUTER JOIN region_administrative
ON soumission.region_administrative_oid=region_administrative.oid
WHERE (soumission.statut=2
AND ((soumission.telephone LIKE '%007195155134070067132211046052045128049212213255%'
OR (soumission.autre_telephone LIKE '%007195155134070067132211046052045128049212213255%'))
OR (soumission.cellulaire LIKE '%007195155134070067132211046052045128049212213255%')))
ORDER BY soumission.date_confirmation DESC, soumission.numero;
我在“ statut”,“ telephone”,“ autre_telephone”,“ cellulaire”多列上添加了索引
如果我強制使用該索引,我的查詢速度會提高7倍,但是如果我未指定要使用的索引,它將使用另一個索引(僅在狀態字段上),速度會慢7倍
這是我選擇較大日期范圍(使用錯誤的索引)的說明
這似乎是您在做什么...
SELECT s.*, ra.*
FROM soumission AS s
LEFT OUTER JOIN region_administrative AS ra ON s.region_administrative_oid=ra.oid
WHERE s.statut = 2
AND ( s.telephone LIKE '%007195155134070067132211046052045128049212213255%'
OR s.autre_telephone LIKE '%007195155134070067132211046052045128049212213255%'
OR s.cellulaire LIKE '%007195155134070067132211046052045128049212213255%'
)
ORDER BY s.date_confirmation DESC, s.numero;
如果您不需要ra.*
,請擺脫LEFT JOIN
。
您建議的多列索引是無用的,除非... statut = 2
(少於20%的行),否則將不會使用該索引。 在這種情況下,它將僅使用索引的第一列。
OR
打敗索引。 (見下文)
LIKE
通配符領先於索引。 您是否需要前導或尾隨通配符?
DESC
和ASC
在ORDER BY
的混合使用索引以避免排序失敗。
那么該怎么辦? 而不是用3列來表示正好3個電話號碼,而是使用另一個表來顯示電話號碼。 然后,對於給定的解決方案,可以有任意數量的行。 然后,由於避免使用OR
因此搜索該表可能會更快-但前提是您必須擺脫前導通配符。
(這是一個非常長的電話號碼!是真的嗎?)
至於查詢本身:
因此,創建以下索引:
ALTER TABLE `region_administrative` ADD INDEX `region_administrativ_idx_oid` (`oid`);
ALTER TABLE `soumission` ADD INDEX `soumission_idx_statut_oid_cellulaire` (`statut`,`region_administrative_oid`,`cellulaire`);
ALTER TABLE `soumission` ADD INDEX `soumission_idx_statut_oid_telephone` (`statut`,`region_administrative_oid`,`autre_telephone`);
ALTER TABLE `soumission` ADD INDEX `soumission_idx_statut_oid_telephone` (`statut`,`region_administrative_oid`,`telephone`);
然后嘗試以下查詢:
SELECT
*
FROM
((SELECT
*
FROM
soumission
LEFT OUTER JOIN
region_administrative
ON soumission.region_administrative_oid = region_administrative.oid
WHERE
(
soumission.statut = 2
AND (
(
soumission.cellulaire LIKE '007195155134070067132211046052045128049212213255%'
)
)
)
ORDER BY
soumission.date_confirmation DESC,
soumission.numero)
UNION
DISTINCT (SELECT
*
FROM
soumission
LEFT OUTER JOIN
region_administrative
ON soumission.region_administrative_oid = region_administrative.oid
WHERE
(soumission.statut = 2
AND (((soumission.autre_telephone LIKE '007195155134070067132211046052045128049212213255%'))))
ORDER BY
soumission.date_confirmation DESC,
soumission.numero)
UNION
DISTINCT (SELECT
*
FROM
soumission
LEFT OUTER JOIN
region_administrative
ON soumission.region_administrative_oid = region_administrative.oid
WHERE
(soumission.statut = 2
AND ((soumission.telephone LIKE '007195155134070067132211046052045128049212213255%')))
ORDER BY
soumission.date_confirmation DESC,
soumission.numero)
) AS union1
ORDER BY
union1.date_confirmation DESC,
union1.numero
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.