a nivel de tabla • Soporta índices FULL TEXT SEARCH • No índices entre tablas (JOINS) • No integridad referencial, no es transaccional • Rápido DUMPS & IMPORTS • Recomendado si tienes una tasa muy alta de lecturas & inserts • Se corrompe con más facilidad, recovery más lento • MyISAM Merge: MySQL 5.1 se puede particionar tablas grandes > rendimiento SELECT 6
a nivel de fila + MVCC (row snapshots) • Pueden producirse DEADLOCKS • COUNT(*) no es real debido a multiversiones • COMMIT es lento, OJO! • Muy lento DUMPS & IMPORTS • Más robusto que MyISAM & más rápido reparando • Recomendado si: • Necesitas transacciones • Alto nivel UPDATES & DELETES 7
Muy rápida para hacer queries • Podemos usar para mapear datos • Reinicio… adiós a los datos pero se mantiene estructura • MySQL la usa internamente si una query necesita una tabla temporal. Importante 8
tumbar el server • No hay que obsesionarse! • Percona al rescate! https://tools.percona.com/wizard • Ejemplos ‐> /usr/share/doc/mysql-server-5.X • Herramientas: • mysqlreport: Analiza y resume variables estado • mysqltuner: Asistente optimizar configuración • Google! 10
• slow_query_log = 1 • slow_query_log_file = /log/mysql/mysql- slow.log • Hasta MySQL 5.1.21, queries lentas > 1sg • Parche PERCONA para bajar este tiempo 12
innodb_buffer_pool_size, innodb_additional_memory_pool_size, innodb_log_buffer_size, query_cache_size • Conexiones máximas * 256Kb * • read_buffer_size • sort_buffer_size • read_rnd_buffer_size • tmp_table_size (128M) • Si las consultas son complejas o poco óptimas podemos matar el server 13
bytes + 1/2 byte • Char(10): siempre 10 bytes • BINARY & VARBINARY • Char vs varchar?, cortas y fijas – char • TEXT /BLOB • MySQL los trata como objetos independientes • ORDER BY text = tabla temporal en disco = MUERTE • Parche: ORDER BY SUBSTING(field, length) • ENUM • Muestra STRING, almacena un INT • Mejor controlarlo desde nuestra aplicación 15
más rápidos • ENUM • solo para tablas estáticas • JOINS no tan rápidos • String • Necesita mucho espacio, inserts & selects lentos • Ojo con los randoms • UUID‐> usamos UHEX() /HEX() y guardamos BINARY(16) • JOINS más lentos 17
índices puedan alojarse en memoria • Sirven agilizar búsquedas y ordenaciones • Índice funcionan de izquierda a derecha. • INDEX `user_data` (`apellido`,`nombre`,`fecha_nac`) • ¿Búsquedas de apellidos empiecen por B?: yes! • ¿Búsquedas de BOLUFER y nombre empiecen por D?: yes! • ¿Búsquedas de nombres empiecen por D?: NO! 18
WHERE user_id = 3150 • La consulta tardó sin índice 1,023 seg. No está mal … • La consulta tardó con índice 0,026 seg ¡4000%! 20 id type type keys key_len ref rows Extra 1 SIMPLE ALL NULL NULL NULL 1.012.563 Using where id type type keys key_len ref rows Extra 1 SIMPLE REF user_id 8 CONST 3004
WHERE user_id = 3150 ORDER BY `comment_date` DESC • La consulta tardó sin índice 1,0424 seg • La consulta tardó con índice anterior 0,0417 seg • EXPLAIN ‐> USING WHERE, USING FILESORT • Añadimos índice en comment_date … 0,0403 seg • EXPLAIN ‐> USING WHERE, USING FILESORT • Añadimos índice user_id,comment_date … 0,0253 seg • EXPLAIN ‐> USING WHERE 21
NAGIOS): Monitorización + alertas • PINBA: Monitorización tiempos de ejecución sobre PHP • pt‐collector/pt‐stack: recolectar información en el momento preciso Percona Toolkit 25
Necesitamos procesar el log y agrupar queries. • mk‐query‐digest de Maatkit • mk-query-digest mysqld-slow.log > slow-mayo.log • Qué queries han consumido más tiempo, no las que más veces se han ejecutado • Analiza tiempo ejecución y tiempo de bloqueo • Maatkit ya no se mantiene, Percona Toolkit 26
todas las queries • Buscar donde se define una query, WP es un laberinto • Calcula tiempos de ejecución (queries, cURL, PHP, …) • Uso de REDIS (hited, missed, seted, …) • A parte … usamos XHPROF para analizar la pila de llamadas, uso de tiempo y memoria 27
las queries • Type (de mejor a peor): • const: ID = 1, buscamos por PK o UNIQUE • eq_ref: ID = 1 AND DNI = ‘111X’, buscamos por PK o UNIQUE • ref: user_id=3150, devuelve todas las filas de un índice • range: user_id > 10, devuelve un rango de filas • index: Escaneo completo del índice • all: Escaneo completo de la tabla • Rows: Filas máximas a leer. 28
where = tabla temporal • SELECT SQL_NO_CACHE * FROM wp_1_comments INNER JOIN wp_1_posts ON wp_1_posts.ID = wp_1_comments.comment_post_ID WHERE wp_1_posts.post_author = 3150 AND wp_1_comments.user_id != 3150 ORDER BY wp_1_comments.comment_date DESC • Tiempo ejecución 1,815 seg • Rows: 68.801 • wp_1_posts: using temporary, using filesort • wp_1_comments: using where 29
de las tablas • Mediante un TRIGGER mantenemos actualizados los campos que hemos denormalizado • Tiempo ejecución 0,008 seg • wp_1_posts: using where • ¿Este cambio en producción se nota? 30
usuarios registrados: • Rankings mejores looks del día, mes y año. • COUNT() con un RANGE = MUERTE • ¿Cuantos votos recibe un usuario? COUNT() • ¿Cuantos votos tiene un look? COUNT() ¿Solución? • Proceso cada N que calcula los rankings y actualiza los valores DATO • Si usamos InnoDB, esto es casi una necesidad 32
posible: ejemplo logs/activity • Necesitamos buscar en un campo VARCHAR, ej: URL: • Crear un campo con un hash CRC32(‘http://chicisimo.com’) • Añadimos índice al campo y un TRIGGER para mantener el valor • WHERE url_crc=‘4240669402’ AND url = ‘http://chicisimo.com’ • No utilizar CURRENT_DATE o similares en WHERE, MySQL no las cachea 33