KEY `foo_bar` (`order_id`)
«КЛЮЧ» совпадает с «ИНДЕКС». Он указывает, что для эффективного доступа к таблице поддерживается отдельная структура данных через столбец order_id
.
foo_bar
- это имя индекса. Это не имеет особого значения и имеет очень мало применений. Например, DROP KEY foo_bar;
- это способ избавиться от индекса.
В MyISAM «FOREIGN KEY» разрешен, но игнорируется. В InnoDB он делает две вещи:
- Создание индекса, если он еще не предоставлен
- Предоставление ограничения. По умолчанию по умолчанию «жаловаться, если в другой таблице еще не указано значение».
Наличие индекса важно для производительности. Приведенный выше индекс заставляет этот
SELECT ... WHERE order_id = 1234 ...
работать в миллисекундах, даже если в таблице есть миллиарды строк. Без индекса запрос занимал бы минуты или часы.
A PRIMARY KEY
- это ключ UNIQUE
, то есть INDEX
.
UNIQUE(widget)
говорит, что только одна строка может иметь конкретное значение `widget в таблице.
PRIMARY KEY(id)
говорит о том, что каждая строка уникально идентифицируется столбцом id
. InnoDB действительно хочет, чтобы каждая таблица имела PK.
"id
" - это соглашение (а не требование) для имени PK. Это также INT AUTO_INCREMENT
по соглашению. Вы можете или не можете когда-либо касаться id
.
Таблицы могут быть связаны друг с другом тремя основными способами:
1: 1 - у них один и тот же уникальный ключ. Это редко полезно; у вас также может быть одна таблица.
1: many - в «заказе» есть несколько «предметов» (один заказ: много предметов). Обычно это делается с помощью order_id
, являющегося столбцом в таблице items
.
many: many - students_classes
- каждый ученик учится во многих классах; В каждом классе много учеников. Это реализуется с помощью таблицы сопоставления, которая имеет (обычно) только два столбца: student_id
и class_id
(не требуется id
) и PRIMARY KEY(student_id, class_id)
и INDEX(class_id, student_id)
. Эти два индекса делают его эффективным для go от известного ученика до его класса, и наоборот.
Другое соглашение для PK таблицы - включение имени таблицы. (Это беспорядочно делать это для других столбцов, таких как order_status
.) Я принимал это соглашение для student_id
и class_id
.
Но теперь меня смущает ваше plugin_orders
- у него есть и id
, и order_id
. Если эта таблица описывает «заказы», то я бы ожидал, что order_id
будет PK вместо id
.
И, если order_product
- это список всех «продуктов» в каждом «заказе» ", тогда я ожидал бы, что у вас будет шаблон 1: много.
Какие индексы будут иметь?
PRIMARY KEY
для уникальной идентификации каждой строки - либо id
, либо некоторые столбцы (или комбинации столбцов), которые являются уникальными. - Другие столбцы, если необходимо, для
SELECTs
, UPDATEs
и DELETEs
, которые у вас есть. Не добавляйте индексы вслепую, пока не получите некоторые подсказки запросов, которые могут им понадобиться.
Индексы иногда помогают в сортировке:
SELECT ... ORDER BY last_name, first_name;
вместе с
INDEX(last_name, first_name)
Индексы обеспечивают производительность; ФК обеспечивают проверки целостности. Ни то, ни другое не требуется; оба «желательны».
MyISAM древний; вам нужно перейти на InnoDB.
Затем сделать что-то вроде
SELECT ...
FROM plugin_orders AS o
JOIN plugin_order_product AS op
ON o.order_id = op.order_id
WHERE ...
В этом примере оптимизатор выполнит запрос примерно так:
- Посмотрите на
WHERE
, чтобы увидеть, какую таблицу лучше всего отфильтровать по имеющимся там условиям. Объявите, что это первая таблица, с которой вы работаете. - Просканируйте первую таблицу, используя индекс, если это возможно.
- Для каждой строки в первой таблице перейдите во вторую таблицу.
- Доступ ко второй таблице, вероятно, будет осуществляться через
INDEX(order_id)
на второй таблице. Это сделает JOIN
быстрым и эффективным.
Обе таблицы имеют INDEX(order_id)
, но это не имеет значения.
Следующий пример:
SELECT ...
FROM plugin_orders AS o
JOIN plugin_order_product AS op
ON o.order_id = op.order_id
WHERE o.people_id = 123 -- note
- Выберите
o
в качестве первой таблицы из-за фильтрации по people_id
- , используйте
op
INDEX(people_id)
, чтобы быстро найти соответствующие строки o
. - et c (
op
- вторая таблица)
Следующий пример:
SELECT ...
FROM plugin_orders AS o
JOIN plugin_order_product AS op
ON o.order_id = op.order_id
WHERE op.product_id = 9887 -- changed again
- Выберите
op
в качестве первой таблицы из-за при фильтрации product_id
- используйте
o
INDEX(people_id)
для быстрого поиска релевантных строк op
. - et c (
o
- вторая таблица на этот раз )