Составной индекс MySQL InnoDB и выбор мощности для производительности - PullRequest
0 голосов
/ 09 ноября 2019

Я хотел бы задать пару вопросов о порядке столбцов в составном индексе для движка InnoDB и об объяснении мощности и селективности, которые должны быть выполнены (и как это сделать), чтобы получить наилучшую производительность на представленном примере. .

  1. В чем разница между селективностью и кардинальностью в контексте производительности составного индекса InnoDb?
  2. Когда следует делать акцент на селективности и на кардинальности, если вы создаете составной индекс?

Так как InnoDB использует индекс B-Tree (B-Tree +), а сопоставленный индекс ищется, начиная с крайнего левого столбца, из которого составляется индекс.

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

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

Это кардинальность? и если составной индекс строится таким образом, как я описал, то является ли количество элементов высоким или низким?

Как насчет селективности? коррелируется ли это с количеством элементов?

5.Как получить лучшую селективность и количество элементов для дизайна таблицы, как показано ниже?

CREATE TABLE IF NOT EXISTS `data_list` (
  `one` varchar(64) NOT NULL,
  `two` mediumint unsigned NOT NULL,
  `three` varchar(128) NOT NULL,
  `four` datetime NOT NULL,
  `five` DECIMAL(5,2)
) ENGINE = InnoDB;

максимальные значения различного числа столбцовбудет:
one макс. 10;
two макс. 100;
three макс. 1000;
four макс. 36500;// 100 лет

вторая таблица для специальных соединений:

CREATE TEMPORARY TABLE IF NOT EXISTS `three_list` (
    `l_three` varchar(128) PRIMARY KEY NOT NULL
) ENGINE = InnoDB;

Запросы, которые будут выдаваться:

(A) Запрос для конкретного one, two, three, four

SELECT *
FROM 
    `data_list`
WHERE 
    `one` = 'abc'
AND    
    `two` = 1
AND    
    `three` = 'xyz'
AND    
    `four` = '2018-01-01'
;

(B) Запрос для конкретных one, two, three и диапазона four

SELECT *
FROM 
    `data_list`
WHERE 
    `one` = 'abc'
AND    
    `two` = 1
AND    
    `three` = 'xyz'
AND    
    `four` >= '2018-01-01'
AND
    `four` < '2019-01-01'
ORDER BY
    `two`,
    `three`,
    `four`
;

(C) Запрос для конкретного one, two и любого three в пределах диапазона four

SELECT *
FROM 
    `data_list`
WHERE 
    `one` = 'abc'
AND    
    `two` = 1
AND    
    `four` >= '2018-01-01'
AND
    `four` < '2019-01-01'
ORDER BY
    `two`,
    `three`,
    `four`
;

(D) Запрос с JOIN для конкретного one иtwo, three в списке three_list и four в пределах диапазона

SELECT *
FROM 
    `data_list`
INNER JOIN 
    `three_list`
ON 
    `three` = `l_three`
WHERE 
    `one` = 'abc'
AND    
    `two` = 1
AND    
    `four` >= '2018-01-01'
AND
    `four` < '2019-01-01'
ORDER BY
    `two`,
    `three`,
    `four`
;

Возможно, вся конструкция таблицы имеет недостатки с самого начала (т. Е. Из-за отсутствия PK id с auto_increment для data_list). Этот вопрос касается кардинальности и избирательности для лучшей производительности составного индекса, однако приветствуется альтернативный дизайн таблицы в случае, если нет хорошего выбора порядка столбцов для запросов, как указано выше.

Самая важная производительность для менядля операторов SELECT. Вставки будут редкими (один раз в день), а ОБНОВЛЕНИЕ, УДАЛЕНИЕ не понадобятся.

Строки должны быть уникальными в data_list Я имею в виду комбинацию one, two,three, four значения столбцов.

1 Ответ

0 голосов
/ 10 ноября 2019

Количество элементов и селективность отдельных столбцов не имеют значения в составном индексе.

Думайте о значениях в индексе InnoDB BTree как о конкатенации указанногоcolumns.

Заполните индекс столбцами примерно в следующем порядке:

  1. Столбцы проверены с помощью '=', даже если это "флаг".
  2. IN(const, ...) - Оптимизатор может перемещаться по индексу.
  3. Один «диапазон». Дальнейшие диапазоны рассматриваться не будут.

Индекс «Покрытия» приводит к некоторым исключениям.

Ваши примеры:

(A) Запрос для конкретного,два, три, четыре:

    INDEX(one, two, three, four) -- in _any_ order

(B) Запрос на конкретное значение один, два, три и диапазон четыре

    INDEX(one, two, three,  -- put these first (=), in _any_ order
          four)             -- after the =s

также будет обрабатываться ORDER BY

(C) Запрос для конкретного одного, двух и любых трех в диапазоне четырех

    INDEX(one, two,         -- either order; including `three` would hurt
          four)             -- after the =s

Но на этот раз ORDER BY two, three, four также не может быть обработан;будет «сортировка файлов».

В качестве альтернативы (хотя маловероятно) оптимизатор может выбрать работу с ORDER BY вместо WHERE. В этом случае это оптимально:

INDEX(two, three, four)  -- in the same order as the ORDER BY.

(D) Запрос с JOIN для конкретного одного и двух, три из которых находятся в списке three_list и четыре в диапазоне

Это становится сложнее, потому чтоОптимизатор выберет, с какой таблицы начать. Обычно выбирает тот, у которого доступно больше фильтров. Вы фильтруете по одному, двум, четырем в data_list? Но совсем не на другом столе. Итак ...

data_list: INDEX(one, two,   -- either order,
                 four)       -- range
three_list;  INDEX(l_three)

Подробнее: http://mysql.rjweb.org/doc.php/index_cookbook_mysql

"нет ПК" - да, это плохо. Но это не обязательно должно быть AUTO_INCREMENT;Это запасной вариант, если у вас нет «естественного» PK, построенного из одного (или более) столбцов.

AUTO_INCREMENT не заставляет столбец быть PK. Однако у вас должно быть немного index , начинающееся со столбца AUTO_INCREMENT. Это единственное ограничение.

«альтернативный дизайн стола также приветствуется» - нам нужно понять, что на самом деле one (и т. Д.).

Если у вас есть эти 4запросы и хотят получить оптимальный набор индексов:

INDEX(one, two, three, four)
INDEX(one, two,        four)
INDEX(     two, three, four)

(другие комбинации будут работать одинаково хорошо.)

Если бы вы были более избирательны в предложении SELECT, я бы также поговорило "покрывающих" показателях.

...