Я будую веб-додаток (систему управління проектами) і мені було цікаво про це, коли справа доходить до продуктивності.
У мене є таблиця "Випуски", всередині неї - 12 сторонніх ключів, що посилаються на різні інші таблиці. з них, 8 з них, мені потрібно було б приєднатись, щоб отримати поле заголовка з інших таблиць, щоб запис мав сенс у веб-додатку, але тоді означає робити 8 приєднань, що здається надмірно тим більше, оскільки я лише підтягую 1 поле для кожного з них приєднується.
Тепер мені також сказали використовувати первинний ключ з автоматичним збільшенням (якщо тільки шардінг не викликає занепокоєння; в цьому випадку я повинен використовувати GUID) з міркувань постійності, але наскільки погано використовувати варчар (максимальна довжина 32)? Я маю на увазі, що більшість із цих таблиць, мабуть, не матимуть багатьох записів (більшість з них має бути молодше 20). Крім того, якщо я використовую заголовок в якості основного ключа, мені не доведеться робити приєднання 95% часу, тому для 95% sql, я навіть матиму будь-які покази продуктивності (я думаю). Єдиний мінус, про який я можу подумати, - це те, що у мене буде більший обсяг дискового простору (але в день це справді велика справа).
Причиною того, що я використовую таблиці пошуку для багатьох цих матеріалів замість перерахунків, є те, що мені потрібно, щоб усі ці значення були налаштовані кінцевим користувачем через саме додаток.
Які недоліки використання varchar в якості основного ключа для таблиці, окрім багатьох записів?
ОНОВЛЕННЯ - Деякі тести
Тому я вирішив зробити деякі основні тести на цей матеріал. У мене є 100000 записів, і це базові запити:
База VARCHAR FK Запит
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 Запит
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
Базовий запит: ~ 4ms / ~ 52ms
Виберіть конкретний предмет: ~ 140ms / ~ 250ms
Групувати за i.id: ~ 4 мс / ~ 2,8 сек
Упорядкувати за: ~ 231ms / ~ 2sec
Ліміт: ~ 67ms / ~ 343ms
Групуйте та обмежуйте разом: ~ 504ms / ~ 2sec
Групуйте, замовляйте та обмежуйте разом: ~ 504ms /~2.3sec
Тепер я не знаю, яку конфігурацію я міг би зробити, щоб зробити те чи інше (або і те й інше) швидше, але, схоже, VARCHAR FK швидше бачить запити щодо даних (іноді набагато швидше).
Я думаю, що мені доведеться вибрати, чи варто це підвищення швидкості додаткових даних / розміру індексу.