Ich erstelle eine Webanwendung (Projektmanagementsystem) und habe mich darüber gewundert, was die Leistung angeht.
Ich habe eine Issues-Tabelle und darin befinden sich 12 Fremdschlüssel, die mit verschiedenen anderen Tabellen verknüpft sind. 8 davon müsste ich verbinden, um das Titelfeld von den anderen Tabellen abzurufen, damit der Datensatz in einer Webanwendung einen Sinn ergibt. Dann bedeutet es jedoch, 8 Verknüpfungen auszuführen, was wirklich übertrieben erscheint, insbesondere, weil ich nur einbezogen bin 1 Feld für jeden dieser Joins.
Jetzt wurde mir auch gesagt, dass ich einen automatisch inkrementierenden Primärschlüssel verwenden soll (es sei denn, das Splittern ist ein Problem, in welchem Fall ich eine GUID verwenden sollte). Aber wie schlecht ist es, einen varchar (max. Länge 32) in Bezug auf die Leistung zu verwenden? Ich meine, die meisten dieser Tabellen werden wahrscheinlich nicht viele Datensätze enthalten (die meisten sollten unter 20 sein). Auch wenn ich den Titel als Primärschlüssel verwende, muss ich 95% der Zeit keine Joins ausführen, sodass bei 95% der SQL sogar Leistungseinbußen auftreten (glaube ich). Der einzige Nachteil, den ich mir vorstellen kann, ist, dass ich mehr Speicherplatz verbrauchen werde (aber ein Tag weniger ist das wirklich eine große Sache).
Der Grund, warum ich Nachschlagetabellen für viele dieser Dinge anstelle von Aufzählungen verwende, ist, dass alle diese Werte vom Endbenutzer über die Anwendung selbst konfiguriert werden müssen.
Was sind die Nachteile der Verwendung eines varchar als Primärschlüssel für eine Tabelle, die nicht über viele Datensätze verfügt?
UPDATE - Einige Tests
Also habe ich mich entschlossen, ein paar grundlegende Tests mit diesem Zeug durchzuführen. Ich habe 100000 Datensätze und dies sind die Basisabfragen:
Basis-VARCHAR-FK-Abfrage
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
Basis INT FK-Abfrage
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
Ich habe diese Abfrage auch mit den folgenden Ergänzungen ausgeführt:
- Wählen Sie ein bestimmtes Element aus (wobei i.key = 43298).
- Gruppieren nach i.id.
- Order by (it.title für int FK, i.issueTypeId für varchar FK)
- Limit (50000, 100)
- Zusammen gruppieren und begrenzen
- Gruppieren, ordnen und begrenzen Sie gemeinsam
Die Ergebnisse für diese wo:
Abfragetyp: VARCHAR FK TIME / INT FK TIME
Basisabfrage: ~ 4ms / ~ 52ms
Wählen Sie ein bestimmtes Element aus: ~ 140ms / ~ 250ms
Gruppieren nach i.id .: ~ 4 ms / ~ 2,8 s
Ordnen nach: ~ 231ms / ~ 2sec
Limit: ~ 67 ms / ~ 343 ms
Zusammen gruppieren und begrenzen: ~ 504ms / ~ 2sec
Zusammen gruppieren, bestellen und begrenzen: ~ 504ms / ~ 2,3sec
Jetzt weiß ich nicht, welche Konfiguration ich vornehmen könnte, um die eine oder die andere (oder beide) schneller zu machen, aber es scheint, als würde der VARCHAR FK in Abfragen nach Daten schneller sehen (manchmal viel schneller).
Ich denke, ich muss mich entscheiden, ob diese Geschwindigkeitsverbesserung die zusätzliche Daten- / Indexgröße wert ist.