sql >> Base de Datos >  >> RDS >> SQLite

Ajuste del rendimiento de SQLite

SQLite es una base de datos relacional popular que usted integra en su aplicación. Con una cantidad cada vez mayor de datos en su base de datos, debe aplicar el ajuste de rendimiento de SQLite. En este artículo se analizan los índices y sus peligros, el uso del planificador de consultas, el modo de diario Write-Ahead-Logging (WAL) y el aumento del tamaño de la memoria caché. También explica la importancia de medir el impacto de tus ajustes mediante pruebas automatizadas.

Introducción

SQLite es un popular sistema de base de datos relacional (DB) . A diferencia de sus hermanos mayores basados ​​en cliente-servidor, como MySQL, SQLite se puede integrar en su aplicación como una biblioteca . SQLite tiene un conjunto de funciones muy similar y también puede manejar millones de filas, dado que conoce algunos consejos y trucos sobre el ajuste del rendimiento. Como se mostrará en las siguientes secciones, hay más que saber sobre el ajuste del rendimiento de SQLite que solo crear índices.

Crear índices, pero con precaución

La idea básica de un índice es acelerar la lectura de datos específicos , es decir, SELECT declaraciones con WHERE cláusula. Los índices también aceleran la clasificación datos (ORDER BY ), o JOIN mesas de trabajo. Lamentablemente, los índices son un arma de doble filo, ya que consumen espacio adicional en el disco y ralentizan la manipulación de datos (INSERT , UPDATE , DELETE ).

El consejo general es crear la menor cantidad de índices posible, pero tantos como sea necesario . Además, los índices solo tienen sentido para grandes bases de datos, con miles o millones de filas.

Utilice el planificador de consultas para analizar sus consultas

La forma en que SQLite usa los índices internamente está documentada, pero no es muy fácil de entender. Como se explica más detalladamente en este artículo, es una buena idea analizar una consulta prefijándola con EXPLAIN QUERY PLAN . Eche un vistazo a cada línea de salida, de las cuales hay tres variantes básicas:

  • SEARCH table ... las líneas son una buena señal:¡SQLite usa uno de sus índices!
  • SCAN table ... USING INDEX es mala señal,
  • SCAN table ... es aún peor!

Trate de evitar SCAN table [using index] entradas en la salida de EXPLAIN QUERY PLAN siempre que sea posible, porque se encontrará con problemas de rendimiento en bases de datos más grandes. Utilice EXPLAIN QUERY PLAN para agregar iterativamente o modificar sus índices hasta que no haya más SCAN table aparecen las entradas.

Optimizar consultas que implican IS NOT

Comprobar IS NOT ... es caro porque SQLite tendrá que escanear todas las filas de la tabla, incluso si la columna afectada tiene un índice . Los índices solo son útiles si busca valores específicos, es decir, comparaciones que involucran < (más pequeño), > (mayor), o = (igual), pero no aplican para !=(desigual).

Un pequeño truco es que puedes reemplazar WHERE column != value con WHERE column > value OR column < value . Esto usará el índice de la columna y afectará efectivamente a todas las filas cuyo valor no sea igual a value . De manera similar, un WHERE stringColumn != '' puede ser reemplazado por WHERE stringColumn > '' , porque las cadenas se pueden ordenar. Sin embargo, al aplicar este truco, asegúrese de saber cómo maneja SQLite NULL comparaciones Por ejemplo, SQLite evalúa NULL > '' como FALSE .

Si usa un truco de comparación de este tipo, hay otra advertencia en caso de que su consulta contenga WHERE y ORDER BY , cada uno con una columna diferente:esto hará que la consulta vuelva a ser ineficaz. Si es posible, use el mismo columna en WHERE y ORDER BY o crea un índice de cobertura que involucra tanto el WHERE y ORDER BY columna.

Mejore la velocidad de escritura con Write-Ahead-Log

El registro de escritura anticipada (WAL) el modo diario mejora significativamente el rendimiento de escritura/actualización , en comparación con la reversión predeterminada modo diario. Sin embargo, como se documenta aquí, hay algunas advertencias . Por ejemplo, el modo WAL no está disponible en ciertos sistemas operativos. Además, existen garantías de consistencia de datos reducidas en caso de falla del hardware . Asegúrese de leer las primeras páginas para comprender lo que está haciendo.

Encontré que el comando PRAGMA synchronous = NORMAL proporciona una aceleración de 3-4x. Configuración de journal_mode a WAL luego vuelve a mejorar significativamente el rendimiento (aproximadamente 10 veces o más, según el sistema operativo).

Además de las advertencias que ya mencioné, también debe tener en cuenta lo siguiente:

  • Usando el modo diario WAL, habrá dos archivos adicionales al lado del archivo de la base de datos en su sistema de archivos, que tienen el mismo nombre que la base de datos, pero con el sufijo "-shm" y "-wal". Normalmente no necesita preocuparse, pero si enviara la base de datos a otra máquina mientras su aplicación se está ejecutando, no olvide incluir esos dos archivos. SQLite compactará estos dos archivos en el archivo principal cada vez que cierre todas las conexiones de bases de datos abiertas.
  • El rendimiento de inserción o actualización disminuirá ocasionalmente, cada vez que la consulta desencadene la fusión del contenido del archivo de registro WAL en el archivo de la base de datos principal. Esto se llama puntos de control , ver aquí.
  • Encontré que PRAGMA s que cambian journal_mode y synchronous no parecen estar persistentemente almacenados en la base de datos. Por lo tanto, siempre volver a ejecutarlos cada vez que abra una nueva conexión a la base de datos, en lugar de simplemente ejecutarlos al crear las tablas por primera vez.

Mide todo

Siempre que agregue ajustes de rendimiento, asegúrese de medir el impacto. Las pruebas (unitarias) automatizadas son un gran enfoque para esto. Ayudan a documentar sus hallazgos para su equipo, y ellos descubrirán comportamientos desviados con el tiempo , p.ej. cuando actualiza a una versión más nueva de SQLite. Ejemplos de lo que puede medir:

  • ¿Cuál es el efecto de usar el WAL modo diario sobre el rollback ¿modo? ¿Cuál es el efecto de otros PRAGMA (supuestamente) que mejoran el rendimiento? s?
  • Una vez que agrega/cambia/elimina un índice, ¿qué tan rápido SELECT declaraciones se convierten? ¿Cuánto más lento INSERT/DELETE/UPDATE declaraciones se convierten?
  • ¿Cuánto espacio de disco adicional consumen los índices?

Para cualquiera de estas pruebas, considere repetirlas con diferentes tamaños de bases de datos. P.ej. ejecútelos en una base de datos vacía y también en una base de datos que ya contiene miles (o millones) de entradas. También debe ejecutar las pruebas en diferentes dispositivos y sistemas operativos, especialmente si su entorno de desarrollo y producción es sustancialmente diferente.

Ajuste el tamaño de caché

SQLite almacena información temporal en un caché (en la RAM), p. mientras construye los resultados de un SELECT consulta, o al manipular datos que aún no se han confirmado. Por defecto, este tamaño es de unos míseros 2 MB . Las máquinas de escritorio modernas pueden ahorrar mucho más. Ejecute PRAGMA cache_size = -kibibytes para aumentar este valor (Cuidado con el menos firmar delante del valor!). Consulte aquí para obtener más información. De nuevo, medir ¡Qué impacto tiene esta configuración en el rendimiento!

Utilice REPLACE INTO para crear o actualizar una fila

Esto puede no ser tanto un ajuste de rendimiento como un pequeño truco. Supongamos que necesita actualizar una fila en la tabla t o crear una fila si aún no existe. En lugar de usar dos consultas (SELECT seguido de INSERT o UPDATE ), use el REPLACE INTO (documentos oficiales).

Para que esto funcione, agregue una columna ficticia adicional (por ejemplo, replacer ) a la tabla t , que tiene un UNIQUE constreñir. La declaración de la columna podría, p. ser ... replacer INTEGER UNIQUE ... eso es parte de tu CREATE TABLE declaración. Luego use una consulta como

REPLACE INTO t (col1, col2, ..., replacer) VALUES (?,?,...,1)Code language: SQL (Structured Query Language) (sql)

Cuando esta consulta se ejecuta por primera vez, simplemente realizará un INSERT . Cuando se ejecuta por segunda vez, UNIQUE restricción del replacer se activará y el comportamiento de resolución de conflictos hará que se elimine la fila anterior, creando una nueva automáticamente. También puede encontrar útil el comando UPSERT relacionado.

Conclusión

Una vez que crece el número de filas en su base de datos, los ajustes de rendimiento se vuelven una necesidad. Los índices son la solución más común. Cambian la complejidad del tiempo mejorada por la complejidad del espacio reducida, mejorando las velocidades de lectura, mientras afectan negativamente el rendimiento de la modificación de datos. R He demostrado que debe tener mucho cuidado al comparar desigualdad en SELECT declaraciones, porque SQLite no puede usar índices para este tipo de comparaciones. En general, recomiendo usar el planificador de consultas eso explica lo que sucede internamente para cada consulta SQL. Cada vez que modifiques algo, ¡mide el impacto!