Подтвердить что ты не робот

Определяет ли порядок полей многоколоночного индекса в MySQL

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

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

Например, с сайта mysql (http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html)

CREATE TABLE test (
    id         INT NOT NULL,
    last_name  CHAR(30) NOT NULL,
    first_name CHAR(30) NOT NULL,
    PRIMARY KEY (id),
    INDEX name (last_name,first_name)
);

Будет ли какое-либо пособие в любых случаях, когда следующее будет лучше или эквивалентно?

CREATE TABLE test (
    id         INT NOT NULL,
    last_name  CHAR(30) NOT NULL,
    first_name CHAR(30) NOT NULL,
    PRIMARY KEY (id),
    INDEX name (first_name,last_name)
);

Specificially:

INDEX name (last_name,first_name)

против

INDEX name (first_name,last_name)
4b9b3361

Ответ 1

При обсуждении многоколоночных индексов я использую аналогию с телефонной книгой. Телефонная книга - это в основном индекс по фамилии, затем имя. Таким образом, порядок сортировки определяется тем, что "столбец" является первым. Поиски попадают в несколько категорий:

  • Если вы посмотрите людей, чья фамилия Смит, вы можете легко найти их, потому что книга сортируется по фамилии.

  • Если вы посмотрите людей, чье имя - Джон, телефонная книга не поможет, потому что Джонс разбросаны по всей книге. Вам нужно отсканировать всю телефонную книгу, чтобы найти все.

  • Если вы посмотрите на людей с определенной фамилией Смит и с конкретным именем Джона, книга поможет, потому что вы обнаружите, что Смиты отсортированы вместе, и внутри этой группы Смит Джонс также найдены в отсортированном порядке.

Если у вас была телефонная книга, отсортированная по имени, а затем по фамилии, сортировка книги поможет вам в вышеуказанных случаях № 2 и № 3, но не в случае № 1.

Это объясняет случаи поиска точных значений, но что, если вы просматриваете диапазоны значений? Скажите, что вы хотели найти всех людей, чье имя - Джон и чья фамилия начинается с "S" (Смит, Сондерс, Стонтон, Шерман и т.д.). Джонс сортируется под "J" в пределах каждой фамилии, но если вы хотите, чтобы все Джонсы для всех фамилий, начинающихся с "S", Джонс не сгруппированы. Они снова разбросаны, поэтому вам придется сканировать все имена с фамилией, начинающейся с "S". Если бы телефонная книга была организована по имени, то по фамилии, вы бы нашли всех Джона вместе, то в пределах Джонса все фамилии "S" были бы сгруппированы вместе.

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

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

Ответ 2

Оба индекса различны. Это верно в MySQL и других базах данных. MySQL делает довольно хорошую работу по объяснению разных в документации.

Рассмотрим два индекса:

create index idx_lf on name(last_name, first_name);
create index idx_fl on name(first_name, last_name);

Оба они должны работать одинаково хорошо:

where last_name = XXX and first_name = YYY

idx_lf будет оптимальным для следующих условий:

where last_name = XXX
where last_name like 'X%'
where last_name = XXX and first_name like 'Y%'
where last_name = XXX order by first_name

idx_fl будет оптимальным для следующего:

where first_name = YYY
where first_name like 'Y%'
where first_name = YYY and last_name like 'X%'
where first_name = XXX order by last_name

Для многих из этих случаев оба индекса могут быть использованы, но один из них оптимален. Например, рассмотрите idx_lf с запросом:

where first_name = XXX order by last_name

MySQL может прочитать всю таблицу с помощью idx_lf, а затем выполнить фильтрацию после order by. Я не думаю, что это вариант оптимизации на практике (для MySQL), но это может произойти в других базах данных.

Ответ 3

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

SELECT * FROM myTable WHERE status='active' and dateAdded='2010-10-01'

... тогда вам нужно сначала dateAdded, потому что это ограничило бы сканирование всего несколькими строками, а не 10% (или любой другой пропорцией "активными" ) ваших строк.

Это требует немного размышлений и настройки; вы должны проверить книгу Лахденмаки и Лича.