Upload
ignacio-nin
View
168
Download
0
Embed Size (px)
DESCRIPTION
Una charla introductoria sobre índices
Citation preview
Índices en MySQL
— @fedesilva, Tech Meetup 2012
“Todo programador debe ser un sysadmin competente."
Optimización
Asignar los índices correctos es la forma mas eficiente de optimizar
• 10% del trabajo
• 90% de los resultados
Índices
• MSSQL puede auto asignar los índices de acuerdo a estadísticas de uso
• MySQL
• Usualmente manual
• De acuerdo a los casos de uso
Regla rápida
• Columnas usadas en la cláusula WHERE
• Columnas con las que se hacen JOINs
Regla rápida> select SQL_NO_CACHE count(*) from posts join users on users.Id = posts.OwnerUserId where users.age > 30;+----------+| count(*) |+----------+| 27887 |+----------+1 row in set (0.20 sec)!> alter table posts add index owner (OwnerUserId);!> select SQL_NO_CACHE count(*) from posts join users on users.Id = posts.OwnerUserId where users.age > 30;+----------+| count(*) |+----------+| 27887 |+----------+1 row in set (0.11 sec)!> alter table users add index age (Age);!> select SQL_NO_CACHE count(*) from posts join users on users.Id = posts.OwnerUserId where users.age > 30;+----------+| count(*) |+----------+| 27887 |+----------+1 row in set (0.06 sec)
PRIMARY KEY
• Única
• InnoDB: Los datos se ordenan en el disco de acuerdo a su clave primaria
• Si no hay una clave obvia, conviene agregar una columna arbitraria, auto_increment (90% de los casos)
UNIQUE KEY
• Mismas optimizaciones que la clave primaria
• Tamaño promedio del grupo de valor 1
FOREIGN KEY
• Usamos la clave desde otra tabla
• Restricciones de negocio
• :)
Columnas múltiples
• Se pueden usar parcialmente, pero sólo de izquierda a derecha (prefijo):
(2,1,1)(2,1,2)(2,2,0)(2,2,1)(2,3,0)(3,1,2)
Columnas múltiples
• Alternativa: hashing
ALTER TABLE ADD [UNIQUE] INDEX hash (hash);
INSERT INTO users SET first=‘Pompa’, last=‘Borges’, hash=md5(‘PompaBorges’);
NULL
• (NULL = x) es falso para todo x, inclusive NULL
• Al recorrer un índice usando los operadores no relacionados con NULL, se ignoran las filas con índice de valor NULL
• Necesitamos <=>, IS NULL, etc., para analizarlas
EXPLAIN
• EXPLAIN nos sirve para corroborar que una consulta se esté ejecutando como esperamos que ejecute
EXPLAIN> explain select Id from votes where PostId=23452635\G *************************** 1. row ***************************id: 1select_type: SIMPLE table: votestype: ref possible_keys: postidkey: postidkey_len: 4ref: const rows: 5Extra: Using index1 row in set (0.04 sec)
EXPLAIN: rows
• Es una estimación de cuántas filas van a ser leídas en la tabla
• Si el producto de todos los rows es demasiado grande, probablemente estemos usando índices equivocados
EXPLAIN: rows
> explain select count(*) from votes join posts on votes.PostId = posts.Id where posts.Score > 10;+------+-------------+-------+--------+---------------+---------+---------+-------------------+--------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+------+-------------+-------+--------+---------------+---------+---------+-------------------+--------+-------------+| 1 | SIMPLE | votes | ALL | NULL | NULL | NULL | NULL | 427399 | || 1 | SIMPLE | posts | eq_ref | PRIMARY | PRIMARY | 4 | unix.votes.PostId | 1 | Using where |+———+-------------+-------+--------+---------------+---------+---------+-------------------+--------+-------------+!> alter table votes add index postid (PostId);> analyze table votes;!> explain select count(*) from votes join posts on votes.PostId = posts.Id where posts.Score > 10;+------+-------------+-------+------+---------------+--------+---------+---------------+--------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+------+-------------+-------+------+---------------+--------+---------+---------------+--------+-------------+| 1 | SIMPLE | posts | ALL | PRIMARY | NULL | NULL | NULL | 134217 | Using where || 1 | SIMPLE | votes | ref | postid | postid | 4 | unix.posts.Id | 2 | Using index |+------+-------------+-------+------+---------------+--------+---------+---------------+--------+-------------+
EXPLAIN: key y ref• possible_keys lista las claves candidatas.
• La clave usada es elegida en base a estadísticas de las tablas.
• ref nos muestra contra qué columna ó constante se compara el índice.
• Nos sirve para corroborar que el JOIN se ejecute como pensamos que es mejor
EXPLAIN: type• const/system: A lo sumo una fila coincidente
• eq_ref: A lo sumo una fila es leída por cada combinación de las tablas anteriores. Aparece cuando se usa todo el índice y es PRIMARY/UNIQUE.
• ref: Todas las filas de cada valor coincidente a la combinación de las tablas anteriores es leída.
• ref_or_null: Ídem, pero con una pasa extra para NULL
• range: Se consulta un rango específico del índice (<, BETWEEN)
• ALL: #FAIL!
• index: Ídem, pero hay un índice que proporciona los datos. Muestra “Using index” en Extra.
> explain select DisplayName from users where Id = 60;+------+-------------+-------+-------+---------------+---------+---------+-------+------+-------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+------+-------------+-------+-------+---------------+---------+---------+-------+------+-------+| 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | |+———+-------------+-------+-------+---------------+---------+---------+-------+------+-------+!> explain select DisplayName from users where AccountId = 60;+------+-------------+-------+------+---------------+---------+---------+-------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+------+-------------+-------+------+---------------+---------+---------+-------+------+-------------+| 1 | SIMPLE | users | ref | accname | accname | 4 | const | 1 | Using index |+———+-------------+-------+------+---------------+---------+---------+-------+------+-------------+!> explain select * from posts join users on users.Id = posts.OwnerUserId;+------+-------------+-------+--------+---------------+---------+---------+---------------------------------+---------+-------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+------+-------------+-------+--------+---------------+---------+---------+---------------------------------+---------+-------+| 1 | SIMPLE | posts | ALL | NULL | NULL | NULL | NULL | 9011718 | || 1 | SIMPLE | users | eq_ref | PRIMARY | PRIMARY | 4 | stackoverflow.posts.OwnerUserId | 1 | |+------+-------------+-------+--------+---------------+---------+---------+---------------------------------+---------+-------+
EXPLAIN: Extra• Using filesort
• Se está ejecutando una pasada adicional para ordenar filas
• Using index [for group by]
• Infame denominación
• Se está usando el índice para obtener los resultados (no necesariamente para recorrer la tabla).
• Using temporary
• Se necesita una tabla temporal para resolver GROUP BY/ORDER BY.
• Using where
• Se está filtrando las filas luego de seleccionadas
• Tiene que aparecer si es ALL/index, a no ser que queramos un full table scan.
Covering indexes• El índice tiene una copia del dato
• Cuando todos los datos de la consulta se pueden extraer del índice, no es necesario analizar la fila
• Se evitan locking, búsquedas en disco, etc.
• Lo vemos en la salida de EXPLAIN como
• type de ref hacia arriba (ref, const, etc.)
• “Using index” en Extra
> explain select AccountId, DisplayName, Age from users where AccountId = 67;+------+-------------+-------+------+---------------+---------+---------+-------+------+-------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+------+-------------+-------+------+---------------+---------+---------+-------+------+-------+| 1 | SIMPLE | users | ref | accname | accname | 4 | const | 1 | |+———+-------------+-------+------+---------------+---------+---------+-------+------+-------+!> explain select AccountId, DisplayName from users where AccountId = 67;+------+-------------+-------+------+---------------+---------+---------+-------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+------+-------------+-------+------+---------------+---------+---------+-------+------+-------------+| 1 | SIMPLE | users | ref | accname | accname | 4 | const | 1 | Using index |+------+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
Referencias• MySQL 5.7 manual
• http://dev.mysql.com/doc/refman/5.7/
• High Performance MySQL 3rd edition
!
Ignacio Nin(@nachexnachex)