Как определить столбцы, которые лучше всего подходят для индексации - PullRequest
0 голосов
/ 26 июня 2018

Я много читал об идентификации столбцов, которые могут быть лучшим кандидатом для создания индексов. Однако большинство из них советуют создавать индексы для столбцов, которые используются в предложении JOIN или WHERE.

Тем не менее, я не уверен, что для сложных запросов, как показано ниже

select b.col1 ,a.col1 ,a.selectionId ,a.table2Id ,a.selectionName ,b.UserId,b.ParantId ,
a.teamType ,d.Name,b.isBack,b.SelectionId,b.Admin AS admin,
b.Master AS master,c.MstDate AS MstDate, c.col2 
from  tblselection a 
       join  table1 c on c.col1 = a.col1 
       join  table2 d on d.Id = a.table2Id 
        left join  tabletest b on b.SelectionId = a.selectionId and a.table2Id = b.table2Id and b.IsMatched = 1
       where ((ifnull(c.active,0) = 1) and isnull(b.Result) and isnull(b.ResultID)) 

Какие столбцы являются наилучшим кандидатом для индексации во всех 4 таблицах для этого запроса?

Стоит ли создавать здесь составные или отдельные индексы?

Ответы [ 3 ]

0 голосов
/ 26 июня 2018

По сути, вы хотите начать с индексируемых столбцов в предложении where. У вас их нет (из-за вызовов функций). Итак, начните со столбцов join:

from tblselection a join
     table1 c
     on c.col1 = a.col1 join
     table2 d
     on d.Id = a.table2Id left join
     tabletest 
     on b.SelectionId = a.selectionId and a.table2Id = b.table2Id and b.IsMatched = 1

Я бы начал с table1(col1), table2(id) и tabletest(SelectionId, table2Id, IsMatched).

0 голосов
/ 27 июня 2018

Сначала измените

    where  ((ifnull(c.active,0) = 1)
              and  isnull(b.Result)
              and  isnull(b.ResultID))

до

    WHERE c.active = 1
      AND b.Result IS NULL
      AND b.ResultID IS NULL

Я сомневаюсь, что Оптимизатор хорошо справляется с IFNULL().

Пожалуйста, укажите SHOW CREATE TABLE и EXPLAIN SELECT...

Теперь вы, вероятно, увидите, что c - это первая таблица в EXPLAIN. Давайте поможем оптимизатору, предоставив

c:  INDEX(active, col1)  -- in that order

После этого

a:  INDEX(col1)
d:  INDEX(Id)  -- unless it is already PRIMARY KEY(Id)
b:  INDEX(IsMatched, table2Id, SelectionId)  -- in any order

При работе с JOIN вам необходимо выяснить, в каком порядке будут просматриваться таблицы. Не доверяйте EXPLAIN, потому что он (изначально) не знает, какие индексы вы собираетесь добавить.

В вашем случае WHERE ссылаются на c и b. Но b - это LEFT JOIN, поэтому мы не можем его использовать. Это оставляет c. Единственный полезный столбец для индекса - это active (после переформулирования). Но это звучит как простой, малозначительный «флаг», который Оптимизатор будет избегать. Я добавил что-то в индекс в надежде, что оптимизатор будет обманут.

Итак, какой будет «следующая» таблица? JOINs получают от c только до a. Так что a следующий. И JOIN использует col1.

Далее может быть либо d, либо b. Похоже, что "Оптимизатор мог бы делать их в любом порядке и оптимизировать все одинаково независимо от порядка.

d: Id это как добраться до него.

b нужно 3 вещи в ON, чтобы проверить с помощью простого AND. Таким образом, «составной» индекс этих 3 столбцов, в любом порядке. (Нет, «кардинальность» каждого столбца не имеет значения, даже для выбора заказа.)

Что касается тестов b... IS NULL в предложении WHERE - они, по-видимому, проверяют, не нашел ли LEFT строку. (Обычно проверяется только PK, поэтому я не знаю, проверяете ли вы также что-то еще.)

Еще одна оптимизация ... Иногда полезно построить индекс "покрытия". Это INDEX, который содержит все столбцы (для таблицы), упомянутые в любом месте в SELECT. Это не кажется практичным, поскольку в каждом из 4 случаев будет задействовано множество столбцов.

0 голосов
/ 26 июня 2018

Запустите ваш запрос с ключевым словом EXPLAIN перед ним (EXPLAIN SELECT b.cl1, a.col1 ...). MySQL даст вам представление о том, как вещи объединяются и сколько строк он просматривает, чтобы выяснить это.

Как правило, вам нужны индексы для столбцов, на которые ссылаются, особенно если им нужно просмотреть много строк или если для их объединения используется "Table-scan". Вы хотите сказать «используя основной» или «используя индекс»

Вот некоторые примеры вывода из одной из моих баз данных. Вы можете видеть, что этот запрос объединяет 3 таблицы, но в итоге находит то, что ему нужно, очень быстро, хотя таблицы довольно большие. Каждая часть должна ссылаться только на одну строку:

+----+-------------+-------+------------+--------+---------------------+---------+---------+-------------------------------+------+----------+-------------+
| id | select_type | table | partitions | type   | possible_keys       | key     | key_len | ref                           | rows | filtered | Extra       |
+----+-------------+-------+------------+--------+---------------------+---------+---------+-------------------------------+------+----------+-------------+
|  1 | SIMPLE      | sa    | NULL       | ref    | choice_id,user_id   | user_id | 5       | const                         |    1 |   100.00 | Using where |
|  1 | SIMPLE      | qc    | NULL       | eq_ref | PRIMARY,question_id | PRIMARY | 4       | sa.choice_id                  |    1 |   100.00 | Using where |
|  1 | SIMPLE      | q     | NULL       | eq_ref | PRIMARY             | PRIMARY | 4       | qc.question_id                |    1 |   100.00 | NULL        |
+----+-------------+-------+------------+--------+---------------------+---------+---------+-------------------------------+------+----------+-------------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...