Mysql не использует правильный индекс

0

У меня есть структура, которая генерирует SQL. один из запросов использует мой индекс "А" и возвращает результаты за 7 секунд. Я вижу, что я могу оптимизировать это, и я создал индекс "B".

теперь, если я запустил "объяснить мой запрос", он все равно использует мой индекс A. Однако, если я заставляю использовать индекс B, я получаю свои результаты за 1 секунду (7 раз быстрее)

поэтому мой индекс B быстрее, чем мой индекс A. Я не могу использовать команду "индекс силы" или "использовать индекс", поскольку мой sql генерируется из фреймворка, который этого не поддерживает.

Итак, почему mysql естественно не использует самый быстрый индекс. И есть способ, которым я могу сказать, что mysql всегда использует определенный индекс без добавления "использования" или "силы".

запрос:

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", "phone", "autre_telephone", "cellulaire"

если я использую этот индекс, мой запрос будет 7 раз быстрее, но если я не укажу, какой индекс использовать, он использует другой индекс (только в поле statut), который на 7x медленнее

вот объяснение, если я выбираю большой период времени (используя неправильный индекс)

Изображение 174551

здесь, когда я выбираю небольшое окно даты Изображение 174551

  • 0
    Невозможно ответить на вопрос об оптимизации и использовании индекса, не зная структуру таблицы и обсуждаемый запрос.
  • 0
    Я добавил подробный запрос
Показать ещё 3 комментария
Теги:
indexing

2 ответа

0

Что касается самого запроса:

  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
0

Кажется, это то, что вы делаете...

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 телефонных номеров, у вас есть другая таблица для телефонных номеров. Затем у вас есть любое количество строк для данного приема. Тогда поиск этой таблицы может быть более быстрым из-за исключения OR - но только если вы избавитесь от основной подстановки.

(Это ужасно длинный номер телефона! Это правда?)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню