Что является первичным MySQL (key1, key2) - PullRequest
2 голосов
/ 28 ноября 2009

Я работаю над существующей БД и пытаюсь ее оптимизировать. Я вижу таблицу без единственного первичного ключа, но с двумя внешними ключами, работающими в качестве первичного ключа. Я знаю, что это сработает. однако лучше ли иметь один первичный ключ с двумя внешними ключами для повышения производительности, или первичный (key1, key2) будет работать так же хорошо, как один?

Например:

CREATE TABLE  ABC (
     'xid' int(11),
    'yid' int (11),
PRIMAY KEY (xid, yid)
)

does it perform the same (in terms of indexing) as:

CREATE TABLE ABC (
  'id' int(11),
  'yid' int (11),
  'xid', int (11),
  PRIMARY KEY (id),
 KEY (xid, yid)
)

некоторые обновления там

Итак, я провожу некоторое тестирование .. используя простые запросы к трем различным таблицам

Таблица myA, более 10000 записей. имеет только ИД пользователя в качестве основного индекса.

ВЫБРАТЬ * ИЗ myA, где ИД пользователя = 12345

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE           myA    const   PRIMARY              PRIMARY    4   const   1 

Таблица myB, таблица «многие ко многим», с первичным идентификатором и ИД пользователя в качестве одного из двух внешних ключей. с более чем 50000 записей

ВЫБРАТЬ * ИЗ myB, где ИД пользователя = 12345

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE           myB    ref     userid           userid     4   const   53   

Таблица myC также является таблицей «многие ко многим», но с составным первичным ключом идентификатор пользователя является одним из двух. с более чем 100 000 записей

ВЫБРАТЬ * ИЗ myC, где ИД пользователя = 12345

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   SIMPLE           myC    ALL     NULL             NULL   NULL    NULL    101289  Using where

Итак, таблица C фактически проверяет все 100 000 записей !!! (запрос возвращает только 50 записей)

Есть кое-что, чего я не понимаю ... мне кажется, что составной первичный не выполняет эту работу.


MORE ..

Хотя я делаю больше тестов и "Объясняю", я заключаю, что (в MySQL), даже вы устанавливаете составные ключи в качестве первичного ключа. Вы все еще должны явно установить индекс для всех ключей. Тогда вы будете наслаждаться индексированием.

Ответы [ 4 ]

4 голосов
/ 28 ноября 2009

Во втором примере, который вы показываете, столбцы xid, yid проиндексированы , но ничто не мешает вашему приложению ввести одну и ту же пару xid, yid в несколько строк ABC таблица:

INSERT INTO ABC (xid, yid) VALUES (123, 456), (123, 456); -- NO ERROR

Таким способом вы можете получить непреднамеренные дубликаты, и это может вызвать странные эффекты, когда вы выполняете объединения и подсчитываете. Также, если вам нужно обновить строку, чтобы изменить связь между данным xid и его yid, вы можете обновить одну строку, а не другую (и).

Вы должны по крайней мере объявить ключ над (xid, yid) как UNIQUE KEY, чтобы избежать дублирования.

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

DELETE FROM ABC WHERE xid = 123 AND yid = 456;

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

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

Настаивать на избыточном суррогатном ключе, когда он не нужен, я считаю антипаттерном SQL.


Повторяйте ваш обновленный вопрос выше: знаете ли вы, что составной индекс помогает только тогда, когда ваш поиск включает в себя самые левые столбцы в индексе? Это верно для любого составного индекса в любой марке РСУБД. Пример: * +1032 *

CREATE TABLE myC (
  somethingid INT,
  userid      INT,
  PRIMARY KEY (somethingid, userid)
);

SELECT * FROM myC WHERE userid = 12345;

Этот запрос не может использовать индекс первичного ключа.

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

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

CREATE TABLE myC (
  somethingid INT,
  userid      INT,
  PRIMARY KEY (somethingid, userid),
  KEY (userid)
);

Обычно, если этот столбец объявлен как внешний ключ, СУБД должна автоматически создать индекс. Однако в некоторых версиях некоторых продуктов СУБД вы должны самостоятельно создать индекс для столбца внешнего ключа как отдельное действие.

1 голос
/ 28 ноября 2009

То, что вы описываете, является составным первичным ключом, который является приемлемым и разумным шаблоном. Многие приложения используют искусственный первичный ключ (обычно int или guid), когда уже есть совершенно приемлемый ключ-кандидат. Это добавляет работу для базы данных, но в некоторых случаях облегчает написание приложения.

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

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

1 голос
/ 28 ноября 2009

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

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

Если вы не выбираете по этому столбцу id, в этом нет необходимости.

0 голосов
/ 28 ноября 2009

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

...