Pregunta

Como crear un índice para filtrar un rango específico o un subconjunto de la tabla en MySQL? Que yo sepa que es imposible crear directamente, pero creo que es posible simular esta característica.

Ejemplo: Quiero crear un índice para la columna NAME sólo para las filas con STATUS = 'ACTIVE'

Esta funcionalidad se llama un filtrada índice en SQL Server y una índice parcial en Postgres.

¿Fue útil?

Solución

MySQL actualmente no soporta índices condicionales.

Para achive lo que están pidiendo (no es que debes hacerlo;)) puede empezar a crear una mesa auxiliar:

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

A continuación, añadir tres disparadores en la tabla 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 ;

Necesitamos delimiter // porque queremos utilizar ; el interior de los factores desencadenantes.

De esta manera, la mesa auxiliar contendrá exactamente los identificadores correspondientes a las principales líneas de la tabla que contienen la cadena "ACTIVO", siendo actualizado por los factores desencadenantes.

Para usar eso en una select, se puede utilizar el join habitual:

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

Si la tabla principal ya contiene datos, o en caso de que haga alguna operación externa que cambia los datos de una manera inusual (por ejemplo .: MySQL exterior), se puede fijar la mesa auxiliar con esto:

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

Sobre el rendimiento, probablemente usted tendrá más lentas inserciones, actualizaciones y eliminaciones. Esto puede tener un cierto sentido sólo si realmente se ocupa de algunos casos en los que la condición deseada es positiva. Incluso esa manera, probablemente sólo prueba se puede ver si el espacio de guardado realmente justifica esta aproach (y si realmente están ahorrando ningún espacio en absoluto).

Otros consejos

entiendo la pregunta correctamente, creo que lo que iba a lograr lo que estamos tratando de hacer es crear un índice en ambas columnas, nombre y estado. Eso le permitirá de manera eficiente a consulta donde nombre = 'SMITH' y STATUS = 'activa'

No se puede hacer la indexación condicional, pero por su ejemplo, se puede añadir un índice de varias columnas en (name, status).

A pesar de que va a indexar todos los datos de esas columnas, todavía ayudarle a encontrar los nombres que usted está buscando con el estado "activo".

Se puede hacer esto mediante la división de los datos entre dos tablas, con vistas a la unión de las dos tablas cuando se necesita todos los datos, y la indexación sólo una de las mesas de la otra columna - pero creo que esto podría causar problemas de rendimiento de las consultas que hay necesidad de correr por toda la mesa a menos que el planificador de consulta es más inteligente de lo que se dé el crédito correspondiente. Esencialmente usted estaría particionando manualmente la tabla (y appying el índice a sólo una de las particiones).

característica integrada de la partición de tablas no lo hará ayudarle en su búsqueda ya que no se puede aplicar un índice para una sola partición.

Se podría mantener una columna adicional con un índice y sólo tienen un valor en esa columna cuando la condición que desea que el índice que se basa en que es cierto, pero esto es probable que sea un trabajo intensivo y de un valor limitado (o negativo) en cuanto a la consulta de eficiencia y ahorro de espacio.

MySQL ahora tiene columnas virtuales, que pueden ser utilizados para los índices.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a dba.stackexchange
scroll top