Comparación de velocidad de base de datos

Nota: este documento es muy antiguo. Describe una comparación de velocidad entre versiones arcaicas de SQLite, MySQL y PostgreSQL.

Los números aquí se han vuelto insignificantes. Esta página se ha conservado solo como un artefacto histórico.

Resumen ejecutivo

Se ejecutaron una serie de pruebas para medir el rendimiento relativo de SQLite 2.7.6, PostgreSQL 7.1.3 y MySQL 3.23.41. Las siguientes son conclusiones generales extraídas de estos experimentos:

  • SQLite 2.7.6 es significativamente más rápido (a veces hasta 10 o 20 veces más rápido) que la instalación predeterminada de PostgreSQL 7.1.3 en RedHat 7.2 para las operaciones más comunes.

  • SQLite 2.7.6 es a menudo más rápido (a veces más del doble) que MySQL 3.23.41 para las operaciones más comunes.

  • SQLite no ejecuta CREATE INDEX o DROP TABLE tan rápido como las otras bases de datos. Pero esto no se ve como un problema porque son operaciones poco frecuentes.

  • SQLite funciona mejor si agrupa varias operaciones en una sola transacción.

Los resultados presentados aquí vienen con las siguientes advertencias:

  • Estas pruebas no intentaron medir el rendimiento de múltiples usuarios ni la optimización de consultas complejas que implican múltiples combinaciones y subconsultas.

  • Estas pruebas se encuentran en una base de datos relativamente pequeña (aproximadamente 14 megabytes). No miden qué tan bien escalan los motores de la base de datos a problemas más grandes.

Entorno de prueba

La plataforma utilizada para estas pruebas es un Athlon de 1,6 GHz con 1 GB de memoria y una unidad de disco IDE. El sistema operativo es RedHat Linux 7.2 con un kernel estándar.

Los servidores PostgreSQL y MySQL utilizados fueron los que se entregaron de forma predeterminada en RedHat 7.2. (PostgreSQL versión 7.1.3 y MySQL versión 3.23.41.) No se hizo ningún esfuerzo para ajustar estos motores. Tenga en cuenta en particular que la configuración predeterminada de MySQL en RedHat 7.2 no admite transacciones. No tener que admitir transacciones le da a MySQL una gran ventaja de velocidad, pero SQLite aún puede mantenerse firme en la mayoría de las pruebas.

Me han dicho que la configuración predeterminada de PostgreSQL en RedHat 7.3 es innecesariamente conservadora (está diseñada para funcionar en una máquina con 8 MB de RAM) y que PostgreSQL podría ejecutarse mucho más rápido con algunos ajustes de configuración bien informados. Matt Sergeant informa que ha ajustado su instalación de PostgreSQL y ha vuelto a ejecutar las pruebas que se muestran a continuación. Sus resultados muestran que PostgreSQL y MySQL se ejecutan aproximadamente a la misma velocidad. Para ver los resultados de Matt, visite

http://www.sergeant.org/sqlite_vs_pgsync.html

SQLite se probó con la misma configuración que aparece en el sitio web. Fue compilado con la optimización -O6 y con el modificador -DNDEBUG = 1 que deshabilita las muchas declaraciones “assert ()” en el código SQLite. La opción del compilador -DNDEBUG = 1 duplica aproximadamente la velocidad de SQLite.

Todas las pruebas se realizan en una máquina que de otro modo estaría inactiva. Se utilizó un script Tcl simple para generar y ejecutar todas las pruebas. Se puede encontrar una copia de este script Tcl en el árbol de fuentes de SQLite en el archivo herramientas / speedtest.tcl.

Los tiempos informados en todas las pruebas representan el tiempo de reloj de pared en segundos. Se informan dos valores de tiempo separados para SQLite. El primer valor es para SQLite en su configuración predeterminada con la sincronización de disco completa activada. Con la sincronización activada, SQLite ejecuta un fsync () llamada al sistema (o el equivalente) en key puntos para asegurarse de que los datos críticos se hayan escrito realmente en la superficie de la unidad de disco. La sincronización es necesaria para garantizar la integridad de la base de datos si el sistema operativo falla o la computadora se apaga inesperadamente en medio de una actualización de la base de datos. La segunda vez que se informa para SQLite es cuando la sincronización está desactivada. Con la sincronización desactivada, SQLite a veces es mucho más rápido, pero existe el riesgo de que una falla del sistema operativo o una falla de energía inesperada pueda dañar la base de datos. En términos generales, los tiempos de SQLite síncronos son para compararlos con PostgreSQL (que también es síncrono) y los tiempos de SQLite asíncronos son para compararlos con el motor MySQL asíncrono.

Prueba 1: 1000 INSERTOS

CREAR TABLA t1 (a INTEGER, b INTEGER, c VARCHAR (100));
INSÉRTESE EN t1 VALORES (1,13153, ‘trece mil ciento cincuenta y tres’);
INSÉRTESE EN t1 VALORES (2,75560, ‘setenta y cinco mil quinientos sesenta’);
… 995 líneas omitidas
INSÉRTESE EN t1 VALORES (998,66289, ‘sesenta y seis mil doscientos ochenta y nueve’);
INSÉRTESE EN t1 VALORES (999,24322, ‘veinticuatro mil trescientos veintidós’);
INSÉRTESE EN t1 VALORES (1000,94142, ‘noventa y cuatro mil ciento cuarenta y dos’);

PostgreSQL: 4.373
MySQL: 0,114
SQLite 2.7.6: 13.061
SQLite 2.7.6 (nosync): 0,223

Debido a que no tiene un servidor central para coordinar el acceso, SQLite debe cerrar y volver a abrir el archivo de la base de datos, y así invalidar su caché, para cada transacción. En esta prueba, cada declaración SQL es una transacción separada, por lo que el archivo de la base de datos debe abrirse y cerrarse y la caché debe vaciarse 1000 veces. A pesar de esto, la versión asincrónica de SQLite sigue siendo casi tan rápida como MySQL. Sin embargo, observe cuánto más lenta es la versión sincrónica. Llamadas SQLite fsync () después de cada transacción síncrona para asegurarse de que todos los datos estén seguros en la superficie del disco antes de continuar. Durante la mayor parte de los 13 segundos de la prueba síncrona, SQLite estuvo inactivo esperando que se completara la E / S del disco.

Prueba 2: 25000 INSERT en una transacción

EMPEZAR;
CREAR TABLA t2 (a INTEGER, b INTEGER, c VARCHAR (100));
INSÉRTESE EN t2 VALORES (1,59672, ‘cincuenta y nueve mil seiscientos setenta y dos’);
… 24997 líneas omitidas
INSÉRTESE EN t2 VALORES (24999,89569, ‘ochenta y nueve mil quinientos sesenta y nueve’);
INSERTAR EN t2 VALORES (25000,94666, ‘noventa y cuatro mil seiscientos sesenta y seis’);
COMETER;

PostgreSQL: 4.900
MySQL: 2.184
SQLite 2.7.6: 0,914
SQLite 2.7.6 (nosync): 0,757

Cuando todos los INSERT se colocan en una transacción, SQLite ya no tiene que cerrar y volver a abrir la base de datos o invalidar su caché entre cada declaración. Tampoco tiene que hacer ningún fsync () s hasta el final. Cuando se desencadena de esta manera, SQLite es mucho más rápido que PostgreSQL y MySQL.

Prueba 3: 25000 INSERTOS en una tabla indexada

EMPEZAR;
CREAR TABLA t3 (a INTEGER, b INTEGER, c VARCHAR (100));
CREAR ÍNDICE i3 EN t3 (c);
… 24998 líneas omitidas
INSÉRTESE EN t3 VALORES (24999,88509, ‘ochenta y ocho mil quinientos nueve’);
INSÉRTESE EN t3 VALORES (25000,84791, ‘ochenta y cuatro mil setecientos noventa y uno’);
COMETER;

PostgreSQL: 8.175
MySQL: 3.197
SQLite 2.7.6: 1,555
SQLite 2.7.6 (nosync): 1.402

Hubo informes de que SQLite no funcionó tan bien en una tabla indexada. Esta prueba se agregó recientemente para refutar esos rumores. Está true que SQLite no es tan rápido en la creación de nuevas entradas de índice como los otros motores (consulte la Prueba 6 a continuación), pero su velocidad general es aún mejor.

Prueba 4: 100 SELECT sin índice

EMPEZAR;
SELECCIONAR recuento
avg (b) DESDE t2 DONDE b> = 0 Y b <1000;
SELECCIONAR recuento
avg (b) DESDE t2 DONDE b> = 100 Y b <1100;
… 96 líneas omitidas
SELECCIONAR recuento

avg (b) DESDE t2 DONDE b> = 9800 Y b <10800; SELECCIONAR recuento
avg (b) DESDE t2 DONDE b> = 9900 Y b <10900; COMETER;
PostgreSQL: 3.629
MySQL: 2.760

SQLite 2.7.6:

2.494 string SQLite 2.7.6 (nosync):

2.526
Esta prueba realiza 100 consultas en una tabla de 25000 entradas sin un índice, por lo que requiere un escaneo completo de la tabla. Las versiones anteriores de SQLite solían ser más lentas que PostgreSQL y MySQL en esta prueba, pero las recientes mejoras de rendimiento han aumentado su velocidad, por lo que ahora es la más rápida del grupo.
Prueba 5: 100 SELECT en un
comparación
EMPEZAR;
SELECCIONAR recuento
avg (b) DESDE t2 DONDE c LIKE ‘% one%’;

SELECCIONAR recuento avg (b) DESDE t2 DONDE c COMO ‘% dos%’;
… 96 líneas omitidas SELECCIONAR recuento
avg (b) DESDE t2 DONDE c LIKE ‘% noventa y nueve%’; SELECCIONAR recuento
avg (b) DESDE t2 DONDE c LIKE ‘% cien%’; COMETER;

PostgreSQL: string 13.409

MySQL:

4.640
SQLite 2.7.6:

3.362 SQLite 2.7.6 (nosync):
3.372 Esta prueba todavía hace 100 escaneos completos de tablas, pero usa usos
comparaciones en lugar de comparaciones numéricas. SQLite es tres veces más rápido que PostgreSQL aquí y aproximadamente un 30% más rápido que MySQL. Prueba 6: creación de un índice
CREAR ÍNDICE i2a EN t2 (a); CREAR ÍNDICE i2b EN t2 (b);

PostgreSQL:

0.381

MySQL:
0.318
SQLite 2.7.6:
0,777
SQLite 2.7.6 (nosync):
0,659
SQLite es más lento para crear nuevos índices. Este no es un gran problema (ya que no se crean índices nuevos muy a menudo) pero es algo en lo que se está trabajando. Con suerte, las futuras versiones de SQLite funcionarán mejor aquí.

Prueba 7: 5000 SELECT con un índice SELECCIONAR recuento
avg (b) DESDE t2 DONDE b> = 0 Y b <100; SELECCIONAR recuento
avg (b) DESDE t2 DONDE b> = 100 Y b <200; SELECCIONAR recuento
avg (b) DESDE t2 DONDE b> = 200 Y b <300; … 4994 líneas omitidas

SELECCIONAR recuento

avg (b) DESDE t2 DONDE b> = 499700 Y b <499800;

SELECCIONAR recuento, avg (b) DESDE t2 DONDE b> = 499800 Y b <499900; SELECCIONAR recuento, avg (b) DESDE t2 DONDE b> = 499900 Y b <500000; PostgreSQL: 4.614 MySQL: 1.270 SQLite 2.7.6: 1.121 SQLite 2.7.6 (nosync): 1,162 Los tres motores de base de datos se ejecutan más rápido cuando tienen índices con los que trabajar. Pero SQLite sigue siendo el más rápido. Prueba 8: 1000 ACTUALIZACIONES sin índice EMPEZAR;
ACTUALIZAR t1 SET b = b * 2 DONDE a> = 0 Y a <10;
ACTUALIZAR t1 SET b = b * 2 DONDE a> = 10 Y a <20;
… 996 líneas omitidas
ACTUALIZAR t1 SET b = b * 2 DONDE a> = 9980 Y a <9990;
ACTUALIZAR t1 SET b = b * 2 DONDE a> = 9990 Y a <10000;
COMETER;

PostgreSQL: 1.739
MySQL: 8.410
SQLite 2.7.6: 0,637
SQLite 2.7.6 (nosync): 0,638

Para esta prueba de ACTUALIZACIÓN en particular, MySQL es consistentemente cinco o diez veces más lento que PostgreSQL y SQLite. Yo no sé por qué. MySQL es normalmente un motor muy rápido. Quizás este problema se haya abordado en versiones posteriores de MySQL.

Prueba 9: 25000 ACTUALIZACIONES con un índice

EMPEZAR;
ACTUALIZAR t2 SET b = 468026 DONDE a = 1;
ACTUALIZAR t2 SET b = 121928 DONDE a = 2;
… 24996 líneas omitidas
ACTUALIZAR t2 SET b = 35065 DONDE a = 24999;
ACTUALIZAR t2 SET b = 347393 DONDE a = 25000;
COMETER;

PostgreSQL: 18.797
MySQL: 8.134
SQLite 2.7.6: 3.520
SQLite 2.7.6 (nosync): 3.104

Tan recientemente como la versión 2.7.0, SQLite se ejecutó aproximadamente a la misma velocidad que MySQL en esta prueba. Pero las optimizaciones recientes de SQLite tienen más del doble de velocidad de ACTUALIZACIONES.

Prueba 10: 25000 ACTUALIZACIONES de texto con un índice

EMPEZAR;
ACTUALIZAR t2 SET c = ‘ciento cuarenta y ocho mil trescientos ochenta y dos’ DONDE a = 1;
ACTUALIZAR t2 SET c = ‘trescientos sesenta y seis mil quinientos dos’ DONDE a = 2;
… 24996 líneas omitidas
ACTUALIZAR t2 SET c = ‘trescientos ochenta y tres mil noventa y nueve’ DONDE a = 24999;
ACTUALIZAR t2 SET c = ‘doscientos cincuenta y seis mil ochocientos treinta’ DONDE a = 25000;
COMETER;

PostgreSQL: 48.133
MySQL: 6.982
SQLite 2.7.6: 2.408
SQLite 2.7.6 (nosync): 1.725

Aquí nuevamente, la versión 2.7.0 de SQLite solía ejecutarse aproximadamente a la misma velocidad que MySQL. Pero ahora la versión 2.7.6 es dos veces más rápida que MySQL y veinte veces más rápida que PostgreSQL.

Para ser justos con PostgreSQL, comenzó a fallar en esta prueba. Un administrador experto podría hacer que PostgreSQL se ejecute mucho más rápido aquí ajustando y ajustando un poco el servidor.

Prueba 11: INSERTOS de un SELECT

EMPEZAR;
INSERT INTO t1 SELECT b, a, c FROM t2;
INSERT INTO t2 SELECT b, a, c FROM t1;
COMETER;

PostgreSQL: 61.364
MySQL: 1.537
SQLite 2.7.6: 2.787
SQLite 2.7.6 (nosync): 1.599

El SQLite asincrónico es solo un poco más lento que MySQL en esta prueba. (MySQL parece ser especialmente experto en instrucciones INSERT … SELECT). El motor PostgreSQL todavía está funcionando: la mayor parte de los 61 segundos que usó se pasaron esperando en la E / S del disco.

Prueba 12: BORRAR sin índice

BORRAR DE t2 DONDE c LIKE ‘% cincuenta%’;

PostgreSQL: 1,509
MySQL: 0,975
SQLite 2.7.6: 4.004
SQLite 2.7.6 (nosync): 0.560

La versión sincrónica de SQLite es la más lenta del grupo en esta prueba, pero la versión asincrónica es la más rápida. La diferencia es el tiempo extra necesario para ejecutar fsync ().

Prueba 13: BORRAR con un índice

BORRAR DE t2 DONDE a> 10 Y a <20000;

PostgreSQL: 1.316
MySQL: 2.262
SQLite 2.7.6: 2.068
SQLite 2.7.6 (nosync): 0,752

Esta prueba es significativa porque es una de las pocas en las que PostgreSQL es más rápido que MySQL. Sin embargo, el SQLite asincrónico es más rápido que los otros dos.

Prueba 14: un INSERT grande después de un DELETE grande

INSERT INTO t2 SELECT * FROM t1;

PostgreSQL: 13.168
MySQL: 1.815
SQLite 2.7.6: 3.210
SQLite 2.7.6 (nosync): 1,485

Algunas versiones anteriores de SQLite (anteriores a la versión 2.4.0) mostrarían un rendimiento decreciente después de una secuencia de DELETE seguida de nuevos INSERT. Como muestra esta prueba, el problema ya se ha resuelto.

Prueba 15: un BORRAR grande seguido de muchos INSERTOS pequeños

EMPEZAR;
BORRAR DE t1;
INSÉRTESE EN t1 VALORES (1,10719, ‘diez mil setecientos diecinueve’);
… 11997 líneas omitidas
INSÉRTESE EN t1 VALORES (11999,72836, ‘setenta y dos mil ochocientos treinta y seis’);
INSÉRTESE EN t1 VALORES (12000,64231, ‘sesenta y cuatro mil doscientos treinta y uno’);
COMETER;

PostgreSQL: 4.556
MySQL: 1.704
SQLite 2.7.6: 0,618
SQLite 2.7.6 (nosync): 0.406

SQLite es muy bueno para hacer INSERT dentro de una transacción, lo que probablemente explica por qué es mucho más rápido que las otras bases de datos en esta prueba.

Prueba 16: TABLA DE GOTA

TABLA DROP t1;
DROP TABLE t2;
TABLA DROP t3;

PostgreSQL: 0,135
MySQL: 0,015
SQLite 2.7.6: 0,939
SQLite 2.7.6 (nosync): 0,254

SQLite es más lento que las otras bases de datos cuando se trata de eliminar tablas. Esto probablemente se deba a que cuando SQLite deja caer una tabla, tiene que revisar y borrar los registros en el archivo de base de datos que tratan con esa tabla. MySQL y PostgreSQL, por otro lado, usan archivos separados para representar cada tabla, de modo que puedan eliminar una tabla simplemente eliminando un archivo, lo cual es mucho más rápido.

Por otro lado, eliminar tablas no es una operación muy común, por lo que si SQLite demora un poco más, eso no se ve como un gran problema.