Недостаток производительности композитного первичного ключа в MySQL - PullRequest
43 голосов
/ 22 сентября 2009

У нас есть таблица с составным первичным ключом, состоящая из трех полей (и это в MySQL 5.1). В этой таблице содержится около 200 вставок и 200 операций выбора в секунду, а размер таблицы составляет около 1 миллиона строк, и он увеличивается.

Мой вопрос: «Составной первичный ключ» снижает производительность вставок и выборок в этой таблице?

Должен ли я использовать простое поле автоматического увеличения INT ID вместо составного первичного ключа? (Я думаю, что ответ очень связан с тем, как MySQL обрабатывает индексы в нескольких столбцах)

Ответы [ 3 ]

53 голосов
/ 22 сентября 2009
Производительность

INSERT и UPDATE мало меняется: она будет практически одинаковой для клавиш (INT) и (INT, INT).

SELECT производительность композита PRIMARY KEY зависит от многих факторов.

Если ваша таблица InnoDB, то таблица неявно сгруппирована по значению PRIMARY KEY.

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

Предположим, ваш запрос выглядит примерно так:

SELECT  *
FROM    mytable
WHERE   col1 = @value1
        AND col2 = @value2

и раскладка таблицы такая:

CREATE TABLE mytable (
        col1 INT NOT NULL,
        col2 INT NOT NULL,
        data VARCHAR(200) NOT NULL,
        PRIMARY KEY pk_mytable (col1, col2)
) ENGINE=InnoDB

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

Если вы используете поле автоинкремента в качестве поддельного идентификатора:

CREATE TABLE mytable (
        id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
        col1 INT NOT NULL,
        col2 INT NOT NULL,
        data VARCHAR(200) NOT NULL,
        UNIQUE KEY ix_mytable_col1_col2 (col1, col2)
) ENGINE=InnoDB

, тогда движку потребуется сначала найти значения (col1, col2) в индексе ix_mytable_col1_col2, извлечь указатель строки из индекса (значение id) и выполнить другой поиск по id в самой таблице.

Для таблиц MyISAM, однако, это не имеет значения, поскольку таблицы MyISAM организованы в виде кучи, а указатель строки - просто смещение файла.

В обоих случаях будет создан один и тот же индекс (для PRIMARY KEY или для UNIQUE KEY) и будет использоваться одинаково.

22 голосов
/ 22 сентября 2009

Если это InnoDB, составной первичный ключ будет включен в каждую запись в каждом из вторичных индексов.

Это означает, что

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

Это, конечно, недостаток и преимущество соответственно.

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

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

Но я бы сказал, что в целом нет. Наличие составного первичного ключа НЕ вызывает проблемы само по себе. Однако наличие «большого» первичного ключа (например, больших varchars) может сработать, если это перевешивает преимущества кластеризации и возможности использования покрывающих индексов.

3 голосов
/ 22 сентября 2009
  1. Наличие этого составного первичного ключа немного замедляет SELECT s, хотя эффект в значительной степени незначителен и не стоит беспокоиться.
  2. Индексирование этих столбцов вообще замедляет ваши INSERT с, и вы, безусловно, делаете достаточно INSERT с, чтобы беспокоиться об этом. Это гораздо больше беспокоит, если это таблица MyISAM, где INSERT блокирует таблицу, чем если это таблица InnoDB. Если, используя первичный ключ auto_increment, вы сможете оставить эти столбцы неиндексированными, вы извлечете выгоду из этого изменения. Однако, если вам все еще необходимо сохранить эти три столбца проиндексированными (например, если вам необходимо обеспечить уникальность их комбинации), это ничего не даст для вас с точки зрения производительности.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...