Slow INSERT en la tabla InnoDB con el valor aleatorio de la columna PRIMARY KEY
Para mi sitio web, uso la API de PHP para Flickr http: //www.flickr.com/services/api). Esta API proporciona varios métodos útiles para obtener fotos en posiciones GPS particulares.
La llamada a los métodos API se ve como URL con parámetros específicos como latitud, longitud, clave API, radio, clasificación, etc. Digamos que se verá comohttp://api.flickr.com/method?lat=0.0&lon=0.0&radius=10
Mi sitio web realiza más de 200,000 llamadas a API para generar varias páginas con imágenes de Flickr. Es un empuje duro en API, por lo tanto, creé un caché de resultados en la base de datos mySQL.
l esquema simplificado de la tabla InnoDB con caché es:
char(32) request
datetime expires // 2-3 days
text response // serialized data from API response
dónderequest
es una CLAVE PRIMARIA y representa un hash MD5 de un URI de solicitud. Otros campos son bastante simples:)
El problema surge cuando la tabla se vuelve lo suficientemente grande, digamos más de 100,000 filas. NuevoINSERTs
tome hasta 2 segundos (y hasta 6 (!) segundos con 1,000,000 de filas).
Por lo que yo entiendo, el problema es que el ÍNDICE PRIMARIO y el motor son InnoDB. Cada vez que se inserta una nueva solicitud, el motor InnoDB reconstruye el índice de árbol y mueve los datos, porque MD5 (solicitud) es un valor realmente aleatorio.
Entonces ... La pregunta es si hay una mejor manera de almacenar en caché tales solicitudes. ¿O tal vez debería cambiar al motor MyISAM? ¿O tal vez debería intentar pseudo-particionar y crear varias tablas para resolver el problema? ¿O simplemente puede usar no un índice BTREE sino HASH?
¡Cualquier idea es bienvenida!
Editar
Ok, traté de alterar la mesa como sugirieron Furicane y Johan, pero aún así no tuve suerte: INSERTAR toma hasta 3 segundos. Actualmenterequest
l campo @ se convirtió en un índice no único normal y en un nuevoid
a columna @ se ha agregado como CLAVE PRIMARIA con incremento automático. También intenté agregar 4 particiones en esta tabla con los mismos resultados.
Creo que el índice enrequest
field sigue siendo un cuello de botella. La única forma que veo actualmente es determinar todos los parámetros posibles, agregarlos como columnas a una tabla y luego crear un índice en ellos.
¿Alguna otra idea? :)
Edit 2:
Salman A en los comentarios a continuación dijo que su tabla similar funciona mucho mejor (~ 0.03 para insertar). Este puede ser el problema en la carga de E / S en el sistema. Aunque no puedo cargar mucho en él.
iostat
resultados:
avg-cpu: %user %nice %system %iowait %steal %idle
22.94 0.71 8.42 8.50 0.00 59.43
Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
sda 38.01 151.04 114.32 1383655437 1047309046
iotop
resultados:
Total DISK READ: 152.91 K/s | Total DISK WRITE: 197.67 K/s
Con mySQL en la parte superior de la lista tanto para escribir como para leer. ¿Quizás mis discos están casi muertos? ¿Cómo puedo verificar el rendimiento de los discos?