Frage

Wie erstelle ich einen Index, um einen bestimmten Bereich oder eine bestimmte Teilmenge der Tabelle in MySQL zu filtern? Afaik Es ist unmöglich, direkt zu erstellen, aber ich denke, es ist möglich, diese Funktion zu simulieren.

Beispiel: Ich möchte einen Index für erstellen NAME Spalte nur für Reihen mit STATUS = 'ACTIVE'

Diese Funktionalität würde als a genannt gefilterter Index in SQL Server und a Teilindex in Postgres.

War es hilfreich?

Lösung

MySQL unterstützt derzeit keine bedingten Indizes.

Um das zu erreichen, was Sie fragen (nicht, dass Sie es tun sollten;)), können Sie eine Hilfstabelle erstellen:

CREATE TABLE  `my_schema`.`auxiliary_table` (
   `id` int unsigned NOT NULL,
   `name` varchar(250), /* specify the same way as in your main table */
   PRIMARY KEY (`id`),
   KEY `name` (`name`)
);

Dann fügen Sie drei Auslöser in der Haupttabelle hinzu:

delimiter //

CREATE TRIGGER example_insert AFTER INSERT ON main_table
FOR EACH ROW
BEGIN
   IF NEW.status = 'ACTIVE' THEN
      REPLACE auxiliary_table SET
         auxiliary_table.id = NEW.id,
         auxiliary_table.name = NEW.name;
   END IF;
END;//

CREATE TRIGGER example_update AFTER UPDATE ON main_table
FOR EACH ROW
BEGIN
   IF NEW.status = 'ACTIVE' THEN
      REPLACE auxiliary_table SET
         auxiliary_table.id = NEW.id,
         auxiliary_table.name = NEW.name;
   ELSE
      DELETE FROM auxiliary_table WHERE auxiliary_table.id = OLD.id;
   END IF;
END;//

CREATE TRIGGER example_delete AFTER DELETE ON main_table
FOR EACH ROW
BEGIN
   DELETE FROM auxiliary_table WHERE auxiliary_table.id = OLD.id;
END;//

delimiter ;

Wir brauchen delimiter // Weil wir verwenden wollen ; Innerhalb der Auslöser.

Auf diese Weise enthält die Hilfstabelle genau die IDs, die den Hauptzeilen der Tabellen entsprechen, die die Zeichenfolge "aktiv" enthalten und von den Triggern aktualisiert werden.

Um das für a zu verwenden select, Sie können das übliche verwenden join:

SELECT main_table.* FROM auxiliary_table LEFT JOIN main_table
   ON auxiliary_table.id = main_table.id
   ORDER BY auxiliary_table.name;

Wenn die Haupttabelle bereits Daten enthält oder falls Sie einen externen Betrieb durchführen, der Daten auf ungewöhnliche Weise ändert (z. B. außerhalb von MySQL), können Sie die Hilfstabelle damit festlegen:

INSERT INTO auxiliary_table SET
   id = main_table.id,
   name = main_table.name,
   WHERE main_table.status="ACTIVE";

In Bezug auf die Leistung haben Sie wahrscheinlich langsamere Einsätze, Updates und Löschungen. Dies kann nur dann sinnvoll sein, wenn Sie sich wirklich mit wenigen Fällen befassen, in denen der gewünschte Zustand positiv ist. Selbst so können Sie wahrscheinlich nur Testen sehen, ob der Speicherplatz diesen Acroach wirklich rechtfertigt (und ob Sie überhaupt einen Platz sparen).

Andere Tipps

Wenn Ich verstehe die Frage richtig, ich denke, was das erreichen würde, was Sie tun möchten, ist, einen Index für Spalten, Name und Status zu erstellen. Das würde es Ihnen effizient ermöglichen, wo name = 'smith' und status = 'active' abfragen, wo name = 'smith' und status = 'aktiv'

Sie können keine bedingte Indexierung durchführen, aber für Ihr Beispiel können Sie einen Multi-Säulen-Index hinzufügen (name,status).

Obwohl es alle Daten in diesen Spalten indexiert, hilft es Ihnen, die Namen zu finden, die Sie mit dem Status "aktiv" suchen.

Sie können dies tun, indem Sie die Daten zwischen zwei Tabellen teilen, Ansichten zur Vereinigung der beiden Tabellen verwenden, wenn alle Daten benötigt werden, und nur eine der Tabellen in dieser Spalte indizieren - aber ich denke, dies würde Leistungsprobleme für Abfragen verursachen, die erforderlich sind Laufen Sie den gesamten Tisch, es sei denn, der Queryplaner ist schlauer als ich ihm eine Gutschrift gebe. Im Wesentlichen würden Sie die Tabelle manuell verteilt (und den Index nur auf eine der Partitionen ansprechen).

Leider das Eingebaute Tischpartitionierungsfunktion Hilft Ihnen bei Ihrer Suche nicht, da Sie keinen Index auf eine einzelne Partition anwenden können.

Sie können eine zusätzliche Spalte mit einem Index beibehalten und nur einen Wert in dieser Spalte haben, wenn der Zustand, auf dem der Index basiert Abfrageeffizienz und Platzeinsparung.

MySQL hat jetzt virtuelle Spalten, die für Indizes verwendet werden können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange
scroll top