Ich fragte eine ähnliche Frage vor (integer-vs-char-for-db-record-property) aber stolperte über etwas, das gegen alle Empfehlungen, die ich in meinem früheren Post erhalten hatte, widerspricht. In Wordpress 3, dem populärsten und ausgereiftesten Open-Source-Blog-Skript, wird der Post-Status als VARCHAR(20)
in db gespeichert - 'publish', 'auto-draft', 'inherit', 'pending' usw. und nicht als INT
mit Nachschlagetabelle oder gemappte String-Konstanten, oder CHAR
, oder etwas ähnliches. Dies gilt auch für das Feld post_type
('post', 'attachment', 'revision' usw.) und einige andere Felder. Um also alle veröffentlichten Posts zu finden, muss ich etwas wie SELECT * FROM posts WHERE post_status = 'published' AND post_type = 'post'
ausführen. Außerdem gibt es einen mehrspaltigen Index für post_status, post_type und einige andere Spalten, der diese Art der Suche sicherlich beschleunigt. Kann jemand erklären, warum sie es so und nicht anders gemacht haben, und welche Vor- und Nachteile hat dieser Ansatz?Integer vs Char für DB-Record-Eigenschaft vs Wordpress-Schema
Antwort
Nur weil eine Anwendung bekannt ist, bedeutet das nicht, dass sie ein gutes Datenbankdesign haben. Dies tendiert dazu, die Normalisierungsregeln zu verletzen. Vielleicht bekommen sie bessere Leistungen und vielleicht haben sie sich die anderen Möglichkeiten nicht angesehen, als sie sich für diese entschieden haben, weil sie es nicht besser wussten. Vielleicht waren sie Anwendungsprogrammierer, die eine Datenbank entwarfen, ohne die Datenbanktheorie sehr gut zu verstehen, oder vielleicht war es eine bewusste Denormierung mit Leistungsstatistiken, um das zu untermauern. Oder sie dachten nicht an die Möglichkeit, 100 Millionen Datensätze auf den neuesten Stand zu bringen, als wir beschlossen, den Wert von "veröffentlicht" in etwas anderes zu ändern. Vielleicht haben sie nur die Leistung von Selects getestet, aber nicht von Updates. Vielleicht ändern sich die Werte im Allgemeinen unweigerlich, also ist es keine so große Sache zu denormalisieren. Wir können es von hier nicht wissen.
Bei der Normalisierung geht es nicht darum, Strings durch Zahlen zu ersetzen oder Strings zu "teilen", nur weil sie die gleichen Buchstaben haben.
Ich kenne ihr Design nicht, aber das folgende Szenario ist perfekt normalisiert, obwohl es Zeichenfolgen als Bezeichner verwendet.
create table post_statuses(
status varchar(20) not null
,primary key(status)
);
insert into post_statuses values('publish');
insert into post_statuses values('inherit');
insert into post_statuses values('pending');
create table posts(
post_id ...
status varchar(20) not null
,primary key(post_id)
,foreign key(status) references post_statuses(status)
);
Der Hauptvorteil von natürlichen Schlüsseln über Ersatzschlüssel ist, dass es die Anzahl der Joins benötigt und auch die Wahrscheinlichkeit, dass ganze Klassen von Anfragen aus dem Index reduziert nur beantwortet werden können. Die Hauptnachteile sind erhöhte Speicherkapazität und die Möglichkeit, eine Hölle zu haben, wenn wir die Werte ändern müssen.
Ich würde vermuten, dass die WP-Entwickler einfach vermieden haben, was sie als vorzeitige Optimierung empfanden, und entschieden sich stattdessen für eine bessere Lesbarkeit.
"SELECT * FROM posts WHERE post_status = 'published' AND post_type = 'post'"
ist ein wenig etwas leichter als
"SELECT * FROM posts WHERE post_status = ".WP_POST_STATUS_PUBLISHED."
AND post_type = ".WP_POST_TYPE_POST.""
zu lesen und wenn ein neuer WP Entwickler eine select * from ...
Abfrage ausgeführt wird, ‚veröffentlicht‘ die Datenbanktabelle Listen anstatt 3 oder 5, das ist einfacher zu verstehen und zu debuggen.
Aus der Sicht des Plattenspeicherplatzes, ist entweder Ansatz ziemlich okay, denke ich - einige mehr post_status
Bytes sollte nicht viel im Vergleich zu dem Blog-Post Text und alle anderen Spalten. Ein Integer ist 8 Bytes (gut, es sei denn, es ist ein Tinyint) und "veröffentlicht" ist vielleicht 10 Bytes, also spielt es keine Rolle?
- 1. Integer vs Char für DB Record Eigenschaft
- 2. char Array vs. char Zeiger
- 3. New Integer vs valueOf
- 4. char vs Wchar_t vs char16_t vs char32_t (C++ 11)
- 5. Uninitialized Int vs Integer
- 6. char * variable Adresse vs. char [] variable Adresse
- 7. const constexpr char * vs. constexpr char *
- 8. Mit char * a [] vs char a [] []
- 9. static_cast void * char * vs static_cast ungültig ** char **
- 10. C++ Karte :: finden char * vs. char []
- 11. Int vs Integer in Swift
- 12. MySQL Integer vs DateTime Index
- 13. (Num a) vs Integer Typinferenz
- 14. int vs Integer Vergleich Java
- 15. Ziel-C: Unichar vs Char
- 16. UTF8 vs. UTF16 vs Char * vs. was? Jemand erklärt mir dieses Durcheinander!
- 17. Effizienz: Char-Array vs Int-Array
- 18. Konvertieren Bytes integer in Java vs Python
- 19. LINQ vs foreach vs für Leistung Testergebnisse
- 20. String Terminierung - char c = 0 vs char c = '\ 0'
- 21. C++ mit size_t vs unsigned integer Beispiel
- 22. MySQL Integer Vergleichsgeschwindigkeit (= vs <>)
- 23. Integer vs. String Entscheidungsfindung in Java
- 24. Null Division java integer vs Doppel
- 25. casting double to signed vs unsigned integer
- 26. MySQL "binär" vs "Char Zeichensatz binär"
- 27. C++ 11-Typ Abzug vs const char *
- 28. Null-Zeiger-Ausnahme (int Vs char)
- 29. mit Character vs char-Array initialisieren
- 30. JPA/Hibernate DDL-Generierung; CHAR vs. VARCHAR
Speichern von Status und post_type als Strings kann möglicherweise nicht "die Normalisierungsregeln verletzen" (oder sogar "tendieren", sie zu verletzen, soweit ich sehen kann). Das Design, das Vincent beschrieben hat, könnte die Datenbank möglicherweise viel größer machen, als es sein müsste, aber das ist eine andere Frage. Die Normalisierung ist völlig unabhängig von der Art der in einer Spalte gespeicherten Daten und hat nichts mit der Speichergröße zu tun. Ich denke, das sollte klar sein. – sqlvogel