Estoy trabajando en una aplicación que involucra muchas escrituras de bases de datos, aproximadamente ~ 70% de inserciones y 30% de lecturas. Esta proporción también incluiría actualizaciones que considero que son una lectura y una escritura. A través de las declaraciones de inserción, varios clientes insertan datos en la base de datos a través de la siguiente declaración de inserción:
$mysqli->prepare("INSERT INTO `track` (user, uniq_name, ad_name, ad_delay_time ) values (?, ?, ?, ?)");
La pregunta es si debería usar insert_delay o mysqli_multi_query mecanismo porque la declaración de inserción utiliza ~ 100% de CPU en el servidor. Estoy usando el motor InnoDB en mi base de datos, por lo que no es posible la inserción retrasada. La inserción en el servidor es de ~ 36k / hr y 99.89% de lectura, también estoy usando la instrucción select para recuperar datos siete veces en una sola consulta , esta consulta tarda 150 segundos en ejecutarse en el servidor. ¿Qué tipo de técnica o mecanismo puedo usar para esta tarea? La memoria de mi servidor es de 2 gb, ¿debería expandir la memoria? Eche un vistazo a este problema, cualquier sugerencia me lo agradecerá.
Estructura de la mesa:
+-----------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user | varchar(100) | NO | | NULL | |
| uniq_name | varchar(200) | NO | | NULL | |
| ad_name | varchar(200) | NO | | NULL | |
| ad_delay_time | int(11) | NO | | NULL | |
| track_time | timestamp | NO | MUL | CURRENT_TIMESTAMP | |
+-----------------+--------------+------+-----+-------------------+----------------+
El estado actual de mi base de datos muestra 41k inserciones (escrituras), lo cual es muy lento para mi base de datos.
SHOW FULL PROCESSLIST
cuando está tomando 100% de CPU? ¿Cuántas conexiones estás permitiendo frente a cuántas se toman durante este tiempo?SHOW GLOBAL VARIABLES LIKE 'innodb%';
ySELECT VERSION();
y muestre su salida.Respuestas:
Como tiene más escrituras que lecturas, me gustaría recomendar lo siguiente
El ajuste decente de InnoDB sería la clave
Buffer Pool (Tamaño por innodb_buffer_pool_size )
Dado que InnoDB no es compatible con INSERT DELAYED , lo más parecido que puede hacer es INSERTAR DELAYED. Todos los DML (INSERTOS, ACTUALIZACIONES y DELETES) se almacenarían en caché en el InnoDB Buffer Pool. La información transaccional para las escrituras se escribe inmediatamente en los registros de rehacer (ib_logfile0, ib_logfile1). Las escrituras que se publican en el Grupo de búferes se vacían periódicamente de la memoria al disco a través de ibdata1 (InsertBuffer para índices secundarios, búfer de doble escritura). Cuanto más grande sea el Buffer Pool, mayor será la cantidad de INSERTs que se pueden almacenar en caché. En un sistema con 8 GB o más de RAM, use el 75-80% de la RAM como innodb_buffer_pool_size. En un sistema con muy poca RAM, 25% (para acomodar el sistema operativo).
PRECAUCIÓN: puede establecer innodb_doublewrite en 0 para acelerar aún más las escrituras, pero a riesgo de la integridad de los datos. También puede acelerar las cosas configurando innodb_flush_method en O_DIRECT para evitar el almacenamiento en caché de InnoDB en el sistema operativo.
Rehacer registros ( dimensionado por innodb_log_file_size )
De forma predeterminada, los registros de rehacer se denominan ib_logfile0 e ib_logfile1 y serían 5MB cada uno. El tamaño debe ser del 25% de innodb_buffer_pool_size. Si los registros de rehacer ya existen, agregue la nueva configuración en my.cnf, cierre mysql, elimínelos y reinicie mysql .
Buffer de registro ( dimensionado por innodb_log_buffer_size )
El búfer de registro contiene cambios en la RAM antes de enjuagarlos en los registros de rehacer. El valor predeterminado es 8M. Cuanto mayor sea el búfer de registro, menor será la E / S de disco. Tenga cuidado con las transacciones muy grandes, ya que esto puede ralentizar los COMPROMISOS por milisegundos.
Acceso a múltiples CPU
MySQL 5.5 y MySQL 5.1 InnoDB Plugin tienen configuraciones para que InnoDB Storage Engine acceda a múltiples CPU. Estas son las opciones que debe configurar:
Actualizar a MySQL 5.5
Si tiene MySQL 5.0, actualice a MySQL 5.5. Si tiene MySQL 5.1.37 o anterior, actualice a MySQL 5.5. Si tiene MySQL 5.1.38 o superior y desea permanecer en MySQL 5.1, instale el complemento InnoDB. De esa manera, puede aprovechar todas las CPU para InnoDB.
fuente
INT (2) todavía usa 4 bytes, ¿tal vez quisiste decir TINYINT SIN FIRMAR?
¿Cuántos valores diferentes hay en setno? Si es pequeño, la CLAVE (setno) nunca se utilizará. INSERTing tiene que actualizar ese índice; quitar la CLAVE acelerará INSERTAR un poco.
CHAR (10) - ¿
flag
Siempre tiene 10 caracteres de longitud? ¿Y en utf8? Quizás podría usar flag VARCHAR (10) CHARACTER SET asciiLote sus insertos: 100 a la vez se ejecutarán 10 veces más rápido. (Más allá de 100 se está metiendo en 'rendimientos decrecientes').
¿Cuál es el valor de la confirmación automática? ¿Estás envolviendo cada INSERTAR en COMENZAR ... COMPROMISO? ¿Cuál es el valor de innodb_flush_log_at_trx_commit?
fuente
code
insertar en los valores t_name (col1, col2, col3) (val1, val2, val3), (val1, val2, val3), (val1, val2, val3), (val1, val2, val3), (val1, val2, val3);code
Establecer una cola. La aplicación escribiría en una fila de fila 1 a la vez y luego sacaría filas e insertaría en una base de datos en lote según el número de filas o la cantidad de tiempo transcurrido desde la última inserción.
He visto dónde es más rápido agrupar los insertos 10,000 a la vez, por lo que deberá realizar una prueba para encontrar un punto óptimo.
Puede crear su propio sistema de cola simple o usar uno existente. Aquí hay algunos ejemplos: HornetQ y File :: Queue . Aquí hay una publicación en SE que enumera algunas otras buenas opciones: Colas de mensajes en perl, php, python .
fuente