Мощность индекса MySQL - производительность и эффективность хранения

Допустим, у вас есть таблица MySQL 5.0 MyISAM со 100 миллионами строк и одним индексом (отличным от первичного ключа) для двух целочисленных столбцов.

Исходя из моего, по общему признанию, плохого понимания структуры B-дерева, я считаю, что меньшее число элементов означает, что эффективность хранения индекса выше, поскольку родительских узлов меньше. В то время как более высокое число элементов означает менее эффективное хранение, но более высокую производительность чтения, потому что ему нужно перемещаться по меньшему количеству ветвей, чтобы добраться до любых данных, которые он ищет, чтобы сузить строки. для запроса.

(Примечание: под «низким» и «высоким» я не имею в виду, например, 1 миллион против 99 миллионов для таблицы из 100 миллионов строк. Я имею в виду скорее 90 миллионов против 95 миллионов)

Правильно ли я понимаю?

Смежный вопрос: как количество элементов влияет на производительность write?


person Sean    schedule 08.04.2010    source источник
comment
Я не уверен, что вы имеете в виду под кардинальностью здесь. Вы имеете в виду размер блока, используемый структурой b-tree (вероятно, b+-tree)?   -  person jemfinch    schedule 08.04.2010
comment
Кардинальность, например, количество уникальных значений. Более высокая кардинальность = больше уникальных значений.   -  person Sean    schedule 08.04.2010
comment
Например, вот сообщение, которое я нашел, в котором говорится, что более высокая кардинальность приведет к лучшей производительности чтения. Но там не так много статей, которые я могу найти об этом, и это просто какой-то случайный блог, так что я действительно не знаю. databasedesign-resource.com/mysql-tuning.html   -  person Sean    schedule 08.04.2010
comment
Также в этой статье рекомендуется использовать индексы для столбцов с более высокой кардинальностью для индекса с 1 столбцом. Мой вопрос касается индексов с несколькими столбцами, которые могут иметь разные последствия для того, что происходит за кулисами.   -  person Sean    schedule 08.04.2010


Ответы (1)


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

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

Чтобы обработать такой запрос:

SELECT  *
FROM    mytable
WHERE   indexed_col = @myvalue

, двигатель должен выполнить следующие шаги:

  1. Найдите первую запись, удовлетворяющую условию.

    Это делается путем обхода B-Tree, начиная с корневой записи.

    По страницам поиск осуществляется по B-Tree ссылкам; внутри страницы поиск выполняется с использованием бинарного поиска (если ваши ключи не сжаты, в этом случае это линейный поиск).

    Этот алгоритм одинаково эффективен как для столбцов с высокой, так и с низкой кардинальностью. Поиск первых 3 (в отличие от любых 3) в этих списках:

    1  2  3  4  5  6  7  8  9  10
    
    3  3  3  3  3  3  3  3  4  4
    

    требует тех же O(log(n)) шагов.

  2. Обход индекса до тех пор, пока значение ключа не изменится. Это, конечно, требует линейного времени: чем больше у вас записей, тем больше вам нужно пройти.

Если вам нужна только первая запись:

SELECT  *
FROM    mytable
WHERE   indexed_col = @myvalue
LIMIT 1

, мощность столбца не влияет на производительность чтения.

Как кардинальность влияет на производительность записи?

Каждый ключ индекса имеет скрытое дополнительное значение: указатель записи. В этом весь смысл наличия индекса: вам нужно знать, на какую запись он указывает.

Поскольку указатель записи по определению уникален, каждый ключ индекса также уникален. Записи индекса, имеющие одно и то же значение ключа, сортируются по указателю записи.

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

Каждый ключ индекса на самом деле уникален (даже если вы не определяете индекс как уникальный) и, следовательно, имеет максимально возможную мощность.

Итак, ответ на ваши вопросы: нет, мощность столбца не влияет на производительность записи индекса.

person Quassnoi    schedule 08.04.2010
comment
Спасибо за очень подробный ответ. Мой вопрос был связан с индексами с несколькими столбцами, но ваши примеры относятся к индексам с одним столбцом. Это что-то меняет? Кроме того, для меня важна эффективность хранения. Для индексов с несколькими столбцами я думал, что высокая кардинальность первого (левого) столбца индекса будет означать больше места для хранения по сравнению с столбцом с меньшей кардинальностью слева. Более высокая кардинальность слева будет означать больше родительских узлов, верно? Это вообще влияет на объем памяти? Еще раз спасибо :) - person Sean; 08.04.2010
comment
@Sean: это также справедливо для составных индексов. Если у вас включено сжатие ключей (в MyISAM), столбцы с низким количеством элементов могут даже сэкономить вам место (но они подразумевают линейный поиск по страницам, так что это вопрос компромисса). Количество родительских узлов полностью зависит от количества записей, которые могут поместиться на странице. - person Quassnoi; 08.04.2010
comment
@Quassnoi - с уходом MyISAM точка сжатия ключа больше не действует. Нет нет веских причин учитывать мощность столбцов составного индекса в InnoDB. - person Rick James; 11.07.2018