Что работает быстрее: длинная таблица с меньшим количеством столбцов или более короткая таблица с большим количеством столбцов?

Я должен принять решение, как спланировать таблицу, которая будет использоваться для хранения дат.

У меня есть около 20 разных дат для каждого пользователя, и я предполагаю, что сейчас 100 000 пользователей и их количество растет.

Итак, вопрос для запроса SELECT, что будет работать быстрее, если я сделаю таблицу с 20 полями? например

"user_dates"

userId, date_registered, date_paid, date_started_working, ... date_reported, date_fired всего 20 полей со 100 000 записей в таблице

или создайте 2 таблицы, как первая таблица "date_types" с 3 полями и 20 записями для вышеуказанных имен столбцов.

   id, date_type_id, date_type_name

    1       5        date_reported
    2       3        date_registerd
    ...

и вторая таблица с 3 полями фактических записей

"user_dates"

userId, date_type, date
   201       2      2012-01-28
   202       5      2012-06-14
 ...

но тогда с 2 000 000 записей?

Я думаю, что второй вариант более универсален, если мне нужно добавить больше дат, я могу сделать это из внешнего интерфейса, просто добавив запись в таблицу "date_type", а затем используя ее в "user_dates", однако теперь меня беспокоит производительность с 2 млн записей в табл.

Итак, какой вариант, по вашему мнению, будет работать быстрее?


person Petja Zaichikov    schedule 20.02.2013    source источник
comment
Не беспокойтесь о скорости. Позаботьтесь о простоте обслуживания и о том, чтобы база данных выполняла как можно больше проверок за вас.   -  person Andy Lester    schedule 20.02.2013


Ответы (5)


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

Я бы, однако, пошел с вашим вторым вариантом. Это потому, что вам не обязательно иметь поля, если они пусты. Поэтому, если пользователь не был уволен, не нужно создавать для него запись.

person Kermit    schedule 20.02.2013
comment
Хороший вопрос о пустых полях! Большинство пользователей никогда не продвинется после третьего 5-го статуса. - person Petja Zaichikov; 20.02.2013
comment
Что касается размера индекса, я не думаю, что вы можете определенно сказать, что один подход даст больший общий размер индекса, чем другой. Таблица с 20 строками, вероятно, может иметь гораздо больший общий размер индекса, чем нормализованные таблицы, если вам нужен индекс для каждого столбца или вам нужны дополнительные многостолбцовые индексы для оптимизации поиска. Это не говоря уже о том, что у вас будет в списке одна запись индекса даты для столбцов значений NULL (где в нормализованном подходе вообще не будет записи). Конечно, обычно меня больше заботит задержка запроса, чем размер индекса. - person Mike Brant; 20.02.2013

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

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

person Andorbal    schedule 20.02.2013
comment
I would only go with the longer table if you know you need the option to create date types on the fly. его возможность не требуется. Я не согласен с тем, что второй вариант сложнее выбрать на основе типа, все, что вам нужно сделать, это SELECT * FROM user_dates WHERE date_type = 2 или левое соединение таблицы document_types, если вам нужно использовать тип по имени. - person Petja Zaichikov; 20.02.2013
comment
По моему опыту, запросы становятся более сложными в большинстве нетривиальных сценариев. Даже для получения date_type 2 для каждого пользователя потребуется соединение, которое вам придется выполнять в каждом сценарии, когда вы получаете даты. - person Andorbal; 20.02.2013
comment
Я не вижу, чем это отличается, мне все равно придется присоединять эту таблицу к user_table, несмотря ни на что... но все в порядке, я на самом деле все время использую левое соединение. - person Petja Zaichikov; 20.02.2013

Лучший способ определить это — провести тестирование. Как правило, размеры данных, о которых вы говорите (20 столбцов дат на 100 тыс. записей), действительно довольно малы по сравнению с таблицами MySQL, поэтому я, вероятно, просто использовал бы одну таблицу с несколькими столбцами, если только вы не думаете, что будете добавлять новые типы полей даты все время и желание более гибкой схемы. Вам просто нужно убедиться, что вы проиндексировали все поля, которые будут использоваться для фильтрации, упорядочения, объединения и т. д. в запросах.

Дизайн также может быть проинформирован о том, какой тип запросов вы хотите выполнять с данными. Если, например, вы ожидаете, что вам может понадобиться запросить данные на основе комбинации полей (т. е. у пользователя есть определенная дата, но не другая дата), запрос, вероятно, будет гораздо более оптимальным для одной таблицы, поскольку вы могли бы использовать простой запрос SELECT ... WHERE. С отдельными таблицами вам может понадобиться выполнять подзапросы, нечетные условия соединения или предложения HAVING для выполнения запроса того же типа.

person Mike Brant    schedule 20.02.2013

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

Не жертвуйте отношением ради возможного повышения эффективности; оно того не стоит.

person Explosion Pills    schedule 20.02.2013
comment
Какое отношение? В настоящее время я использую первый вариант с 20 полями, интересно, но перестраиваю базу данных, поэтому интересно, следует ли мне использовать более универсальную модель (второй пример). - person Petja Zaichikov; 20.02.2013

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

person Chris    schedule 20.02.2013