2010-07-31 8 views

Antwort

5

Es scheint, wie ich gebe diesen Rat dreimal in der Woche hier auf SO, vielleicht sollte ich einfach aufgeben und lassen Sie es :-) Nö gehen, ich glaube nicht so:

Don‘ t Verwenden Sie pro Zeile Zeilenfunktionen in Ihren Spaltenberechnungen (oder order by Klauseln), wenn Sie möchten, dass Ihre Datenbank gut skaliert. Sie sollten die Leistung für Ihren speziellen Fall überprüfen (messen, nicht raten), aber Berechnungen, wenn lesen die Datenbank wird in der Regel beeinflussen Ihre Fähigkeit zu skalieren (dies ist nicht wichtig für Ihre Adressbuch-Datenbank, aber die Geschäfte, die ich arbeite in haben riesige Mengen von Daten).

Die Anzahl der "Wie bekomme ich meine DB schneller?" Fragen überwiegen bei weitem die Anzahl von "Wie verwende ich weniger Platz?" Einsen. Es ist ein ausgetretener Pfad, um Speicherplatz für die Leistung zu opfern.

Die richtige Zeit für Berechnungen ist, wenn sich die Daten ändern. Auf diese Weise werden die Kosten der Änderungen über alle Lesevorgänge hinweg amortisiert.

Mein Rat ist, ein weitere Spalte wie dtLastAction erstellen, um die Bestellwert enthält dann ein Insert/Update-Trigger verwenden, um das gleiche zu setzen, wie dtModified wenn nicht null, oder dtPosted wenn dtModified ist null. Technisch gesehen verstößt dies gegen 3NF, aber das ist in Ordnung, wenn Sie wissen, was Sie tun, und die Auslöser garantieren in diesem Fall die Datenkonsistenz.

Dann Index auf der dtLastAction Spalte und sehen Sie die Geschwindigkeit Ihrer Abfragen verbessern zu den (geringeren) Kosten für einige zusätzliche Arbeit während Einfügungen und Updates. Ich sage weniger, weil die Mehrheit der Datenbanktabellen mehr gelesen als geschrieben wird (offensichtlich ist diese Methode nutzlos, wenn Ihre besondere Situation eine der sehr seltenen Ausnahmen ist).

Alternativ kann für diesen speziellen Fall könnten Sie dtModified und dtPosted auf den gleichen Wert gesetzt, wenn Sie den Eintrag erstellen, was bedeutet, dass dtModified wird nie null sein. Sie können immer noch Posts erkennen, die noch nie geändert wurden, da diese beiden Datetime-Werte identisch sind.

+0

ja, ich denke,' dtLastAction' ist großartig. vielleicht überprüft, ob das Überprüfen, ob "dtModified" gleich "dtPosted" ist, noch größer ist. Ich brauche kein zusätzliches Feld. vielleicht umbenennen 'dtModified' zu' dtLastAction' wird es intuitiver machen –

+0

Insgesamt stimme ich mit der Senkung der Kosten für die Lesevorgänge überein. Dieser spezielle Fall ist jedoch so einfach, dass ich nicht denke, dass dies die zusätzliche Komplexität des Caching rechtfertigt. Z.B. Wenn die Aktion gelöscht wird, müssen Sie das letzte Aktionsdatum auf die letzte letzte Aktion aktualisieren, Alptraum! – malhal

13

können Sie COALESCE verwenden:

ORDER BY COALESCE(dtModified, dtPosted) 

Eine weitere Option, um die MySQL-spezifische Funktion IFNULL statt COALESCE zu verwenden ist.


Testing auf MySQL:

CREATE TABLE table1 (dtModified DATETIME NULL, dtPosted DATETIME NOT NULL); 
INSERT INTO table1 (dtModified, dtPosted) VALUES 
('2010-07-31 10:00:00', '2010-07-30 10:00:00'), 
(NULL     , '2010-07-31 09:00:00'), 
('2010-07-31 08:00:00', '2010-07-30 10:00:00'); 

SELECT dtModified, dtPosted 
FROM table1 
ORDER BY COALESCE(dtModified, dtPosted) 

Ergebnisse:

dtModified   dtPosted 
2010-07-31 08:00:00 2010-07-30 10:00:00 
NULL     2010-07-31 09:00:00 
2010-07-31 10:00:00 2010-07-30 10:00:00 
+0

können Sie eine COALESCE in ORDER BY verwenden? –

+0

Ja, ich denke, Sie müssen 'IFNULL' für MySQL verwenden. –

+0

@Daniel Vassallo: Ich habe es gerade in MySQL getestet und es scheint gut zu funktionieren. Sehen Sie meine aktualisierte Antwort für die SQL, die ich verwendete. –

0

In der SELECT, verwenden Sie eine CASE-Anweisung, die den Wert von Datum ansonsten null geändert nimmt, wenn nicht Datum gebucht. Dann verwenden Sie diese neue "berechnete" Spalte für Ihre ORDER BY.

Verwandte Themen