Domanda

Come creare un indice per filtrare una gamma specifica o un sottoinsieme della tabella in MySQL? AFAIK è impossibile creare direttamente, ma penso che sia possibile simulare questa funzione.

Esempio: Voglio creare un indice per la colonna NAME solo per le righe con STATUS = 'ACTIVE'

Questa funzionalità sarebbe chiamato un filtrata indice in SQL Server e un parziale indice di PostgreSQL.

È stato utile?

Soluzione

MySQL attualmente non supporta gli indici condizionali.

Per achive quello che chiedete (non che si dovrebbe fare;)), è possibile iniziare a creare una tabella ausiliaria:

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

Poi si aggiunge tre trigger nella tabella principale:

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 ;

Abbiamo bisogno delimiter // perché vogliamo usare ; all'interno dei trigger.

In questo modo, il piano ausiliario conterrà esattamente gli ID corrispondenti alle principali righe della tabella che contengono la stringa "ACTIVE", aggiornato dai trigger.

Per usare che su un select, è possibile utilizzare il solito join:

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

Se la tabella principale contiene già dei dati, o nel caso in cui fare qualche operazione esterna che cambia i dati in un modo insolito (es .: MySQL esterno), è possibile correggere la tabella ausiliaria con questo:

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

A proposito di prestazioni, probabilmente avrete più lente inserimenti, aggiornamenti ed eliminazioni. Questo può dare un senso solo se avete a che fare davvero con pochi casi in cui la condizione desiderata è positivo. Anche in questo modo, probabilmente solo il test si può vedere se lo spazio risparmiato davvero giustifica questa aproach (e se siete davvero salvando qualsiasi spazio a tutti).

Altri suggerimenti

Se ho capito bene la questione, penso che quello che sarebbe realizzare quello che stai cercando di fare è quello di creare un indice su entrambe le colonne, nome e lo stato. Ciò in modo efficiente consentono di query in cui NAME = 'Smith' e STATUS = 'ACTIVE'

Non si può fare l'indicizzazione condizionale, ma per il tuo esempio, è possibile aggiungere un indice a più colonne su (name, status).

Anche se sarà indice di tutti i dati in quelle colonne, sarà ancora aiuterà a trovare i nomi si sta cercando con lo stato "attivo".

Si potrebbe fare questo da dividere i dati tra due tabelle, utilizzando viste per l'unione delle due tabelle quando è necessario tutti i dati, e l'indicizzazione solo uno dei tavoli su quella colonna - ma credo che questo potrebbe causare problemi di prestazioni per le query che hanno bisogno di correre su tutto il tavolo a meno che il pianificatore query è più intelligente di io do credito per. In sostanza si sarebbe partizionando manualmente la tabella (e appying l'indice ad una sola delle partizioni).

built-in funzione il partizionamento delle tabelle non lo farà aiutare nella vostra ricerca, come non è possibile applicare un indice per una singola partizione.

Si potrebbe mantenere una colonna in più con un indice e hanno solo un valore in quella colonna quando la condizione che si desidera l'indice per essere basata su è vero, ma questo è probabile che sia alta intensità di lavoro e di valore limitato (o negativo) in termini di risparmio di query efficienza e lo spazio.

MySQL ha ora colonna virtuale, che possono essere utilizzati per gli indici.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a dba.stackexchange
scroll top