2012-04-18 19 views
14

Tengo una tabla Assets en un motor InnoDB definen como:Índices y el uso de las claves principales como los índices de MySQL

CREATE TABLE Assets (
qid SMALLINT(5) NOT NULL, 
sid BIGINT(20) NOT NULL AUTO_INCREMENT, 
... 
PRIMARY KEY (sid,qid), 
KEY sid (sid) 
); 

estoy ejecutando la siguiente consulta:

SELECT COUNT(*) FROM Assets WHERE sid>10000; 

En mi máquina, esta consulta lleva unos 30 segundos con 2 millones de entradas en la tabla. Ahora bien, si modifico la consulta para utilizar índices, los resultados varían ampliamente:

SELECT COUNT(*) FROM Assets USE INDEX(<index>) WHERE sid>10000; 
  • NO INDEX: No explícita USE INDEX, es decir, el primer SELECT consulta: 30 segundos
  • KEY sid (sid): 1,5 segs
  • KEY cid (sid,qid): 1,5 segundos
  • PRIMARY: utilicé USE INDEX(PRIMARY) dentro de la consulta. : 30 segundos

Así que estas son mis preguntas:

  1. pensé que una consulta sería utilizar automáticamente la clave primaria como su índice, basado en this. Y, sin embargo, hay una gran diferencia entre USE INDEX (cid) y NO INDEX. ¿Cual es la diferencia? Además, ¿cómo doy explícitamente la clave principal como índice?

  2. Si NO INDEX no usa realmente la clave principal como índice, ¿qué hace USE INDEX(PRIMARY) que tenga el mismo tiempo de ejecución que NO INDEX?

  3. ¿Hay alguna diferencia (no sólo se refiere a rendimiento) entre USE INDEX(sid) y USE INDEX(cid) en una consulta que sólo filtra por sid?

Perdonen la publicación larga, pero quiero que sea abierta a discusión.


Ok, esto es lo que he encontrado hasta ahora:

En primer lugar, me han dicho la clave de configuración, debe ser: PRIMARY KEY(qid,sid), KEY(sid) o PRIMARY KEY(sid,qid), KEY(qid). Realmente no entiendo la diferencia. Si alguien lo hace, házmelo saber.

En segundo lugar, la LLAVE sid (sid) hace referencia a muchas menos páginas de índice que una clave más grande, por lo que tiende a ser más rápida. En cuanto a la diferencia entre utilizar PRIMARY KEY como índice y una KEY adecuada (incluso si usan los mismos campos), me dijeron que es algo como esto:

Las claves principales indexan los datos de la tabla completa con los campos de la clave principal. Eso significa que la PRIMARY KEY y los datos se almacenan juntos. Por lo tanto, una consulta que use PRIMARY KEY debería pasar por toda la tabla de datos, que incluso indexada se empantanaría en tablas grandes e incavocables.

Con teclas discretas, el número de filas puede ser el mismo, pero se escanea un índice mucho más pequeño (que consta de los campos indicados), lo que afecta a un número menor de bloques de disco y, por lo tanto, se ejecuta mucho más rápido. Supongo que este es también el motivo de la diferencia en el uso de USE INDEX(cid) y el uso de la clave principal como índice, que tienen los mismos campos.

+4

Sólo una nota : si tiene 'PRIMARY KEY (sid, qid)' then 'KEY sid (sid)' no tiene sentido – zerkms

+0

PD: ponga EXPLAIN para 'SELECT COUNT (*) FROM Assets DONDE sid> 10000' please – zerkms

+0

cuantas filas con' sid> 10000' del total de 2M? Si es más que ~ 30%, entonces mysql decide que fullscan es más barato. Y es por eso que forzar índice ayuda – zerkms

Respuesta

1

Desde mi experiencia, que tiene un índice que es un subconjunto de otro tiende a ralentizar las cosas .. pero que el kilometraje puede variar, ya que hay que tener en cuenta muchas cosas cuando se trata de índices ..

Por ejemplo, si lee con frecuencia y rara vez cambia los datos, tener muchos índices podría ayudarlo más; si sus operaciones implican una gran cantidad de inserción/actualización/eliminación, tener demasiados índices puede hacer que disminuya bastante.

Si su clave principal es (sid, qid), entonces no veo la necesidad de tener otra clave (sid) que el motor probablemente pueda recuperar como un prefijo de la PK. Prefiero agregar un índice en qid si voy a aprovecharlo, es decir, si tengo algunas consultas filtrando o clasificando en ese campo o si tengo algunas JOIN en ese campo ...

A partir del orden de los campos en la clave principal, generalmente trato de determinar cómo se usarán en mis consultas: si todas mis consultas utilizan sid y algunas usan sid y qid, entonces elija (sid, qid); si todos usan qid y solo algunos usan sid, entonces elije (qid, sid); si usan sid o qid, entonces tienen un PK (sid, qid) y otra clave (qid), de modo que las consultas con ambos campos usarán su PK, lo mismo ocurrirá con las consultas que usen solo sid, y finalmente aquellos que usan solo qid usarán la tecla (qid).

estoy un poco confundido acerca de la utilización (primaria) obligando a MySQL que no utilice índices, pero que podría ser algo (un error?) Relacionada con su versión de MySQL ..

Aquí se pueden encontrar algunos consejos sobre indicios de índice: http://dev.mysql.com/doc/refman/5.1/en/index-hints.html

En general, intente no meter demasiado con las pistas de índice, ¡el optimizador por lo general hace un buen trabajo! si no lo hace, probablemente haya un error en alguna parte o simplemente considere que un escaneo de tabla es más rápido porque los índices no son lo suficientemente selectivos.

Por otra parte, es posible que a veces estar en necesidad de una optimización de la tabla para actualizar estadísticas de índice .. pero ya que estás usando InnoDB probablemente no es el caso ...

HTH

+0

Ver también este [enlace] (http://www.databasejournal.com/features/mysql/article.php/1382791/Optimizing -MySQL-Queries-and-Indexes.htm) sobre la optimización de consultas de MySQL; está claro y bien escrito en mi opinión – Luke

Cuestiones relacionadas