Ich habe große Datenmengen, bei denen ich jeweils nur ein kleines Datenintervall auswähle, sodass die Auswahl immer in einer Reihenfolge erfolgt. Ich versuche, PostgreSQL wie Partial Index in MySQL zu implementieren, der für solche Zwecke vorgesehen ist. Ich bin nicht sicher, ob die teilweise eindeutige Einschränkung dieselbe ist wie die, die ich möchte.
Code in PostgreSQL 9.4
CREATE UNIQUE INDEX dir_events
ON events (measurement_id)
USING btree
(eventBody)
WHERE is_active;
Versuch des Teilindex von ypercube in MySQL
CREATE UNIQUE INDEX dir_events
[index_type] -- TODO what here?
ON events (measurement_id, is_active)
[index_type] -- TODO what here?
Wie können Sie einen PostgreSQL-ähnlichen Teilindex in MySQL 5.5 oder ähnlichem erstellen?
is_active = TRUE
(oder nur eine Spalte, die PK vondir_events
) gespeichert sind .Antworten:
Weder MySQL noch die Geschwister (MariaDB, Drizzle usw.) haben Teilindizes implementiert.
Was Sie unter Berücksichtigung dieser Einschränkung tun können:
a) Machen Sie einen einfachen (nicht partiellen) Index auf
(is_active, measurement_id)
. Es wird in Abfragen verwendet, in denen der Teilindex verwendet wird. Wenn dieis_active
Spalte 3% Wahr und 97% Falsch ist, ist dieser Index natürlich viel größer (als ein Teilindex). Aber immer noch kleiner als die Tabelle und nützlich für diese Abfragen.Eine weitere Einschränkung ist, dass der Index
UNIQUE
bei dieser Lösung nicht vorhanden sein kann, sodass die Einschränkung nicht erzwungen wird. Wenn der Index mit erstellt wirdUNIQUE
, wird die Eindeutigkeit auch für Zeilen mit erzwungenis_active = FALSE
. Ich nehme an, das willst du nicht:b1) (die einfache Variante von b): Fügen Sie Ihrem Entwurf eine weitere Tabelle hinzu, zu der nur die Primärschlüsselspalten
events
und ein Fremdschlüssel gehörenevents
. Diese Tabelle sollte nur Zeilen enthalten, in denen dasis_active
in der Originaltabelle wahr ist (dies wird von Ihrer Anwendung / Ihren Prozeduren erzwungen). Abfragen mitis_active = TRUE
würden geändert, um dieser Tabelle beizutreten (anstelle derWHERE
Bedingung).Die
UNIQUE
Abfrage wird auch mit dieser Lösung nicht erzwungen, aber die Abfragen würden nur eine einfache Verknüpfung (zu einem viel kleineren Index) durchführen und sollten recht effizient sein:b2) eine komplexere Lösung: Fügen Sie Ihrem Entwurf eine weitere Tabelle hinzu, die nur die Primärschlüsselspalten der Tabelle und enthält
measurement_id
. Wie im vorherigen Vorschlag sollte diese Tabelle nur Zeilen enthalten, in denen dieis_active
ursprüngliche Tabelle wahr ist (dies wird auch von Ihrer Anwendung / Ihren Prozeduren erzwungen). Verwenden Sie diese Tabelle dann stattdessen nur für Abfragen, dieWHERE is_active = TRUE
nur diemeasurement_id
Spalte haben und benötigen . Wenn mehr Spalten von benötigt werdenevents
, müssen Siejoin
wie zuvor.Die
UNIQUE
Einschränkung kann mit dieser Lösung erzwungen werden. Das Duplizieren dermeasurement_id
Spalte kann auch so gesichert werden, dass es konsistent ist (mit einer zusätzlichen eindeutigen Einschränkungevents
und einem zusammengesetzten Fremdschlüssel):c) vielleicht das einfachste von allen: Verwenden Sie PostgreSQL. Ich bin sicher, es gibt Pakete für Ihre Linux-Distribution. Möglicherweise handelt es sich nicht um die neueste Version von Postgres, aber in 7.0 (oder früher?) Wurden Teilindizes hinzugefügt, sodass Sie kein Problem haben sollten. Außerdem bin ich zuversichtlich, dass Sie die neueste Version in fast jeder Linux-Distribution installieren können - auch mit ein wenig Aufwand. Sie müssen es nur einmal installieren.
quelle
Es ist nicht ideal, aber wenn Sie eine Validierung für das Feld haben, können Sie eine Änderung vornehmen, die den Wert ungültig macht. Zum Beispiel unzulässige Zeichen oder negative Zahlen. Sie können diese Änderung beim Soft-Löschen vornehmen und wissen, dass sie nicht mit einem gültigen Wert kollidiert. Sie müssen auch auf weiche gelöschte Werte achten, die nicht miteinander in Konflikt geraten.
In einem Fall hatte ich eine E-Mail-Spalte mit einer eindeutigen Einschränkung und einer Integer-ID für die automatische Inkrementierung für jede Zeile. Beim sanften Löschen habe ich vor der eigentlichen E-Mail "id @" hinzugefügt, wobei id die eindeutige Zeilen-ID war.
@
ist in E-Mails nur zulässig, wenn sie in Anführungszeichen gesetzt sind. Daher weiß ich, dass keine gültige E-Mail mit dem neuen Wert kollidiert und daher niemals mit einer gültigen E-Mail kollidiert. Die eindeutige Ganzzahl-ID garantiert auch, dass jede gelöschte Zeile eindeutig ist, selbst wenn dieselbe E-Mail mehrmals gelöscht wird.Ich weiß, dass dies nicht ideal ist, aber es ist eine einfache Möglichkeit, das Problem zu umgehen.
HINWEIS: Die von mir erwähnte Änderung fügt dem eindeutigen Feld Zeichen hinzu , sodass ich zusätzliche Tricks ausführen musste, wenn der aktuelle Wert bereits bei / nahe der maximalen Länge liegt. Sie sind anwendungsspezifisch, daher hier nicht erwähnenswert. Beachten Sie jedoch auch eine Problemumgehung, und dies ist eine einfache Möglichkeit, um das Fehlen der Teilindexfunktion zu umgehen.
quelle