Много столбцов против нескольких таблиц - с точки зрения производительности

12

Да, я знаю, что нормализация данных должна быть моим приоритетом (как есть).

  1. У меня есть таблица с 65 столбцами , хранящих данные транспортного средства с колоннами: used_vehicle, color, doors, mileage, priceи так далее, в общей сложности 65.
  2. Теперь, я могу разделить это и есть Vehicleтаблица, VehicleInterior, VehicleExterior, VehicleTechnical, VehicleExtra(все один к одному с основной Vehicleтаблицей).

Предположим, у меня будет около 5 миллионов строк (транспортных средств).

Вкл. SELECTС WHEREпредложением: Будет ли производительность при поиске лучше (оба случая проиндексированы хотя бы на IDs:)

  1. Vehicle таблица с 65 столбцами или
  2. Vehicleтаблица с JOINSчетырьмя другими таблицами (все с 5 миллионами строк), чтобы вернуть все данные, связанные с Vehicle?

(Что касается механизма базы данных, рассмотрим PostgreSQL и / или MySQL).

Действительно цените какие-либо подробные идеи, которые вы могли бы получить из вашего предыдущего опыта?

Урим Куртиши
источник
1
Одна из причин сделать это (вертикальное разбиение) состоит в том, что если у вас есть запросы, относящиеся к столбцам из VehicleInterior, другие запросы, относящиеся только к столбцам VehicleTechnicalи т. Д., Или если есть много строк / транспортных средств, которые не имеют абсолютно никакой информации (например), VehicleExtraтак вместо множества строк с множеством нулей в одной таблице у вас есть строки в остальных таблицах и нет строк вVehicleExtra
ypercubeᵀᴹ

Ответы:

14

Предполагая, что речь идет об отношениях 1: 1 между всеми таблицами.

Общее хранилище практически всегда (существенно) дешевле с одной таблицей вместо нескольких таблиц в соотношении 1: 1. Каждая строка имеет 28 байтов служебной информации плюс обычно еще несколько байтов для дополнительного заполнения. И вам нужно хранить столбец PK с каждой таблицей. И иметь отдельный (избыточный) индекс для каждого из этих столбцов ... Размер имеет значение для производительности.

Это даже верно, если многие столбцы имеют значение NULL в большинстве строк, поскольку хранилище NULL очень дешево :

При извлечении всех столбцов одна таблица значительно быстрее, чем 5 таблиц, соединенных вместе. Это также намного проще . Пять таблиц может быть сложно объединить, если не все строки присутствуют во всех таблицах. С WHEREусловиями, предназначенными для одной таблицы, достаточно легко добавлять другие таблицы LEFT JOIN. Не так тривиально, если у вас есть предикаты в нескольких таблицах ...

Вертикальное разбиение может все еще улучшить производительность определенных запросов. Например, если 90% ваших запросов извлекают те же 5 столбцов из 65 доступных, это будет быстрее, если таблица будет содержать только эти 5 столбцов.

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

Еще один кандидат на вертикальное разбиение: если у вас много обновлений только по нескольким столбцам, тогда как остальные вряд ли когда-либо изменятся. В таком случае разделение строк может быть значительно дешевле, поскольку Postgres пишет новую версию строки для каждого обновления. Существуют исключения для больших значений, хранящихся вне строки («TOASTed»). Больше деталей:

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

Эрвин Брандштеттер
источник
обновления будут редкими, если их нет, и выбор будет происходить в основном для всех столбцов (страница сведений об автомобиле) и основной информации (несколько столбцов) для списка результатов поиска, и фактически, возможно, лучшим решением будут две таблицы: одна с основной информацией (несколько столбцов) ) и другая таблица с остальными столбцами. так что в этом случае, что вы думаете о соединениях SQL, скажем, 5 миллионов строк - с точки зрения производительности? Кстати, спасибо за ваши подробные усилия
Урим Куртиши
1
@octavius: наилучшим маршрутом может быть одиночная таблица с многоколоночным индексом в нескольких столбцах, чтобы разрешить сканирование только по индексу для списка результатов. (Имейте в виду, что последовательность столбцов имеет значение в индексах btree .) Объединения не так уж дороги, но без объединения они будут быстрее. Дополнительный размер хранилища и разброс данных по нескольким таблицам могут быть более медленными (больше страниц данных для чтения для каждого запроса).
Эрвин Брандштеттер
1
Я согласен с комментарием Эрвинса, что ответ действительно будет зависеть от ситуации в целом или использования в реальном мире. Если вы обнаружили, что 90% запросов относились к небольшому подмножеству данных, а производительность была абсолютно первостепенной, то может возникнуть необходимость оправдать дополнительные усилия, разбитые на множество таблиц. Лично я постараюсь сделать модель данных простой. Кроме того, насколько быстро достаточно быстро? Сколько усилий вы тратите, чтобы сохранить эту последнюю миллисекунду? Вы пробовали копировать какие-либо данные и делать какие-либо тесты?
Сэр, ругается много
@ErwinBrandstetter вы упомянули в своем ответе, что соотношение 1: 1. А как насчет кораблей отношения 1: N?
Слим
В любом случае для отношения 1: N вам нужны две отдельные таблицы. За исключением случаев, когда вы втисните несколько строк в массив или тип документа. Тогда это зависит. Принципы, изложенные здесь, применяются независимо. Ваши шаблоны доступа и индексные стратегии могут иметь значение. Задайте новый вопрос, если хотите быть более конкретным.
Эрвин Брандштеттер,
0

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

Однако вы теряете эффективность нормализации. Например, если у 1 машины было много моделей с разными вариантами.

Это эталонный дБ всех автомобилей? Или список подержанных автомобилей? Будет ли много примеров одной марки / модели с одинаковыми параметрами?

Изменить: я должен квалифицировать мой ответ как общие rdbms, а не конкретные postgres. Я полагаюсь на подробный ответ @ Erwin, специфичный для postgres

Сэр ругается много
источник
2
«Выбор на одном столе всегда должен быть быстрее». Почему?
ypercubeᵀᴹ
vehiclemake и vehiclemodel - это разные таблицы, поэтому в таблице транспортных средств есть внешние ключи vehiclemake и vehiclemodel. я не думаю, что нормализация является проблемой здесь. я понимаю, что выборка по одной таблице будет быстрее, однако у нас другая ситуация: как строка с большим количеством столбцов повлияет на производительность и т. д. по сравнению с таблицами с меньшим количеством столбцов (но с несколькими таблицами - 5 из них с объединениями)
Урим Куртиши
Извините, я упустил момент, что марка и модель уже были разделены. Короткая версия заключается в том, что объединения требуют усилий для механизма базы данных. Если вы используете одну таблицу / строку, вы получите все за один выбор, что приведет к меньшему количеству ввода-вывода и накладных расходов для движка БД.
Сэр, ругается много