Question

Comment créer un index pour filtrer une gamme spécifique ou sous-ensemble de la table dans MySQL? Autant que je sache, il est impossible de créer directement, mais je pense qu'il est possible de simuler cette fonction.

Exemple: Je veux créer un index pour la colonne de NAME juste pour les lignes avec STATUS = 'ACTIVE'

Cette fonctionnalité sera appelée index filtré dans SQL Server et un index partiel dans Postgres.

Était-ce utile?

La solution

MySQL ne supporte pas les index conditionnels.

Pour ACHIVE ce que vous demandez (pas que vous devriez le faire;)), vous pouvez commencer à créer une table auxiliaire:

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`)
);

Ensuite, vous ajoutez trois déclencheurs dans le tableau principal:

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 ;
  

Nous avons besoin delimiter // parce que nous voulons utiliser ; à l'intérieur des déclencheurs.

De cette façon, la table auxiliaire contiendra exactement les ID correspondant aux principales lignes de la table contenant la chaîne « ACTIVE », mise à jour par les déclencheurs.

Pour utiliser sur un select, vous pouvez utiliser la join habituelle:

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

Si la table principale contient déjà des données, ou dans le cas où vous faites une opération externe qui modifie les données d'une manière inhabituelle (MySQL en dehors .: par exemple), vous pouvez fixer la table auxiliaire avec ceci:

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

A propos de la performance, probablement vous aurez des inserts plus lents, les mises à jour et les suppressions. Cela peut donner un sens que si vous traitez vraiment avec quelques cas où la condition souhaitée est positive. Même de cette façon, probablement vous pouvez tester si l'espace sauvegardé justifie vraiment ce aproche (et si vous enregistrez vraiment un espace du tout).

Autres conseils

Si je comprends bien la question, je pense que ce qui accomplir ce que vous essayez de faire est de créer un index sur les deux colonnes, nom et son statut. Cela efficace vous permettant de demander où NAME = 'SMITH' et STATUS = 'ACTIVE'

Vous ne pouvez pas faire l'indexation conditionnelle, mais pour votre exemple, vous pouvez ajouter un index à plusieurs colonnes (name, status).

Même si elle indexe toutes les données dans ces colonnes, il sera toujours vous aider à trouver les noms que vous recherchez avec le statut « actif ».

Vous pouvez le faire en divisant les données entre deux tables, en utilisant des vues à l'union des deux tables lorsque toutes les données sont nécessaires, et l'indexation que l'une des tables sur cette colonne - mais je pense que cela poserait des problèmes de performance pour les requêtes qui ont besoin de courir sur toute la table, sauf si le planificateur de requêtes est plus intelligent que je lui donne le crédit. Essentiellement, vous seriez partitionnez manuellement la table (et appying l'indice à une seule des partitions).

Malheureusement, le fonction intégrée de partitionnement de table ne sera pas vous aider dans votre quête que vous ne pouvez pas appliquer un index à une seule partition.

Vous pourriez maintenir une colonne supplémentaire avec un indice et ont seulement une valeur dans cette colonne lorsque la condition que vous souhaitez l'indice se fonder sur est vrai, mais cela est susceptible d'être beaucoup de travail et de faible valeur (ou négative) en termes de recherche d'économie d'efficacité et de l'espace.

MySQL a maintenant des colonnes virtuelles, qui peuvent être utilisés pour les index.

Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top