2009-11-21 13 views
6

He estado pensando en los índices de mi base de datos últimamente, en el pasado simplemente los lancé de forma caprichosa como una idea de último momento, y nunca pensé mucho si eran correctos o incluso ayudando He leído información contradictoria, algunos dicen que más índices son mejores y otros que demasiados índices son malos, así que espero obtener algunas aclaraciones y aprender un poco aquí.Necesito una pequeña aclaración sobre los índices de MySQL

Digamos que tengo esta tabla hipotética:

CREATE TABLE widgets (
    widget_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, 
    widget_name VARCHAR(50) NOT NULL, 
    widget_part_number VARCHAR(20) NOT NULL, 
    widget_price FLOAT NOT NULL, 
    widget_description TEXT NOT NULL 
); 

Me normalmente añadir un índice para los campos que se unirán y los campos que se pueden clasificar en más a menudo:

ALTER TABLE widgets ADD INDEX widget_name_index(widget_name); 

Así que ahora , en una consulta, tales como:

SELECT w.* FROM widgets AS w ORDER BY w.widget_name ASC 

El widget_name_index se utiliza para SOR t el conjunto de resultados

Ahora bien, si puedo añadir un parámetro de búsqueda:

SELECT w.* FROM widgets AS w 
WHERE w.widget_price > 100.00 
ORDER BY w.widget_name ASC 

supongo que necesito un nuevo índice.

ALTER TABLE widgets ADD INDEX widget_price_index(widget_price); 

Pero, ¿usará ambos índices? Como lo entiendo no lo hará ...

ALTER TABLE widgets ADD INDEX widget_price_name_index(widget_price, widget_name); 

Ahora widget_price_name_index se utilizará tanto para seleccionar y ordenar los registros. Pero lo que si quiero darle la vuelta y hacer esto:

SELECT w.* FROM widgets AS w 
WHERE w.widget_name LIKE '%foobar%' 
ORDER BY w.widget_price ASC 

Será widget_price_name_index ser utilizado para esto? ¿O necesito un widget_name_price_index también?

ALTER TABLE widgets ADD INDEX widget_name_price_index(widget_name, widget_price); 

Ahora lo que si tengo un cuadro de búsqueda que busca en widget_name, widget_part_number y widget_description?

ALTER TABLE widgets 
ADD INDEX widget_search(widget_name, widget_part_number, widget_description); 

¿Y si los usuarios finales pueden ordenar por cualquier columna? Es fácil ver cómo podría terminar con más de una docena de índices por tan solo 5 columnas.

Si añadimos otra tabla:

CREATE TABLE specials (
    special_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, 
    widget_id INT UNSIGNED NOT NULL, 
    special_title VARCHAR(100) NOT NULL, 
    special_discount FLOAT NOT NULL, 
    special_date DATE NOT NULL 
); 
ALTER TABLE specials ADD INDEX specials_widget_id_index(widget_id); 
ALTER TABLE specials ADD INDEX special_title_index(special_title); 

SELECT w.widget_name, s.special_title 
FROM widgets AS w 
INNER JOIN specials AS s ON w.widget_id=s.widget_id 
ORDER BY w.widget_name ASC, s.special_title ASC 

Estoy asumiendo para ello se utiliza widget_id_index y el índice de clave principal widgets.widget_id de la unión, pero ¿qué pasa con la clasificación? ¿Utilizará ambos widget_name_index y special_title_index?

No quiero dar vueltas por mucho tiempo, hay un sinfín de escenarios que podría conujure. Obviamente, esto puede ser mucho más complejo con escenarios del mundo real en lugar de un par de tablas simples. Cualquier aclaración sería apreciada.

+4

No voy a poner esto como una respuesta, ya que no soy un experto en lo que respecta a bases de datos, pero en mysql puede usar EXPLAIN antes de una consulta para proporcionar información sobre qué índices se utilizan. http://dev.mysql.com/doc/refman/5.0/en/explain.html – MitMaro

Respuesta

5

Según las prácticas recomendadas, no es necesario crear un índice mientras se definen los esquemas de la tabla. Siempre es mejor crear un índice a medida que crea las consultas en su aplicación. En la mayoría de los casos, comenzará con un índice de columna única para satisfacer una consulta. Si desea utilizar muchas columnas en una consulta, puede crear un índice de cobertura.

Un índice de cobertura es un índice con dos o más columnas en él. Si el índice satisface todos los requisitos de columna de una consulta, el motor de almacenamiento puede obtener todos los resultados del índice en lugar de iniciar una operación de E/S de disco. Por lo tanto, al crear una consulta que utiliza más columnas, puede crear un nuevo índice que abarque todas las columnas requeridas o, puede ampliar el índice existente para incluir más columnas.

Debe tener en cuenta algunas consideraciones al hacer cualquiera de las anteriores. MySQL considera un índice solo cuando la columna más a la izquierda del índice se puede usar en la consulta. De lo contrario, simplemente busca la tabla completa para obtener resultados. Entonces, si puede extender un índice existente sin afectar todas las consultas que usan ese índice, entonces sería una buena elección. De lo contrario, puede continuar y crear un nuevo índice para la nueva consulta. A veces, las consultas se pueden ajustar para adaptarse a la estructura del índice.

+0

'en lugar de iniciar una operación de E/S de disco' ¿Dónde cree que se almacenan los datos de índice? –

3

Un índice acelera las selecciones, pero ralentiza inserciones y actualizaciones. No necesita crear un índice para cada combinación posible de columnas que pueda imaginar. Normalmente solo creo los índices obvios que sé que usaré a menudo, y solo agrego más si puedo ver que son necesarios después de tomar medidas de rendimiento.La base de datos aún puede usar un índice incluso si no cubre todas las columnas en la consulta.

+0

Más índices pueden ser mejores. Demasiados índices definitivamente es peor. –

3

Solo se utiliza un índice en una consulta. Afortunadamente, se puede crear un índice que cubre varias columnas:

ALTER TABLE widgets ADD INDEX name_and_price_index(widget_name, widget_price); 

Se utilizará el índice por encima de si se selecciona por WIDGET_NAME o WIDGET_NAME + widget_price (pero no sólo widget_price).

Como señala MitMaro, use EXPLAIN en una consulta para ver de qué índices tiene que elegir MySQL, así como qué índice termina usando. Consulte here para obtener más detalles.

+0

Las versiones recientes de MySQL tienen fusión de índice, que puede usar varios índices, en algunos casos. – peufeu

Cuestiones relacionadas