Я создаю веб-приложение (систему управления проектами), и мне было интересно об этом, когда дело доходит до производительности.
У меня есть таблица вопросов, внутри которой есть 12 внешних ключей, связанных с различными другими таблицами. из них 8 из них мне нужно было бы объединить, чтобы получить поле заголовка из других таблиц, чтобы запись имела какой-либо смысл в веб-приложении, но тогда это означает выполнение 8 объединений, что кажется чрезмерным, особенно если учесть, что я только вытягиваю 1 поле для каждого из этих объединений.
Теперь мне также сказали использовать автоинкрементный первичный ключ (если не нужно использовать шардинг, в этом случае я должен использовать GUID) по причинам постоянства, но насколько плохо использовать varchar (максимальная длина 32) с точки зрения производительности? Я имею в виду, что большинство этих таблиц, вероятно, не будет иметь много записей (большинство из них должно быть меньше 20). Кроме того, если я использую заголовок в качестве первичного ключа, мне не нужно будет выполнять объединения в 95% случаев, поэтому для 95% sql я бы даже столкнулся с какой-либо потерей производительности (я думаю). Единственный недостаток, о котором я могу подумать, - это то, что у меня будет больше использования дискового пространства (но один день - это действительно большая проблема).
Причина, по которой я использую таблицы поиска для большей части этого материала вместо перечислений, заключается в том, что мне нужно, чтобы все эти значения были настраиваемы конечным пользователем через само приложение.
Каковы недостатки использования varchar в качестве первичного ключа для таблицы, в которой не должно быть много записей?
ОБНОВЛЕНИЕ - Некоторые тесты
Поэтому я решил сделать некоторые базовые тесты на этот материал. У меня есть 100000 записей, и это базовые запросы:
База VARCHAR FK Query
SELECT i.id, i.key, i.title, i.reporterUserUsername, i.assignedUserUsername, i.projectTitle,
i.ProjectComponentTitle, i.affectedProjectVersionTitle, i.originalFixedProjectVersionTitle,
i.fixedProjectVersionTitle, i.durationEstimate, i.storyPoints, i.dueDate,
i.issueSecurityLevelId, i.creatorUserUsername, i.createdTimestamp,
i.updatedTimestamp, i.issueTypeId, i.issueStatusId
FROM ProjectManagement.Issues i
База INT FK Query
SELECT i.id, i.key, i.title, ru.username as reporterUserUsername,
au.username as assignedUserUsername, p.title as projectTitle,
pc.title as ProjectComponentTitle, pva.title as affectedProjectVersionTitle,
pvo.title as originalFixedProjectVersionTitle, pvf.title as fixedProjectVersionTitle,
i.durationEstimate, i.storyPoints, i.dueDate, isl.title as issueSecurityLevelId,
cu.username as creatorUserUsername, i.createdTimestamp, i.updatedTimestamp,
it.title as issueTypeId, is.title as issueStatusId
FROM ProjectManagement2.Issues i
INNER JOIN ProjectManagement2.IssueTypes `it` ON it.id = i.issueTypeId
INNER JOIN ProjectManagement2.IssueStatuses `is` ON is.id = i.issueStatusId
INNER JOIN ProjectManagement2.Users `ru` ON ru.id = i.reporterUserId
INNER JOIN ProjectManagement2.Users `au` ON au.id = i.assignedUserId
INNER JOIN ProjectManagement2.Users `cu` ON cu.id = i.creatorUserId
INNER JOIN ProjectManagement2.Projects `p` ON p.id = i.projectId
INNER JOIN ProjectManagement2.`ProjectComponents` `pc` ON pc.id = i.projectComponentId
INNER JOIN ProjectManagement2.ProjectVersions `pva` ON pva.id = i.affectedProjectVersionId
INNER JOIN ProjectManagement2.ProjectVersions `pvo` ON pvo.id = i.originalFixedProjectVersionId
INNER JOIN ProjectManagement2.ProjectVersions `pvf` ON pvf.id = i.fixedProjectVersionId
INNER JOIN ProjectManagement2.IssueSecurityLevels isl ON isl.id = i.issueSecurityLevelId
Я также выполнил этот запрос со следующими дополнениями:
- Выберите конкретный элемент (где i.key = 43298)
- Группировать по i.id
- Упорядочить по (it.title для int FK, i.issueTypeId для varchar FK)
- Лимит (50000, 100)
- Группируйте и ограничивайте вместе
- Группируйте, заказывайте и ограничивайте вместе
Результаты для них, где:
ТИП ЗАПРОСА: VARCHAR FK TIME / INT FK TIME
Базовый запрос: ~ 4 мс / ~ 52 мс
Выберите конкретный элемент: ~ 140 мс / ~ 250 мс
Группировка по i.id: ~ 4 мс / ~ 2,8 с
Упорядочить по: ~ 231мс / ~ 2сек
Предел: ~ 67мс / ~ 343мс
Группировать и ограничивать вместе: ~ 504мс / ~ 2сек
Группировать, заказывать и ограничивать вместе: ~ 504ms /~2.3sec
Теперь я не знаю, какую конфигурацию я мог бы сделать, чтобы сделать один или другой (или оба) быстрее, но кажется, что VARCHAR FK видит быстрее в запросах данных (иногда намного быстрее).
Я думаю, мне нужно выбрать, стоит ли это повышение скорости дополнительным размером данных / индекса.