Tworzę aplikację internetową (system zarządzania projektami) i zastanawiałem się nad tym, jeśli chodzi o wydajność.
Mam tabelę problemów, w której znajduje się 12 kluczy obcych łączących różne tabele. z tych, 8 z nich musiałbym dołączyć, aby uzyskać pole tytułu z innych tabel, aby rekord miał jakikolwiek sens w aplikacji internetowej, ale wtedy oznacza wykonanie 8 złączeń, co wydaje się naprawdę przesadne, zwłaszcza że wciągam tylko 1 pole dla każdego z tych złączeń.
Teraz powiedziano mi również, aby używać automatycznego klucza podstawowego (chyba że sharding jest problemem, w którym to przypadku powinienem użyć GUID) ze względów trwałości, ale jak źle jest używać varchar (maksymalna długość 32) pod względem wydajności? Mam na myśli, że większość tych tabel prawdopodobnie nie będzie miała wielu rekordów (większość z nich powinna mieć mniej niż 20 lat). Również jeśli użyję tego tytułu jako klucza podstawowego, nie będę musiał wykonywać złączeń w 95% przypadków, więc dla 95% sql nawet wystąpiłbym jakikolwiek spadek wydajności (tak myślę). Jedynym minusem, jaki mogę wymyślić, jest to, że będę miał większe wykorzystanie miejsca na dysku (ale minusem jest to naprawdę wielka sprawa).
Powodem, dla którego używam tabel wyszukiwania dla wielu takich rzeczy zamiast wyliczeń jest to, że potrzebuję wszystkich tych wartości, aby użytkownik końcowy mógł je skonfigurować za pośrednictwem samej aplikacji.
Jakie są wady używania varchar jako klucza podstawowego dla tabeli, z wyjątkiem wielu rekordów?
AKTUALIZACJA - Niektóre testy
Postanowiłem więc przeprowadzić podstawowe testy tych rzeczy. Mam 100000 rekordów i to są podstawowe zapytania:
Podstawowe zapytanie 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
Zapytanie bazowe 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
Uruchomiłem te zapytanie z następującymi dodatkami:
- Wybierz konkretny element (gdzie i.key = 43298)
- Grupuj według i.id
- Zamów przez (it.title dla int FK, i.issueTypeId dla varchar FK)
- Limit (50000, 100)
- Grupuj i ograniczaj razem
- Grupuj, porządkuj i ograniczaj razem
Wyniki dla tych, gdzie:
TYP ZAPYTAŃ: VARCHAR FK TIME / INT FK TIME
Zapytanie podstawowe: ~ 4ms / ~ 52ms
Wybierz konkretny element: ~ 140ms / ~ 250ms
Grupuj według identyfikatora i.id: ~ 4ms / ~ 2.8sec
Sortuj według: ~ 231ms / ~ 2sec
Limit: ~ 67ms / ~ 343ms
Grupuj i ogranicz razem: ~ 504ms / ~ 2sec
Grupuj, porządkuj i ograniczaj razem: ~ 504 ms / ~ 2,3 s
Teraz nie wiem, jaką konfigurację mogę zrobić, aby przyspieszyć jedną lub drugą (lub obie), ale wygląda na to, że VARCHAR FK widzi szybciej w zapytaniach o dane (czasem znacznie szybciej).
Chyba muszę wybrać, czy to zwiększenie prędkości jest warte dodatkowego rozmiaru danych / indeksu.