簡體   English   中英

MySQL不使用正確的索引

[英]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倍

這是我選擇較大日期范圍(使用錯誤的索引)的說明

看到它可以使用ix_statut_date_confirmation2,但它沒有

這是當我選擇一個小的日期窗口時 看到它使用正確的索引“ ix_statut_date_confirmation_2”

這似乎是您在做什么...

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通配符領先於索引。 您是否需要前導或尾隨通配符?

DESCASCORDER BY的混合使用索引以避免排序失敗。

那么該怎么辦? 而不是用3列來表示正好3個電話號碼,而是使用另一個表來顯示電話號碼。 然后,對於給定的解決方案,可以有任意數量的行。 然后,由於避免使用OR因此搜索該表可能會更快-但前提是您必須擺脫前導通配符。

(這是一個非常長的電話號碼!是真的嗎?)

至於查詢本身:

  1. 盡量避免使用前導LIKE通配符(在下面的查詢中已刪除)。
  2. 將查詢分為幾個部分,並結合UNION子句,以便可以使用索引。

因此,創建以下索引:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM