ли не Нормализовать "непрерывного" значение, такие как DATETIME
, FLOAT
, INT
. Do оставить значения в основной таблице.
При переносе значения в другие таблицы, особенно «снежинка», он делает запрос на основе значений где-то между немного медленнее и много медленнее. Это особенно важно, когда вам нужно отфильтровать более одного показателя, который не находится в главной таблице. Любой из них выполняют очень плохо из-за «снежинкой» или «по-нормализации»:
WHERE a.x = 123 AND b.y = 345
ORDER BY a.x, b.y
Как для того, что индексы создавать - это целиком зависит от запросов, которые необходимо выполнить. Итак, я настоятельно рекомендую вам набросать вероятный SELECTs
на основе вашего предварительного CREATE TABLEs
.
INT
- 4 байт. TIMESTAMP
- 5, FLOAT
- 4 и т. Д. То есть нормализация таких вещей также неэффективна в пространстве.
Больше
При выполнении JOINs
, оптимизатор почти всегда будет начинаться с одной таблицей, а затем перейти к другой таблице, и т.д. (см «вложенный цикл».)
Например (на основе вышеуказанного «кода»), когда 2 столбца нормированы, и вы тестируете значения, у вас нет двух ids
в руке, у вас есть только два значения. Это делает выполнение запроса очень неэффективным. Для
SELECT ...
FROM main
JOIN a USING(a_id)
JOIN b USING(b_id)
WHERE a.x = 123 AND b.y = 345
Ниже очень вероятно, будет «план выполнения»:
- достичь в
a
, чтобы найти строку (ы) с х = 123; получите id(s)
для этих строк. Это может включать в себя множество строк, которые еще не фильтруются b.y
. a
INDEX(x)
- Возврат к таблице
main
, поиск строк с этими идентификаторами. main
INDEX(a_id)
.Опять же, может быть перемещено больше строк, чем необходимо.
- Только сейчас, вы добираетесь до
b
(с использованием b_id
) для проверки на y=345
; бросить ненужные строки, которые вы вытаскивали. b
нуждается в INDEX(b_id)
Запомните мой комментарий о "haul around". Слепо с помощью *
(в SELECT *
) добавляется проблема - все столбцы перемещаются во время выполнения шагов.
С другой стороны ... Если x
и y
были в main
таблице, то код работает как:
WHERE main.x = 123
AND main.y = 345
нуждается только INDEX(x,y)
(в любом порядке). И он быстро находит нужные строки.
В случае ORDER BY a.x, b.y
, он не может использовать любой индекс на любой таблицы. Поэтому запрос должен создать таблицу tmp, отсортировать ее, а затем доставить строки в нужном порядке.
Но если x
и y
находятся в одной таблице, то INDEX(x,y)
(в таком порядке) может быть полезным для ORDER BY x,y
и избежать таблицы TMP и сортировки.
С помощью одной таблицы Оптимизатор может использовать индекс для WHERE
, или он может использовать индекс для ORDER BY
, в зависимости от фазы луны. В некоторых случаях один индекс может использоваться для обоих - это оптимально.
Другое примечание: Если у вас также есть LIMIT 10
, ... Если избежать sort
, необходимо просмотреть только 10 строк, а не весь набор из WHERE
.
Неужели это очень сложно иметь отдельный столбец для каждого подтипа? Способность поддерживать правильные отношения с внешним ключом представляется желательной для схемы таблицы фактов. Я понимаю, что стандартный столбец размером 4 байта может в конечном итоге потерять пространство. –
@ GordonLinoff это не конец света, но это еще больше усложнит процесс ETL, чтобы получить данные. Вот почему, пока производительность похожа, стоит компромисс с тем, чтобы поддерживать процесс одинаковым. – aarbor