2013-04-15 3 views
7

Какая эффективность (с точки зрения производительности запросов) таблицы базы данных - длинная или широкая?MySQL: Long table vs wide table

Т.е., этот

id size price 
1 S 12.4 
1 M 23.1 
1 L 33.3 
2 S 3.3 
2 M 5.3 
2 L 11.0 

по сравнению с этим

id S  M  L 
1 12.4 23.1 33.3 
2 3.3 5.3 11.0 

В общем случае (я считаю) сводится к сравнению производительности между GROUP BY и выбора столбцов непосредственно:

SELECT AVG(price) FROM table GROUP BY size 

или

SELECT AVG(S), AVG(M), AVG(L) FROM table 

Второе - это немного длиннее для записи (в терминах многих столбцов), но как насчет производительности двух? Если возможно, каковы общие преимущества/недостатки каждого из этих табличных форматов?

ответ

5

Прежде всего, это две разные модели данных, подходящие для разных целей.

Это, как говорится, я бы ожидать, вторая модель будет быстрее для агрегации, просто потому, что данные упакованы более компактно, поэтому необходимости меньше I/O:

  • The GROUP BY в первая модель может быть удовлетворена полностью сканирование по индексу {size, price}. Альтернатива индексу слишком медленная, когда данные слишком велики для размещения в ОЗУ.
  • Запрос во второй модели может быть удовлетворен полным сканированием таблицы. Не требуется указаний .

Поскольку для первого подхода требуется таблица + индекс, а вторая - только таблица, использование кэша лучше во втором случае.Даже если мы проигнорируем кеширование и сравниваем индекс (без таблицы) в первой модели со следующей во второй модели, я подозреваю, что индекс будет больше, чем таблица, просто потому, что он физически записывает size и имеет неиспользуемые «дыры» типичные для B-деревьев (хотя то же самое верно для таблицы, если оно равно clustered).

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

Кроме этого, вы можете рассматривать кеширование SUM и COUNT в отдельной таблице, содержащей только одну строку. Обновляйте триггеры SUM и COUNT через триггеры, когда строка вставлена, обновлена ​​или удалена в основной таблице. Затем вы можете легко получить текущий AVG, просто разделив SUM и COUNT.


Но вы должны действительно мера репрезентативных объемов данных, чтобы быть уверенным.

Поскольку нет ИНЕКЕ в запросе, все строки будут проверяться. Индексы полезны только для получения относительно небольшого подмножества строк таблицы (а иногда и для index-only scans). Как правило, если требуется более 10% строк в таблице, индексы не помогут, и СУБД часто выбирают полное сканирование таблицы, даже если индексы доступны.

+0

Большое спасибо за отличное объяснение! Ваши дополнительные комментарии в конце очень полезны, мой вопрос - это просто краткое изложение более крупной проблемы, с которой я столкнулся, и я обязательно их рассмотрю внимательно. – sashkello

1

Длинные более гибкие в использовании. Это позволяет фильтровать size, например

SELECT MAX(price) where size='L' 

Также он позволяет индексации на size и на id. Это ускоряет GROUP BY и любые запросы, к которым присоединяются другие таблицы на id и/или size такие таблицы запасов продукта.

2

Первый вариант приводит к увеличению количества строк и, как правило, будет медленнее второго.

Однако, как указал Deltalima, первый вариант более гибкий. Не только тогда, когда речь идет о разных вариантах запроса, но и когда/когда вам нужно продлить таблицу с другими размерами, цветами и т. Д.

Если у вас нет очень большого набора данных или требуется сверхбыстрое время поиска, вы Вероятно, лучше с первым вариантом.

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