Gibt es einen messbaren Leistungsunterschied zwischen der Verwendung von INT und VARCHAR als Primärschlüssel in MySQL? Ich möchte VARCHAR als Primärschlüssel für Referenzlisten verwenden (denken Sie an US-Bundesstaaten, Ländercodes), und ein Mitarbeiter wird sich nicht an INT AUTO_INCREMENT als Primärschlüssel für alle Tabellen rühren.
Wie hier ausgeführt , ist mein Argument, dass der Leistungsunterschied zwischen INT und VARCHAR vernachlässigbar ist, da für jede INT-Fremdschlüsselreferenz ein JOIN erforderlich ist, um die Referenz zu verstehen, und ein VARCHAR-Schlüssel die Informationen direkt darstellt.
Hat jemand Erfahrung mit diesem speziellen Anwendungsfall und den damit verbundenen Leistungsproblemen?
mysql
performance
primary-key
innodb
myisam
Jake McGraw
quelle
quelle
Antworten:
Sie machen einen guten Punkt, dass Sie eine bestimmte Anzahl von verknüpften Abfragen vermeiden können, indem Sie einen sogenannten natürlichen Schlüssel anstelle eines Ersatzschlüssels verwenden . Nur Sie können beurteilen, ob der Nutzen davon in Ihrer Anwendung von Bedeutung ist.
Das heißt, Sie können die Abfragen in Ihrer Anwendung messen, die für die Schnelligkeit am wichtigsten sind, da sie mit großen Datenmengen arbeiten oder sehr häufig ausgeführt werden. Wenn diese Abfragen von der Beseitigung eines Joins profitieren und nicht unter der Verwendung eines varchar-Primärschlüssels leiden, tun Sie dies.
Verwenden Sie keine der beiden Strategien für alle Tabellen in Ihrer Datenbank. In einigen Fällen ist ein natürlicher Schlüssel wahrscheinlich besser, in anderen Fällen ist ein Ersatzschlüssel besser.
Andere Leute weisen darauf hin, dass es in der Praxis selten vorkommt, dass sich ein natürlicher Schlüssel niemals ändert oder Duplikate aufweist. Daher lohnen sich Ersatzschlüssel normalerweise.
quelle
Es geht nicht um Leistung. Es geht darum, was einen guten Primärschlüssel ausmacht. Einzigartig und unveränderlich im Laufe der Zeit. Sie denken vielleicht, dass sich eine Entität wie ein Ländercode im Laufe der Zeit nie ändert und ein guter Kandidat für einen Primärschlüssel wäre. Aber bittere Erfahrung ist, dass das selten so ist.
INT AUTO_INCREMENT erfüllt die Bedingung "eindeutig und über die Zeit unverändert". Daher die Präferenz.
quelle
Ich war ein bisschen verärgert über das Fehlen von Benchmarks für dieses Online, also habe ich selbst einen Test durchgeführt.
Beachten Sie jedoch, dass ich dies nicht regelmäßig mache. Überprüfen Sie daher mein Setup und meine Schritte auf Faktoren, die die Ergebnisse unbeabsichtigt beeinflusst haben könnten, und veröffentlichen Sie Ihre Bedenken in Kommentaren.
Das Setup war wie folgt:
Die Tische:
Dann füllte ich 10 Millionen Zeilen in jeder Tabelle mit einem PHP-Skript, dessen Wesen wie folgt ist:
Für
int
Tabellen wurde das Bit($keys[rand(0, 9)])
durch just ersetztrand(0, 9)
, und fürvarchar
Tabellen habe ich vollständige US-Statusnamen verwendet, ohne sie auf 6 Zeichen zu schneiden oder zu erweitern.generate_random_string()
generiert eine 10-stellige Zufallszeichenfolge.Dann lief ich in MySQL:
SET SESSION query_cache_type=0;
jan_int
Tabelle:SELECT count(*) FROM jan_int WHERE myindex = 5;
SELECT BENCHMARK(1000000000, (SELECT count(*) FROM jan_int WHERE myindex = 5));
myindex = 'califo'
fürchar
Tabellen undmyindex = 'california'
fürvarchar
Tabellen.Zeiten der
BENCHMARK
Abfrage für jede Tabelle:In Bezug auf Tabellen- und Indexgrößen ist hier die Ausgabe von
show table status from janperformancetest;
(mit einigen nicht gezeigten Spalten):Mein Fazit ist, dass es für diesen speziellen Anwendungsfall keinen Leistungsunterschied gibt.
quelle
INDEX
anstelle vonPRIMARY KEY
. Ich erinnere mich nicht an meine Argumentation - ich habe wahrscheinlich angenommen, dassPRIMARY KEY
es sich nur um eineINDEX
Einschränkung der Eindeutigkeit handelt. Wenn ich jedoch den Abschnitt darüber lese , wie Dinge in InnoDB unter federico-razzoli.com/primary-key-in-innodb gespeichert werden , denke ich, dass meine Ergebnisse immer noch für Primärschlüssel gelten, und beantworte die Frage zum Leistungsunterschied bei der Wertesuche . Auch Ihr Kommentar schlägt vor , bei der Ausführung der Suche Sortieralgorithmen, die gelten nicht für die Verwendung Fall , den ich untersuchen, welche aufzublicken Werte in einem Satz.Hängt von der Länge ab. Wenn der Varchar 20 Zeichen und der Int 4 ist, hat Ihr Index bei Verwendung eines Int FÜNF Mal so viele Knoten pro Seite Indexspeicherplatz auf der Festplatte ... Das bedeutet, dass das Durchlaufen erfolgt Der Index erfordert ein Fünftel so viele physische und / oder logische Lesevorgänge.
Wenn die Leistung ein Problem darstellt, verwenden Sie bei Gelegenheit immer einen integralen, nicht aussagekräftigen Schlüssel (als Ersatzschlüssel bezeichnet) für Ihre Tabellen und für Fremdschlüssel, die auf die Zeilen in diesen Tabellen verweisen ...
Um die Datenkonsistenz zu gewährleisten, sollte jede Tabelle, auf die es ankommt, auch einen aussagekräftigen nicht numerischen Alternativschlüssel (oder einen eindeutigen Index) haben, um sicherzustellen, dass keine doppelten Zeilen eingefügt werden können (doppelte basierend auf aussagekräftigen Tabellenattributen).
Für die spezifische Verwendung, über die Sie sprechen (wie Status-Lookups), spielt es keine Rolle, da die Größe der Tabelle so klein ist. Im Allgemeinen hat dies keinen Einfluss auf die Leistung von Indizes für Tabellen mit weniger als einigen tausend Zeilen. ..
quelle
Absolut nicht.
Ich habe mehrere ... mehrere ... Leistungsprüfungen zwischen INT, VARCHAR und CHAR durchgeführt.
10 Millionen Datensatztabellen mit einem PRIMARY KEY (eindeutig und gruppiert) hatten genau die gleiche Geschwindigkeit und Leistung (und Teilbaumkosten), unabhängig davon, welche der drei von mir verwendet wurde.
Davon abgesehen ... verwenden Sie das, was für Ihre Anwendung am besten ist. Mach dir keine Sorgen über die Leistung.
quelle
Bei Funktionscodes gibt es wahrscheinlich keinen Unterschied. Dies gilt insbesondere, da die Tabelle mit diesen Codes wahrscheinlich sehr klein ist (höchstens ein paar tausend Zeilen) und sich nicht oft ändert (wann haben wir das letzte Mal einen neuen US-Bundesstaat hinzugefügt).
Bei größeren Tabellen mit einer größeren Variation zwischen den Schlüsseln kann dies gefährlich sein. Denken Sie beispielsweise an die Verwendung der E-Mail-Adresse / des Benutzernamens aus einer Benutzertabelle. Was passiert, wenn Sie einige Millionen Benutzer haben und einige dieser Benutzer lange Namen oder E-Mail-Adressen haben? Jedes Mal, wenn Sie diese Tabelle mit diesem Schlüssel verbinden müssen, wird sie viel teurer.
quelle
Was den Primärschlüssel betrifft, sollte als Primärschlüssel festgelegt werden, was eine Zeile physisch eindeutig macht.
Für eine Referenz als Fremdschlüssel ist die Verwendung einer automatisch inkrementierenden Ganzzahl als Ersatz aus zwei Hauptgründen eine gute Idee.
- Erstens fällt beim Join normalerweise weniger Overhead an.
- Zweitens, wenn Sie die Tabelle aktualisieren müssen, die das eindeutige varchar enthält, muss das Update auf alle untergeordneten Tabellen herunterkaskadiert und alle sowie die Indizes aktualisiert werden, während beim int-Ersatz nur das aktualisiert werden muss Mastertabelle und ihre Indizes.
Der Nachteil bei der Verwendung des Ersatzes besteht darin, dass Sie möglicherweise eine Änderung der Bedeutung des Ersatzes zulassen können:
Es hängt alles davon ab, worüber Sie sich in Ihrer Struktur wirklich Sorgen machen müssen und was am meisten bedeutet.
quelle
Häufige Fälle, in denen ein Ersatz
AUTO_INCREMENT
weh tut:Ein allgemeines Schemamuster ist eine Viele-zu-Viele-Zuordnung :
Die Leistung dieses Musters ist viel besser, insbesondere bei Verwendung von InnoDB:
Warum?
id
ein Index entfernt wurde.Ein anderer Fall ( Land ):
Allzu oft normalisiert der Anfänger den Ländercode in ein 4-Byte
INT
anstatt eine 'natürliche' 2-Byte-Zeichenfolge zu verwenden, die sich fast nicht . Schneller, kleiner, weniger JOINs, besser lesbar.quelle
Bei HauteLook haben wir viele unserer Tabellen geändert, um natürliche Schlüssel zu verwenden. Wir haben eine echte Leistungssteigerung erlebt. Wie Sie bereits erwähnt haben, verwenden viele unserer Abfragen jetzt weniger Verknüpfungen, wodurch die Abfragen leistungsfähiger werden. Wir werden sogar einen zusammengesetzten Primärschlüssel verwenden, wenn dies sinnvoll ist. Abgesehen davon sind einige Tabellen einfacher zu bearbeiten, wenn sie einen Ersatzschlüssel haben.
Wenn Sie zulassen, dass Benutzer Schnittstellen in Ihre Datenbank schreiben, kann ein Ersatzschlüssel hilfreich sein. Der Dritte kann sich darauf verlassen, dass sich der Ersatzschlüssel nur in sehr seltenen Fällen ändert.
quelle
Ich stand vor dem gleichen Dilemma. Ich habe ein DW (Konstellationsschema) mit 3 Faktentabellen erstellt: Verkehrsunfälle, Fahrzeuge bei Unfällen und Unfallopfer. Die Daten umfassen alle von 1979 bis 2012 in Großbritannien erfassten Unfälle sowie 60 Dimensionstabellen. Insgesamt rund 20 Millionen Datensätze.
Faktentabellen Beziehungen:
RDMS: MySQL 5.6
Der Unfallindex ist ein Varchar (Zahlen und Buchstaben) mit 15 Ziffern. Ich habe versucht, keine Ersatzschlüssel zu haben, sobald sich die Unfallindizes nie ändern würden. In einem i7-Computer (8 Kerne) wurde der DW zu langsam, um nach 12 Millionen Lastdatensätzen abhängig von den Abmessungen abzufragen. Nach vielen Überarbeitungen und dem Hinzufügen von Bigint-Ersatzschlüsseln erhielt ich eine durchschnittliche Geschwindigkeitssteigerung von 20%. Noch zu geringem Leistungsgewinn, aber gültiger Versuch. Ich arbeite in MySQL Tuning und Clustering.
quelle
Die Frage bezieht sich auf MySQL, daher gibt es einen signifikanten Unterschied. Wenn es um Oracle ging (das Zahlen als Zeichenfolge speichert - ja, ich konnte es zuerst nicht glauben), dann kein großer Unterschied.
Die Speicherung in der Tabelle ist nicht das Problem, aber das Aktualisieren und Verweisen auf den Index ist. Abfragen, bei denen ein Datensatz anhand seines Primärschlüssels nachgeschlagen wird, sind häufig. Sie möchten, dass sie so schnell wie möglich ausgeführt werden, da sie so häufig auftreten.
Die Sache ist, dass eine CPU natürlich mit 4-Byte- und 8-Byte-Ganzzahlen in Silizium umgeht . Es ist WIRKLICH schnell, zwei ganze Zahlen zu vergleichen - es geschieht in ein oder zwei Taktzyklen.
Schauen Sie sich jetzt eine Zeichenfolge an - sie besteht aus vielen Zeichen (heutzutage mehr als ein Byte pro Zeichen). Das Vergleichen von zwei Zeichenfolgen auf Vorrang kann nicht in einem oder zwei Zyklen durchgeführt werden. Stattdessen müssen die Zeichen der Zeichenfolgen iteriert werden, bis ein Unterschied festgestellt wird. Ich bin mir sicher, dass es Tricks gibt, um es in einigen Datenbanken schneller zu machen, aber das ist hier irrelevant, da ein int-Vergleich auf natürliche Weise und blitzschnell von der CPU in Silizium durchgeführt wird.
Meine allgemeine Regel - jeder Primärschlüssel sollte ein automatisch inkrementierendes INT sein, insbesondere in OO-Apps, die ein ORM (Hibernate, Datanucleus, was auch immer) verwenden, in dem es viele Beziehungen zwischen Objekten gibt - sie werden normalerweise immer als einfaches FK und die Fähigkeit für das implementiert DB, um diese Probleme schnell zu lösen, ist wichtig für die Reaktionsfähigkeit Ihrer App.
quelle
Sie sind sich nicht sicher über die Auswirkungen auf die Leistung, aber es scheint ein möglicher Kompromiss zu sein, zumindest während der Entwicklung, sowohl den automatisch inkrementierten, ganzzahligen "Ersatz" -Schlüssel als auch Ihren beabsichtigten, eindeutigen "natürlichen" Schlüssel einzuschließen. Dies gibt Ihnen die Möglichkeit, die Leistung sowie andere mögliche Probleme zu bewerten, einschließlich der Änderbarkeit natürlicher Schlüssel.
quelle
Wie üblich gibt es keine pauschalen Antworten. 'Es hängt davon ab, ob!' und ich bin nicht scherzhaft. Mein Verständnis der ursprünglichen Frage war, dass Schlüssel in kleinen Tabellen - wie Country (Ganzzahl-ID oder char / varchar-Code) - ein Fremdschlüssel für eine potenziell große Tabelle wie Adresse / Kontakttabelle sind.
Hier gibt es zwei Szenarien, in denen Sie Daten aus der Datenbank zurückerhalten möchten. Das erste ist eine Listen- / Suchabfrage, bei der Sie alle Kontakte mit Staats- und Ländercodes oder -namen auflisten möchten (IDs helfen nicht und benötigen daher eine Suche). Das andere ist ein Get-Szenario für den Primärschlüssel, in dem ein einzelner Kontaktdatensatz angezeigt wird, in dem der Name des Staates und des Landes angezeigt werden muss.
Für letztere ist es wahrscheinlich egal, worauf die FK basiert, da wir Tabellen für einen einzelnen Datensatz oder einige Datensätze und für Schlüssellesevorgänge zusammenführen. Das erstere Szenario (Suche oder Liste) kann durch unsere Wahl beeinflusst werden. Da das Land angezeigt werden muss (zumindest ein erkennbarer Code und möglicherweise sogar die Suche selbst einen Ländercode enthält), kann es möglicherweise möglich sein, nicht über einen Ersatzschlüssel einer anderen Tabelle beizutreten (ich bin hier nur vorsichtig, weil ich nicht tatsächlich getestet habe) dies, scheint aber sehr wahrscheinlich) die Leistung zu verbessern; ungeachtet der Tatsache, dass es sicherlich bei der Suche hilft.
Da die Codes klein sind - normalerweise nicht mehr als 3 Zeichen für Land und Bundesland - kann es in diesem Szenario in Ordnung sein, die natürlichen Schlüssel als Fremdschlüssel zu verwenden.
Das andere Szenario, in dem Schlüssel von längeren Varchar-Werten und möglicherweise von größeren Tabellen abhängen. Der Ersatzschlüssel hat wahrscheinlich den Vorteil.
quelle
Gestatten Sie mir, zu sagen, dass es unter Berücksichtigung des Leistungsumfangs definitiv einen Unterschied gibt (Standarddefinition):
1- Die Verwendung von Surrogate Int ist in der Anwendung schneller, da Sie ToUpper (), ToLower (), ToUpperInvarient () oder ToLowerInvarient () nicht in Ihrem Code oder in Ihrer Abfrage verwenden müssen und diese 4 Funktionen unterschiedliche Leistungsbenchmarks haben. Siehe hierzu die Microsoft-Leistungsregeln. (Leistung der Anwendung)
2- Die Verwendung von Surrogate Int garantiert, dass der Schlüssel im Laufe der Zeit nicht geändert wird. Sogar Ländercodes können sich ändern, siehe Wikipedia, wie sich ISO-Codes im Laufe der Zeit geändert haben. Das würde viel Zeit in Anspruch nehmen, um den Primärschlüssel für Teilbäume zu ändern. (Durchführung der Datenpflege)
3- Es scheint Probleme mit ORM-Lösungen zu geben, z. B. NHibernate, wenn PK / FK nicht int ist. (Entwicklerleistung)
quelle