Índices en mysql

23
Índices en MySQL

Upload: ignacio-nin

Post on 18-Jun-2015

168 views

Category:

Technology


0 download

DESCRIPTION

Una charla introductoria sobre índices

TRANSCRIPT

Page 1: Índices en MySQL

Índices en MySQL

Page 2: Índices en MySQL

— @fedesilva, Tech Meetup 2012

“Todo programador debe ser un sysadmin competente."

Page 3: Índices en MySQL

Optimización

Asignar los índices correctos es la forma mas eficiente de optimizar

• 10% del trabajo

• 90% de los resultados

Page 4: Índices en MySQL

Índices

• MSSQL puede auto asignar los índices de acuerdo a estadísticas de uso

• MySQL

• Usualmente manual

• De acuerdo a los casos de uso

Page 5: Índices en MySQL

Regla rápida

• Columnas usadas en la cláusula WHERE

• Columnas con las que se hacen JOINs

Page 6: Índices en MySQL

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)

Page 7: Índices en MySQL

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)

Page 8: Índices en MySQL

UNIQUE KEY

• Mismas optimizaciones que la clave primaria

• Tamaño promedio del grupo de valor 1

Page 9: Índices en MySQL

FOREIGN KEY

• Usamos la clave desde otra tabla

• Restricciones de negocio

• :)

Page 10: Índices en MySQL

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)

Page 11: Índices en MySQL

Columnas múltiples

• Alternativa: hashing

ALTER TABLE ADD [UNIQUE] INDEX hash (hash);

INSERT INTO users SET first=‘Pompa’, last=‘Borges’, hash=md5(‘PompaBorges’);

Page 12: Índices en MySQL

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

Page 13: Índices en MySQL

EXPLAIN

• EXPLAIN nos sirve para corroborar que una consulta se esté ejecutando como esperamos que ejecute

Page 14: Índices en MySQL

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)

Page 15: Índices en MySQL

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

Page 16: Índices en MySQL

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 |+------+-------------+-------+------+---------------+--------+---------+---------------+--------+-------------+

Page 17: Índices en MySQL

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

Page 18: Índices en MySQL

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.

Page 19: Índices en MySQL

> 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 | |+------+-------------+-------+--------+---------------+---------+---------+---------------------------------+---------+-------+

Page 20: Índices en MySQL

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.

Page 21: Índices en MySQL

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

Page 22: Índices en MySQL

> 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 |+------+-------------+-------+------+---------------+---------+---------+-------+------+-------------+

Page 23: Índices en MySQL

Referencias• MySQL 5.7 manual

• http://dev.mysql.com/doc/refman/5.7/

• High Performance MySQL 3rd edition

!

Ignacio Nin(@nachexnachex)