Tengo una tabla de 500 millones de filas (y en crecimiento)
Hice lo siguiente para mejorar el rendimiento de las inserciones:
En el lado de la base de datos:
- eliminó todos los índices y restricciones
- registro deshabilitado
En el lado de la aplicación:
- cambió de entidades administradas por JPA a consultas de inserción nativas, agregó la sugerencia APPEND Oracle a la consulta
- intentó comprometerse en lotes por 1k / 2k / 3k de filas
- Intenté escribir en paralelo (varios subprocesos, recuento de subprocesos = al recuento central en el servidor) en una tabla
Esto me dio alrededor de 300 filas por segundo.
Probado adicionalmente:
- escriba en paralelo en lotes en varias tablas (para agrupar y luego retroceder los resultados usando UNION)
Esto me dio aproximadamente 1k filas por segundo, pero en mesas vacías. Pero cuando llené las tablas con datos ficticios (200 de millones cada uno), la velocidad de las inserciones se redujo a 250 - 300 por segundo.
¿Alguien podría sugerir qué más puedo hacer para acelerar los insertos? Básicamente quiero entender qué es (qué podría ser) el cuello de botella primero.
UPD: la tabla está dividida por fecha de inserción, la tabla tiene aproximadamente 60 columnas; la mayoría de las columnas son VARCHAR2 (2000 BYTE)
/*+APPEND*/
sugerencia se ignora en las inserciones de una sola fila (si no tieneINSERT INTO ... SELECT
, no se moleste en agregar). (3) Debe configurar un ejemplo de SQL * Loaderdirect=true
para establecer una línea base como lo sugiere @parsifal.Respuestas:
Acabo de ver la actualización, tabla de 60 col con campos principalmente VARCHAR (2k), que es (potencialmente) una tabla de monstruos.
Lo primero es lo primero ...
Tienes que entender tu cuello de botella PRIMERO. En el lado de la aplicación, regrese a su solución de inserción por lotes de un solo hilo (1/2 / 3k a la vez) y comience a ejecutarla e inicie sesión en la máquina DB y ejecute una 'parte superior': vea cuánto tiempo que tarda el proceso de DB Y cuánto tiempo (si lo hay) es% de tiempo que muestra la máquina
Si la parte superior le muestra CUALQUIER tiempo de wa%, eso significa que su base de datos está vinculada a E / S y es probable que deba considerar varias máquinas de bases de datos (fragmentos) o considerar lanzar SSD en la máquina host.
Eso es; Su investigación se detiene aquí. No importa la cantidad de CPU que tomaba la base de datos o lo saturada que estaba su aplicación cliente; si tiene problemas de latencia de E / S en la base de datos del host, eso es tan rápido como NUNCA lo hará por usted.
SUGERENCIA Si los cambios de hardware están fuera de discusión, dependiendo del sistema de archivos que esté ejecutando (Linux) puede intentar deshabilitar el registro o la escritura de metadatos para la base de datos para mejorar ligeramente el rendimiento a nivel del sistema de archivos. Puede hacer algo similar en NTFS, pero esto solo le dará un pequeño impulso. Esto no será 2x.
Ahora, lo segundo es lo segundo ...
Digamos que casi no tuvo tiempo de espera, pero su CPU está completamente vinculada por el proceso de DB. Su única opción ahora es introducir más máquinas DB (fragmentos) y dividir el trabajo.
Nuevamente, ha terminado con su investigación si este es el caso. Nada que pueda hacer para ajustar la CPU para que vaya más rápido.
Por último, terceros ... terceros ...
Digamos que el DB no está haciendo mucho de nada. Luego, vaya a la máquina cliente que ejecuta la inserción por lotes y verifique la carga de la CPU: ¿está vinculada? Si es así, encienda algunas máquinas más haciendo exactamente las mismas inserciones de lote y vea si puede obtener una rampa lineal.
Si la CPU no está vinculada, active algunos subprocesos más en la misma máquina hasta que esté vinculada y vea cómo se escala la base de datos.
Creo que ya lo has intentado, así que supongo que tu host cliente ya estaba vinculado (y más hilos no harán la diferencia) o el DB ya estaba llegando a su límite y no puede escalar más.
Apéndice
Hacer inserciones en bruto en una tabla no indexada que no tiene basura es esencialmente una operación APPEND que debería ir tan rápido como el disco pueda manejar las escrituras.
Crear más tablas en la misma máquina host no va a ayudar, en todo caso aumentará la búsqueda de su disco (para llegar a las otras tablas en el disco para agregar) y ralentizará las cosas.
Es fundamental descubrir primero ese cuello de botella, luego podemos optimizarlo al máximo.
¡Espero que ayude! Que nos mantengais.
fuente
Invocar la inserción de ruta directa con la sugerencia de agregar hace que se tome un bloqueo exclusivo en toda la tabla, por lo que tener múltiples hilos que realicen la inserción no será de ayuda. Debería abordar explícitamente una partición diferente con cada inserción ...
... para obtener bloqueos exclusivos a nivel de partición. No podrá hacer eso con una tabla particionada en la fecha de inserción, lo más probable, pero podría usar la partición compuesta (no la subpartición) para obtener múltiples particiones por rango único de fechas de inserción.
No cometas en el medio de los insertos, solo al final.
fuente