6. 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)
7. 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)
8. UNIQUE KEY
• Mismas optimizaciones que la clave primaria
• Tamaño promedio del grupo de valor 1
10. 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)
11. Columnas múltiples
• Alternativa: hashing
ALTER TABLE ADD [UNIQUE] INDEX hash
(hash);
INSERT INTO users SET first=‘Pompa’,
last=‘Borges’,
hash=md5(‘PompaBorges’);
12. 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
13. EXPLAIN
• EXPLAIN nos sirve para corroborar que una
consulta se esté ejecutando como esperamos
que ejecute
14. EXPLAIN
> explain select Id from votes where PostId=23452635G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: votes
type: ref
possible_keys: postid
key: postid
key_len: 4
ref: const
rows: 5
Extra: Using index
1 row in set (0.04 sec)
15. 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
16. 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 |
+------+-------------+-------+------+---------------+--------+---------+---------------+--------+-------------+
17. 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
18. 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.
19. > 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 | |
+------+-------------+-------+--------+---------------+---------+---------+---------------------------------+---------+-------+
20. 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.
21. 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
22. > 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 |
+------+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
23. Referencias
• MySQL 5.7 manual
• http://dev.mysql.com/doc/refman/
5.7/
• High Performance MySQL 3rd edition
!
Ignacio Nin
(@nachexnachex)