MyISAM versus InnoDB [cerrado]

857

Estoy trabajando en un proyecto que involucra muchas escrituras de bases de datos, diría ( 70% de inserciones y 30% de lecturas ). Esta proporción también incluiría actualizaciones que considero una lectura y una escritura. Las lecturas pueden estar sucias (por ejemplo, no necesito información 100% precisa en el momento de la lectura).
La tarea en cuestión será realizar más de 1 millón de transacciones de base de datos por hora.

He leído un montón de cosas en la web sobre las diferencias entre MyISAM e InnoDB, y MyISAM me parece la opción obvia para la base de datos / tablas en particular que usaré para esta tarea. Por lo que parece estar leyendo, InnoDB es bueno si se necesitan transacciones ya que se admite el bloqueo de nivel de fila.

¿Alguien tiene alguna experiencia con este tipo de carga (o superior)? ¿MyISAM es el camino a seguir?

usuario2013
fuente
13
El Blog de rendimiento de MySQL es un gran recurso para este tipo de cosas.
ceejayoz
3
Esto dependería un poco de si su sistema está OLTP o está más orientado al datawarehouse (donde la mayoría de las escrituras están cargando en masa).
nos
35
MyISAM no admite el bloqueo de filas, las transacciones, ni siquiera admite claves externas ... demonios, ya que no puede proporcionar ACID , ¡casi ni siquiera puede considerarse una base de datos adecuada! Es por eso que InnoDB ha sido el motor predeterminado desde MySQL 5.5 ... pero, por alguna razón, MyISAM continúa siendo el motor predeterminado para las tablas creadas dentro de PhpMyAdmin, por lo que muchas bases de datos de aficionados se ejecutan en MyISAM.
BlueRaja - Danny Pflughoeft
Ver todos los motores MySql DB comparados
Somnath Muluk

Respuestas:

523

He discutido brevemente esta pregunta en una tabla para que pueda concluir si debe ir con InnoDB o MyISAM .

Aquí hay una pequeña descripción de qué motor de almacenamiento db debe usar en qué situación:

                                                 MyISAM InnoDB
-------------------------------------------------- --------------
Búsqueda de texto completo requerida Sí 5.6.4
-------------------------------------------------- --------------
Requerir transacciones Sí
-------------------------------------------------- --------------
Consultas de selección frecuente Sí      
-------------------------------------------------- --------------
Insertar, actualizar, eliminar con frecuencia Sí
-------------------------------------------------- --------------
Bloqueo de fila (procesamiento múltiple en una sola tabla) Sí
-------------------------------------------------- --------------
Diseño de base relacional Sí

Resumen

  • En casi todas las circunstancias, InnoDB es el mejor camino a seguir.
  • Pero, lectura frecuente, casi sin escritura, use MyISAM
  • Búsqueda de texto completo en MySQL <= 5.5, use MyISAM
desarrollador99
fuente
11
InnoDB tiene índices de texto completo en MySQL 5.6, pero hasta ahora, no están realmente listos para su uso en producción.
Bill Karwin
3
De acuerdo a 12.9. Funciones de búsqueda de texto completo , "Los índices de texto completo solo se pueden usar con tablas InnoDB o MyISAM". Parece correcto para MySQL> = 5.6, sin embargo, la misma página para MySQL 5.5 todavía dice "Los índices de texto completo solo se pueden usar con tablas MyISAM". La tabla anterior podría actualizarse para indicar cómo difiere con las versiones de MySQL. Desafortunadamente, hasta ahora, MySQL 5.5 parece ser el estándar.
Hibou57
2
¿Qué significa: InnoDB - full-text: 5.6.4?? ¿Es sí o no?
2
MyISAM también almacena el recuento de filas internamente. Por lo tanto, la función Count () es casi gratuita en MyISAM, mientras que lleva una cantidad de tiempo notable en InnoDB.
Hedeshy
3
buena mesa, pero agregando una fila para la calidad y la estabilidad, MyIsam = no, innoDB = sí lo haría aún mejor
pilavdzice
268

No soy un experto en bases de datos, y no hablo por experiencia. Sin embargo:

Las tablas MyISAM usan bloqueo a nivel de tabla . Según sus estimaciones de tráfico, tiene cerca de 200 escrituras por segundo. Con MyISAM, solo uno de estos podría estar en progreso en cualquier momento . Debe asegurarse de que su hardware pueda mantenerse al día con estas transacciones para evitar que se desborde, es decir, una sola consulta no puede llevar más de 5 ms.

Eso me sugiere que necesitaría un motor de almacenamiento que admita el bloqueo de nivel de fila, es decir, InnoDB.

Por otro lado, debería ser bastante trivial escribir algunos scripts simples para simular la carga con cada motor de almacenamiento, luego comparar los resultados.

rix0rrr
fuente
12
Cerca de 200? Si su transacción promedio realiza 2.5 consultas, eso es [(2.5 * 1M) / 3600s =] más cercano a 700.
Ozzy
12
También estoy en desacuerdo a single query can take no more than 5msporque hiciste 2 suposiciones poco probables; A: todas las consultas necesitaban la misma tabla y B: ¡solo había 1 conexión disponible! Debo informarle que una configuración de Linux y MySQL 5.5 con RAM alta puede admitir hasta 10,000 conexiones simultáneas (consulte: dev.mysql.com/doc/refman//5.5/en/too-many-connections.html )
Ozzy
152
Cuando una tabla está bloqueada, solo se puede ejecutar una consulta a la vez. No importa si el servidor admite 10000 conexiones simultáneas, cada una se respaldará mientras la tabla esté bloqueada.
Ryaner
2
También podría ser útil saber que MyISAM admite el índice espacial mientras que InnoDB no. Y MyISAM no parece usar claves foráneas aunque no impide crear una.
kriver
44
@kriver: no puede tener claves foráneas en las tablas MyISAM. Puede incluir definiciones FK en las instrucciones CREATE TABLE pero ellas (las definiciones) simplemente se ignoran.
ypercubeᵀᴹ
191

La gente a menudo habla sobre el rendimiento, las lecturas frente a las escrituras, las claves externas, etc. pero en mi opinión hay otra característica imprescindible para un motor de almacenamiento: las actualizaciones atómicas.

Prueba esto:

  1. Emita una ACTUALIZACIÓN en su tabla MyISAM que demore 5 segundos.
  2. Mientras la ACTUALIZACIÓN está en progreso, digamos 2.5 segundos, presione Ctrl-C para interrumpirla.
  3. Observa los efectos sobre la mesa. ¿Cuántas filas se actualizaron? ¿Cuántos no se actualizaron? ¿La tabla es incluso legible o se dañó cuando presionó Ctrl-C?
  4. Pruebe el mismo experimento con ACTUALIZAR en una tabla InnoDB, interrumpiendo la consulta en curso.
  5. Observe la tabla InnoDB. Se actualizaron cero filas. InnoDB ha asegurado que tiene actualizaciones atómicas, y si no se pudo confirmar la actualización completa, revierte todo el cambio. Además, la tabla no está corrupta. Esto funciona incluso si se usa killall -9 mysqldpara simular un bloqueo.

El rendimiento es deseable, por supuesto, pero no perder datos debería superar eso.

Bill Karwin
fuente
44
Para el registro, MyISAM tampoco admite las otras características de una base de datos ACID: consistencia, aislamiento y durabilidad.
Bill Karwin
Control-C no debe corromper la tabla, como en CHECK TABLE devolverá el éxito y todas las consultas continuarán sin errores. MyISAM abortará la actualización sin actualizar todos los registros, pero la tabla mantendrá la integridad estructural interna. Matar mysqld con SIGTERM tendrá el mismo efecto. Sin embargo, si le das SIGKILL (kill -9) o alguna señal de bloqueo (o lo gana por sí solo cuando choca con un error), o si el sistema operativo se bloquea / se pierde energía, entonces es una historia diferente: puedes ver Corrupción a nivel MyISAM.
Sasha Pachev
1
InnoDB también puede corromperse de manera real, generalmente más real que MyISAM cuando lo hace. La ironía de ACID es que tenemos la noción de todo o nada. Entonces, cuando InnoDB no puede darlo todo, no da nada, afirmación interna, y se niega a ejecutarse porque un byte en alguna estructura es incorrecto, el 90% del tiempo podría haberse ignorado y, como mucho, afectaría solo una tabla. Los servidores recientes de Percona tienen la opción de manejarlo: innodb_pass_corrupt_table.
Sasha Pachev
1
Estaba buscando este tipo de información de los últimos 3 días, ahora tengo esto. InnoDB es el mejor. GraciasBill Karwin
user3833682
3
@ flow2k, casi ninguno en estos días. En mi último trabajo utilizamos MyISAM para una tabla en un servidor, y la única razón fue que MyISAM pudo almacenar esa tabla específica en menos espacio del que tendría InnoDB. Estábamos limitados en el espacio en disco, por lo que tuvimos que usar MyISAM hasta que pudimos mover la base de datos a otro servidor. En mi nuevo trabajo, ya existe una política de que cada tabla debe ser InnoDB.
Bill Karwin
138

Trabajé en un sistema de alto volumen usando MySQL y probé tanto MyISAM como InnoDB.

Descubrí que el bloqueo a nivel de tabla en MyISAM causaba serios problemas de rendimiento para nuestra carga de trabajo que suena similar a la suya. Desafortunadamente, también encontré que el rendimiento bajo InnoDB también fue peor de lo que esperaba.

Al final, resolví el problema de contención fragmentando los datos de modo que las inserciones entraran en una tabla "activa" y las selecciones nunca consultaran la tabla activa.

Esto también permitió que se produjeran eliminaciones (los datos eran urgentes y solo conservamos X días) en tablas "obsoletas" que nuevamente no fueron tocadas por consultas seleccionadas. InnoDB parece tener un bajo rendimiento en las eliminaciones masivas, por lo que si planea purgar datos, es posible que desee estructurarlos de tal manera que los datos antiguos estén en una tabla obsoleta que simplemente se puede eliminar en lugar de ejecutar eliminaciones en ella.

Por supuesto, no tengo idea de cuál es su aplicación, pero espero que esto le dé una idea de algunos de los problemas con MyISAM e InnoDB.

alanc10n
fuente
3
'Al final he resuelto el problema de contención al fragmentar los datos de tal manera que los insertos entraron en una mesa 'caliente' y selecciona nunca se pusieron en duda la mesa caliente ". - No es que esencialmente lo que un grupo de búfer es para?
BlueRaja - Danny Pflughoeft
15
Danny - No, en realidad no. Ajustar la configuración del servidor es importante, pero de ninguna manera es un sustituto de una estructuración cuidadosa de su esquema. Si tiene una base de datos mucho más grande que la RAM disponible y patrones de acceso que tocan datos aleatoriamente en toda la base de datos, entonces todo el ajuste del grupo de búferes en el mundo no lo ayudará. Si comprende los datos y los patrones de acceso, puede mitigar gran parte del dolor mediante un diseño cuidadoso.
alanc10n
66

Un poco tarde para el juego ... pero aquí hay una publicación bastante completa que escribí hace unos meses , que detalla las principales diferencias entre MYISAM e InnoDB. Agarra una cuppa (y tal vez una galleta) y disfruta.


La principal diferencia entre MyISAM e InnoDB está en la integridad referencial y las transacciones. También hay otra diferencia, como bloqueo, reversiones y búsquedas de texto completo.

Integridad referencial

La integridad referencial asegura que las relaciones entre las tablas se mantengan consistentes. Más específicamente, esto significa que cuando una tabla (p. Ej., Listados) tiene una clave externa (p. Ej., ID de producto) que apunta a una tabla diferente (p. Ej., Productos), cuando se producen actualizaciones o eliminaciones en la tabla señalada, estos cambios se conectan en cascada al enlace mesa. En nuestro ejemplo, si se cambia el nombre de un producto, las claves externas de la tabla de enlace también se actualizarán; Si un producto se elimina de la tabla 'Productos', también se eliminará cualquier listado que apunte a la entrada eliminada. Además, cualquier listado nuevo debe tener esa clave externa que apunte a una entrada válida y existente.

InnoDB es un DBMS relacional (RDBMS) y, por lo tanto, tiene integridad referencial, mientras que MyISAM no.

Transacciones y Atomicidad

Los datos en una tabla se administran utilizando instrucciones del lenguaje de manipulación de datos (DML), como SELECT, INSERT, UPDATE y DELETE. Una transacción agrupa dos o más sentencias DML en una sola unidad de trabajo, por lo que se aplica la unidad completa o no se aplica ninguna.

MyISAM no admite transacciones, mientras que InnoDB sí.

Si se interrumpe una operación mientras se usa una tabla MyISAM, la operación se interrumpe inmediatamente y las filas (o incluso los datos dentro de cada fila) que se ven afectados permanecen afectados, incluso si la operación no se completó.

Si se interrumpe una operación mientras se usa una tabla InnoDB, debido a que usa transacciones, que tiene atomicidad, cualquier transacción que no se haya completado no tendrá efecto, ya que no se realiza ninguna confirmación.

Bloqueo de mesa vs bloqueo de fila

Cuando una consulta se ejecuta en una tabla MyISAM, se bloqueará toda la tabla en la que se está consultando. Esto significa que las consultas posteriores solo se ejecutarán una vez que finalice la actual. Si está leyendo una tabla grande, y / o hay operaciones frecuentes de lectura y escritura, esto puede significar una gran acumulación de consultas.

Cuando una consulta se ejecuta en una tabla InnoDB, solo las filas involucradas están bloqueadas, el resto de la tabla permanece disponible para operaciones CRUD. Esto significa que las consultas pueden ejecutarse simultáneamente en la misma tabla, siempre que no utilicen la misma fila.

Esta característica en InnoDB se conoce como concurrencia. Por grande que sea la concurrencia, hay un inconveniente importante que se aplica a un rango selecto de tablas, ya que hay una sobrecarga al cambiar entre hilos del kernel, y debe establecer un límite en los hilos del kernel para evitar que el servidor se detenga .

Transacciones y Rollbacks

Cuando ejecuta una operación en MyISAM, se establecen los cambios; en InnoDB, esos cambios pueden revertirse. Los comandos más comunes utilizados para controlar las transacciones son COMMIT, ROLLBACK y SAVEPOINT. 1. COMMIT: puede escribir varias operaciones DML, pero los cambios solo se guardarán cuando se realice un COMMIT 2. ROLLBACK: puede descartar cualquier operación que aún no se haya confirmado 3. SAVEPOINT: establece un punto en la lista de operaciones a las que una operación ROLLBACK puede revertir a

Fiabilidad

MyISAM no ofrece integridad de datos: las fallas de hardware, los cierres sucios y las operaciones canceladas pueden provocar que los datos se corrompan. Esto requeriría una reparación completa o reconstrucciones de los índices y las tablas.

InnoDB, por otro lado, utiliza un registro de transacciones, un búfer de doble escritura y suma de verificación y validación automáticas para evitar la corrupción. Antes de que InnoDB realice ningún cambio, registra los datos antes de las transacciones en un archivo de espacio de tabla del sistema llamado ibdata1. Si hay un bloqueo, InnoDB se recuperaría automáticamente mediante la reproducción de esos registros.

Indexación FULLTEXT

InnoDB no admite la indexación FULLTEXT hasta MySQL versión 5.6.4. Al momento de escribir esta publicación, la versión MySQL de muchos proveedores de alojamiento compartido todavía está por debajo de 5.6.4, lo que significa que la indexación FULLTEXT no es compatible con las tablas InnoDB.

Sin embargo, esta no es una razón válida para usar MyISAM. Es mejor cambiar a un proveedor de alojamiento que admita versiones actualizadas de MySQL. No es que una tabla MyISAM que utiliza la indexación FULLTEXT no pueda convertirse en una tabla InnoDB.

Conclusión

En conclusión, InnoDB debería ser su motor de almacenamiento predeterminado preferido. Elija MyISAM u otros tipos de datos cuando satisfagan una necesidad específica.

d4nyll
fuente
Estaba haciendo un script de suma de comprobación de sesión php y la mayor parte de mi clave son cadenas aleatorias de [az09] ... Innodb tardó más de 30 ms en hacer una, INSERT ON DUPLICATE KEY UPDATEasí que probé MyISAM y ahora se reduce a <1ms ... Muchas respuestas que vi dicen que innodb tiene dificultades para lidiar con teclas únicas 'no ordenables' (cadena aleatoria) ... ¿Tiene alguna entrada para nosotros en eso? De hecho, me preguntaba sobre el impacto que tendría usar MyISAM, pero su excelente respuesta me hizo darme cuenta de que era el camino a seguir para ese caso en particular.
Louis Loudog Trottier
64

Para una carga con más escrituras y lecturas, se beneficiará de InnoDB. Debido a que InnoDB proporciona bloqueo de fila en lugar de bloqueo de tabla, sus SELECTcorreos electrónicos pueden ser concurrentes, no solo entre sí, sino también con muchos INSERTcorreos electrónicos. Sin embargo, a menos que tenga la intención de utilizar transacciones SQL, establezca el vaciado de confirmación InnoDB en 2 ( innodb_flush_log_at_trx_commit ). Esto le devuelve una gran cantidad de rendimiento bruto que de otro modo perdería al mover tablas de MyISAM a InnoDB.

Además, considere agregar replicación. Esto le da un poco de escala de lectura y, dado que declaró que sus lecturas no tienen que estar actualizadas, puede dejar que la replicación se retrase un poco. Solo asegúrese de que pueda atrapar debajo de cualquier cosa que no sea el tráfico más pesado o siempre estará detrás y nunca se pondrá al día. Sin embargo, si sigue este camino, le recomiendo encarecidamente que aísle la lectura de los esclavos y la gestión del retraso de la replicación en su manejador de base de datos. Es mucho más simple si el código de la aplicación no lo sabe.

Finalmente, tenga en cuenta las diferentes cargas de la mesa. No tendrá la misma relación de lectura / escritura en todas las tablas. Algunas tablas más pequeñas con lecturas cercanas al 100% podrían permitirse mantener MyISAM. Del mismo modo, si tiene algunas tablas que están cerca del 100% de escritura, puede beneficiarse INSERT DELAYED, pero eso solo es compatible con MyISAM (la DELAYEDcláusula se ignora para una tabla InnoDB).

Pero punto de referencia para estar seguro.

staticsan
fuente
44
¿Es el "InnoDB commit flush" al que se refiere innodb_flush_log_at_trx_commit?
ceejayoz
2
Tu publicación me pareció muy útil, gracias. Actualmente evaluando cuándo usar MyISAM / InnoDB para mis tablas y su publicación fue útil. Salud.
starmonkey
2
dev.mysql.com/doc/refman/5.5/en/insert-delayed.html declara: Para las tablas MyISAM, si no hay bloques libres en el medio del archivo de datos, se admiten las declaraciones concurrentes SELECT e INSERT. En estas circunstancias, rara vez necesita usar INSERT DELAYED con MyISAM.
tymtam
Publicación muy informativa. Tenía la misma pregunta que las operaciones y debo decir que su publicación me ha tranquilizado sobre la decisión de mi motor de base de datos. ¡Gracias! ++
Joe Majewski
Nota rápida: la demora ya no se admite en 5.7. Es posible que desee probar con LOW_PRIORITY en su lugar.
webmat
59

Para agregar a la amplia selección de respuestas que cubren las diferencias mecánicas entre los dos motores, presento un estudio empírico de comparación de velocidad.

En términos de velocidad pura, no siempre es el caso de que MyISAM sea más rápido que InnoDB, pero en mi experiencia tiende a ser más rápido para entornos de trabajo PURE READ en un factor de aproximadamente 2.0-2.5 veces. Claramente, esto no es apropiado para todos los entornos: como otros han escrito, MyISAM carece de cosas como transacciones y claves foráneas.

He hecho un poco de evaluación comparativa a continuación: he usado python para bucles y la biblioteca timeit para comparaciones de temporización. Por interés, también he incluido el motor de memoria, que ofrece el mejor rendimiento en todos los ámbitos, aunque solo es adecuado para tablas más pequeñas (se encuentra continuamente The table 'tbl' is fullcuando excede el límite de memoria de MySQL). Los cuatro tipos de selección que miro son:

  1. SELECTs de vainilla
  2. cuenta
  3. SELECT condicionales
  4. subselecciones indexadas y no indexadas

Primero, creé tres tablas usando el siguiente SQL

CREATE TABLE
    data_interrogation.test_table_myisam
    (
        index_col BIGINT NOT NULL AUTO_INCREMENT,
        value1 DOUBLE,
        value2 DOUBLE,
        value3 DOUBLE,
        value4 DOUBLE,
        PRIMARY KEY (index_col)
    )
    ENGINE=MyISAM DEFAULT CHARSET=utf8

con 'MyISAM' sustituido por 'InnoDB' y 'memoria' en las tablas segunda y tercera.

 

1) Vanilla selecciona

Consulta: SELECT * FROM tbl WHERE index_col = xx

Resultado: empate

Comparación de selecciones de vainilla por diferentes motores de bases de datos

La velocidad de estos es, en general, la misma, y ​​como se espera es lineal en el número de columnas que se seleccionarán. InnoDB parece un poco más rápido que MyISAM pero esto es realmente marginal.

Código:

import timeit
import MySQLdb
import MySQLdb.cursors
import random
from random import randint

db = MySQLdb.connect(host="...", user="...", passwd="...", db="...", cursorclass=MySQLdb.cursors.DictCursor)
cur = db.cursor()

lengthOfTable = 100000

# Fill up the tables with random data
for x in xrange(lengthOfTable):
    rand1 = random.random()
    rand2 = random.random()
    rand3 = random.random()
    rand4 = random.random()

    insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

    cur.execute(insertString)
    cur.execute(insertString2)
    cur.execute(insertString3)

db.commit()

# Define a function to pull a certain number of records from these tables
def selectRandomRecords(testTable,numberOfRecords):

    for x in xrange(numberOfRecords):
        rand1 = randint(0,lengthOfTable)

        selectString = "SELECT * FROM " + testTable + " WHERE index_col = " + str(rand1)
        cur.execute(selectString)

setupString = "from __main__ import selectRandomRecords"

# Test time taken using timeit
myisam_times = []
innodb_times = []
memory_times = []

for theLength in [3,10,30,100,300,1000,3000,10000]:

    innodb_times.append( timeit.timeit('selectRandomRecords("test_table_innodb",' + str(theLength) + ')', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('selectRandomRecords("test_table_myisam",' + str(theLength) + ')', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('selectRandomRecords("test_table_memory",' + str(theLength) + ')', number=100, setup=setupString) )

 

2) cuenta

Consulta: SELECT count(*) FROM tbl

Resultado: MyISAM gana

Comparación de conteos por diferentes motores de bases de datos.

Éste demuestra una gran diferencia entre MyISAM e InnoDB: MyISAM (y la memoria) realiza un seguimiento del número de registros en la tabla, por lo que esta transacción es rápida y O (1). La cantidad de tiempo requerida para que InnoDB cuente aumenta de forma superlineal con el tamaño de la tabla en el rango que investigué. Sospecho que muchas de las aceleraciones de las consultas MyISAM que se observan en la práctica se deben a efectos similares.

Código:

myisam_times = []
innodb_times = []
memory_times = []

# Define a function to count the records
def countRecords(testTable):

    selectString = "SELECT count(*) FROM " + testTable
    cur.execute(selectString)

setupString = "from __main__ import countRecords"

# Truncate the tables and re-fill with a set amount of data
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE test_table_innodb"
    truncateString2 = "TRUNCATE test_table_myisam"
    truncateString3 = "TRUNCATE test_table_memory"

    cur.execute(truncateString)
    cur.execute(truncateString2)
    cur.execute(truncateString3)

    for x in xrange(theLength):
        rand1 = random.random()
        rand2 = random.random()
        rand3 = random.random()
        rand4 = random.random()

        insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)
        cur.execute(insertString3)

    db.commit()

    # Count and time the query
    innodb_times.append( timeit.timeit('countRecords("test_table_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('countRecords("test_table_myisam")', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('countRecords("test_table_memory")', number=100, setup=setupString) )

 

3) selecciones condicionales

Consulta: SELECT * FROM tbl WHERE value1<0.5 AND value2<0.5 AND value3<0.5 AND value4<0.5

Resultado: MyISAM gana

Comparación de selecciones condicionales por diferentes motores de bases de datos

Aquí, MyISAM y la memoria funcionan aproximadamente igual, y superan a InnoDB en aproximadamente un 50% para tablas más grandes. Este es el tipo de consulta para la cual los beneficios de MyISAM parecen ser maximizados.

Código:

myisam_times = []
innodb_times = []
memory_times = []

# Define a function to perform conditional selects
def conditionalSelect(testTable):
    selectString = "SELECT * FROM " + testTable + " WHERE value1 < 0.5 AND value2 < 0.5 AND value3 < 0.5 AND value4 < 0.5"
    cur.execute(selectString)

setupString = "from __main__ import conditionalSelect"

# Truncate the tables and re-fill with a set amount of data
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE test_table_innodb"
    truncateString2 = "TRUNCATE test_table_myisam"
    truncateString3 = "TRUNCATE test_table_memory"

    cur.execute(truncateString)
    cur.execute(truncateString2)
    cur.execute(truncateString3)

    for x in xrange(theLength):
        rand1 = random.random()
        rand2 = random.random()
        rand3 = random.random()
        rand4 = random.random()

        insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)
        cur.execute(insertString3)

    db.commit()

    # Count and time the query
    innodb_times.append( timeit.timeit('conditionalSelect("test_table_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('conditionalSelect("test_table_myisam")', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('conditionalSelect("test_table_memory")', number=100, setup=setupString) )

 

4) Sub-selecciona

Resultado: InnoDB gana

Para esta consulta, creé un conjunto adicional de tablas para la sub-selección. Cada uno es simplemente dos columnas de BIGINT, una con un índice de clave principal y otra sin ningún índice. Debido al gran tamaño de la tabla, no probé el motor de memoria. El comando de creación de la tabla SQL fue

CREATE TABLE
    subselect_myisam
    (
        index_col bigint NOT NULL,
        non_index_col bigint,
        PRIMARY KEY (index_col)
    )
    ENGINE=MyISAM DEFAULT CHARSET=utf8;

donde una vez más, 'MyISAM' se sustituye por 'InnoDB' en la segunda tabla.

En esta consulta, dejo el tamaño de la tabla de selección en 1000000 y, en cambio, varío el tamaño de las columnas subseleccionadas.

Comparación de sub-selecciones por diferentes motores de bases de datos.

Aquí el InnoDB gana fácilmente. Después de llegar a una tabla de tamaño razonable, ambos motores se escalan linealmente con el tamaño de la sub-selección. El índice acelera el comando MyISAM pero, curiosamente, tiene poco efecto en la velocidad de InnoDB. subSelect.png

Código:

myisam_times = []
innodb_times = []
myisam_times_2 = []
innodb_times_2 = []

def subSelectRecordsIndexed(testTable,testSubSelect):
    selectString = "SELECT * FROM " + testTable + " WHERE index_col in ( SELECT index_col FROM " + testSubSelect + " )"
    cur.execute(selectString)

setupString = "from __main__ import subSelectRecordsIndexed"

def subSelectRecordsNotIndexed(testTable,testSubSelect):
    selectString = "SELECT * FROM " + testTable + " WHERE index_col in ( SELECT non_index_col FROM " + testSubSelect + " )"
    cur.execute(selectString)

setupString2 = "from __main__ import subSelectRecordsNotIndexed"

# Truncate the old tables, and re-fill with 1000000 records
truncateString = "TRUNCATE test_table_innodb"
truncateString2 = "TRUNCATE test_table_myisam"

cur.execute(truncateString)
cur.execute(truncateString2)

lengthOfTable = 1000000

# Fill up the tables with random data
for x in xrange(lengthOfTable):
    rand1 = random.random()
    rand2 = random.random()
    rand3 = random.random()
    rand4 = random.random()

    insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

    cur.execute(insertString)
    cur.execute(insertString2)

for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE subselect_innodb"
    truncateString2 = "TRUNCATE subselect_myisam"

    cur.execute(truncateString)
    cur.execute(truncateString2)

    # For each length, empty the table and re-fill it with random data
    rand_sample = sorted(random.sample(xrange(lengthOfTable), theLength))
    rand_sample_2 = random.sample(xrange(lengthOfTable), theLength)

    for (the_value_1,the_value_2) in zip(rand_sample,rand_sample_2):
        insertString = "INSERT INTO subselect_innodb (index_col,non_index_col) VALUES (" + str(the_value_1) + "," + str(the_value_2) + ")"
        insertString2 = "INSERT INTO subselect_myisam (index_col,non_index_col) VALUES (" + str(the_value_1) + "," + str(the_value_2) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)

    db.commit()

    # Finally, time the queries
    innodb_times.append( timeit.timeit('subSelectRecordsIndexed("test_table_innodb","subselect_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('subSelectRecordsIndexed("test_table_myisam","subselect_myisam")', number=100, setup=setupString) )

    innodb_times_2.append( timeit.timeit('subSelectRecordsNotIndexed("test_table_innodb","subselect_innodb")', number=100, setup=setupString2) )
    myisam_times_2.append( timeit.timeit('subSelectRecordsNotIndexed("test_table_myisam","subselect_myisam")', number=100, setup=setupString2) )

Creo que el mensaje final de todo esto es que si está realmente preocupado por la velocidad, debe comparar las consultas que está haciendo en lugar de suponer qué motor será más adecuado.

StackG
fuente
1
el rendimiento no siempre es la única consideración, ¿qué tal un gráfico sobre la estabilidad? un motor no sirve para nada si se bloquea y no admite funciones básicas de la base de datos.
pilavdzice
1
MyISAM probablemente vencería a InnoDB la mayoría de las veces si el my.cnfarchivo no está optimizado para InnoDB. No ha mencionado cómo se my.cnfve su archivo, que es realmente el factor más importante para el rendimiento de InnoDB.
itoctopus
Gracias itoctopus: me encantaría saber más sobre las optimizaciones que recomiendas. El código completo utilizado en estas pruebas está arriba, no dude en repetir los experimentos con varias optimizaciones y háganos saber si encuentra cambios significativos en los resultados
StackG
32

Ligeramente fuera de tema, pero para propósitos de documentación e integridad, me gustaría agregar lo siguiente.

En general, usar InnoDB resultará en una aplicación mucho menos compleja, probablemente también más libre de errores. Debido a que puede poner toda la integridad referencial (restricciones de clave externa) en el modelo de datos, no necesita tanto código de aplicación como necesitará con MyISAM.

Cada vez que inserte, elimine o reemplace un registro, DEBERÁ verificar y mantener las relaciones. Por ejemplo, si elimina a un padre, todos los hijos también deberían eliminarse. Por ejemplo, incluso en un sistema de blogging simple, si elimina un registro de publicación de blog, tendrá que eliminar los registros de comentarios, los me gusta, etc. En InnoDB, esto lo hace automáticamente el motor de la base de datos (si especificó las restricciones en el modelo ) y no requiere código de aplicación. En MyISAM, esto tendrá que codificarse en la aplicación, lo cual es muy difícil en los servidores web. Los servidores web son por naturaleza muy concurrentes / paralelos y debido a que estas acciones deben ser atómicas y MyISAM no admite transacciones reales, el uso de MyISAM para servidores web es riesgoso / propenso a errores.

También en la mayoría de los casos generales, InnoDB funcionará mucho mejor, por múltiples razones, una de ellas es que puede usar el bloqueo de nivel de registro en lugar del bloqueo de nivel de tabla. No solo en una situación donde las escrituras son más frecuentes que las lecturas, también en situaciones con uniones complejas en grandes conjuntos de datos. Notamos un aumento de rendimiento de 3 veces simplemente usando tablas InnoDB sobre tablas MyISAM para uniones muy grandes (tomar varios minutos).

Yo diría que, en general, InnoDB (que usa un modelo de datos 3NF completo con integridad referencial) debería ser la opción predeterminada cuando se usa MySQL. MyISAM solo debe usarse en casos muy específicos. Lo más probable es que rinda menos, resulte en una aplicación más grande y con más errores.

Habiendo dicho ésto. El modelado de datos es un arte que rara vez se encuentra entre los diseñadores / programadores web. Sin ofender, pero explica que MyISAM se está usando mucho.

Patrick Savalle
fuente
31

InnoDB ofrece:

ACID transactions
row-level locking
foreign key constraints
automatic crash recovery
table compression (read/write)
spatial data types (no spatial indexes)

En InnoDB, todos los datos en una fila, excepto TEXT y BLOB, pueden ocupar 8,000 bytes como máximo. No hay indexación de texto completo disponible para InnoDB. En InnoDB, los COUNT (*) s (cuando WHERE, GROUP BY o JOIN no se utilizan) se ejecutan más lentamente que en MyISAM porque el recuento de filas no se almacena internamente. InnoDB almacena datos e índices en un archivo. InnoDB utiliza una agrupación de almacenamiento intermedio para almacenar en caché tanto los datos como los índices.

MyISAM ofrece:

fast COUNT(*)s (when WHERE, GROUP BY, or JOIN is not used)
full text indexing
smaller disk footprint
very high table compression (read only)
spatial data types and indexes (R-tree)

MyISAM tiene bloqueo a nivel de tabla, pero no bloqueo a nivel de fila. No hay transacciones No hay recuperación automática de fallos, pero ofrece funcionalidad de tabla de reparación. Sin restricciones de clave externa. Las tablas MyISAM son generalmente de tamaño más compacto en el disco en comparación con las tablas InnoDB. Las tablas MyISAM podrían reducirse aún más en tamaño si se comprimen con myisampack si fuera necesario, pero se convertirían en solo lectura. MyISAM almacena índices en un archivo y datos en otro. MyISAM utiliza memorias intermedias clave para almacenar en caché los índices y deja la gestión de almacenamiento en caché de datos al sistema operativo.

En general, recomendaría InnoDB para la mayoría de los propósitos y MyISAM solo para usos especializados. InnoDB es ahora el motor predeterminado en las nuevas versiones de MySQL.

Pankaj Khurana
fuente
2
fwiw, VARCHAR en InnoDB también puede ir a páginas de desbordamiento, como BLOB y TEXT do. Todos estos tipos de datos se almacenan de manera similar internamente.
Bill Karwin
Es bueno saberlo, @BillKarwin! Hacemos un uso intensivo de VARCHAR en nuestra aplicación y hacer que VARCHAR contribuya a este límite de ~ 8kB fue un poco preocupante.
rinogo
Ver mysqlperformanceblog.com/2010/02/09/blob-storage-in-innodb para más detalles.
Bill Karwin el
la respuesta no está actualizada, ya que el motor innodb en MySQL versión 5.6+ hoy en día también admite indexación de texto completo y también MySQL 5.5 + / 5.7 + admite tipos de datos espaciales (5.5+) e índices espaciales (r-tee) (5.7+) .. Para obtener el mejor soporte, necesitaría al menos tener MySQL versión 5.7+
Raymond Nijland
25

Si usa MyISAM, no realizará ninguna transacción por hora, a menos que considere que cada declaración DML es una transacción (que, en cualquier caso, no será duradera ni atómica en el caso de un bloqueo).

Por lo tanto, creo que tienes que usar InnoDB.

300 transacciones por segundo suenan bastante. Si realmente necesita que estas transacciones sean duraderas durante una falla de energía, asegúrese de que su subsistema de E / S pueda manejar tantas escrituras por segundo fácilmente. Necesitará al menos un controlador RAID con caché respaldada por batería.

Si puede recibir un pequeño golpe de durabilidad, puede usar InnoDB con innodb_flush_log_at_trx_commit establecido en 0 o 2 (consulte los documentos para obtener más detalles), puede mejorar el rendimiento.

Hay una serie de parches que pueden aumentar la concurrencia de Google y otros, estos pueden ser de interés si aún no puede obtener el rendimiento suficiente sin ellos.

MarkR
fuente
24

La pregunta y la mayoría de las respuestas están desactualizadas .

Sí, es un cuento de viejas que MyISAM es más rápido que InnoDB. observe la fecha de la Pregunta: 2008; ahora es casi una década después. InnoDB ha logrado avances significativos en el rendimiento desde entonces.

El gráfico dramático fue para el caso en que MyISAM gana: COUNT(*) sin una WHEREcláusula. ¿Pero es eso realmente lo que pasas tu tiempo haciendo?

Si ejecuta la prueba de concurrencia , es muy probable que InnoDB gane, incluso en contraMEMORY .

Si escribe durante la evaluación comparativa SELECTs, MEMORYes probable que MyISAM pierda debido al bloqueo a nivel de tabla.

De hecho, Oracle está tan seguro de que InnoDB es mejor que han eliminado MyISAM de 8.0.

La pregunta fue escrita temprano en los días de 5.1. Desde entonces, estas versiones principales se marcaron como "Disponibilidad general":

  • 2010: 5.5 (.8 en diciembre)
  • 2013: 5.6 (.10 en febrero)
  • 2015: 5.7 (.9 en octubre)
  • 2018: 8.0 (.11 en abril)

En pocas palabras: no use MyISAM

Rick James
fuente
2
La tecnología de base de datos MySQL avanza. Y las preguntas y respuestas de StackOverflow permanecen sumidas en el pasado. Las principales diferencias entre MyISAM e InnoDB son menos sobre la "carga" en el servidor y más sobre el soporte para la integridad referencial y las transacciones , así como la concurrencia y la
capacidad de
12

Consulte también algunos reemplazos directos para MySQL:

MariaDB

http://mariadb.org/

MariaDB es un servidor de base de datos que ofrece la funcionalidad de reemplazo directo para MySQL. MariaDB está construido por algunos de los autores originales de MySQL, con la asistencia de la comunidad más amplia de desarrolladores de software libre y de código abierto. Además de la funcionalidad central de MySQL, MariaDB ofrece un amplio conjunto de mejoras de características que incluyen motores de almacenamiento alternativos, optimizaciones de servidor y parches.

Servidor Percona

https://launchpad.net/percona-server

Un reemplazo mejorado para MySQL, con un mejor rendimiento, diagnósticos mejorados y funciones adicionales.

Refinador
fuente
1
Los estoy usando a ambos (Percona en producción, Maria en desarrollo de Windows). son más rápidos y funcionan perfectamente.
Moshe L
44
Esto no responde la pregunta. MariaDB y Percona son tenedores de MySQL, y también usan motores InnoDB y MyISAM.
dr_
12

Tenga en cuenta que mi educación y experiencia formales son con Oracle, mientras que mi trabajo con MySQL ha sido completamente personal y en mi propio tiempo, por lo que si digo cosas que son ciertas para Oracle pero que no lo son para MySQL, me disculpo. Si bien los dos sistemas comparten mucho, la teoría / álgebra relacional es la misma, y ​​las bases de datos relacionales siguen siendo bases de datos relacionales, ¡todavía hay muchas diferencias!

Particularmente me gusta (así como el bloqueo de nivel de fila) que InnoDB está basado en transacciones, lo que significa que puede estar actualizando / insertando / creando / alterando / soltando / etc. varias veces para una "operación" de su aplicación web. El problema que surge es que si solo algunos de esos cambios / operaciones terminan siendo confirmados, pero otros no, la mayoría de las veces (dependiendo del diseño específico de la base de datos) terminará con una base de datos con datos / estructura en conflicto.

Nota: Con Oracle, las declaraciones crear / alterar / soltar se denominan declaraciones "DDL" (Definición de datos) y desencadenan implícitamente una confirmación. Las instrucciones de inserción / actualización / eliminación, llamadas "DML" (manipulación de datos), no se confirman automáticamente, sino solo cuando se realiza un DDL, commit o exit / quit (o si configura su sesión como "auto-commit", o si su cliente se compromete automáticamente). Es imprescindible tener en cuenta eso cuando se trabaja con Oracle, pero no estoy seguro de cómo MySQL maneja los dos tipos de declaraciones. Debido a esto, quiero dejar en claro que no estoy seguro de esto cuando se trata de MySQL; solo con Oracle.

Un ejemplo de cuándo los motores basados ​​en transacciones son excelentes:

Digamos que usted o usted están en una página web para registrarse para asistir a un evento gratuito, y uno de los principales propósitos del sistema es permitir que solo 100 personas se registren, ya que ese es el límite de asientos. Para el evento. Una vez que se alcanzan las 100 suscripciones, el sistema deshabilitaría más suscripciones, al menos hasta que otras cancelen.

En este caso, puede haber una mesa para invitados (nombre, teléfono, correo electrónico, etc.) y una segunda mesa que rastrea el número de invitados que se han registrado. Por lo tanto, tenemos dos operaciones para una "transacción". Ahora suponga que después de agregar la información del invitado a la tabla INVITADOS, hay una pérdida de conexión o un error con el mismo impacto. La tabla INVITADOS se actualizó (se insertó en), pero la conexión se perdió antes de que se pudieran actualizar los "asientos disponibles".

Ahora tenemos un invitado agregado a la mesa de invitados, pero el número de asientos disponibles ahora es incorrecto (por ejemplo, el valor es 85 cuando en realidad es 84).

Por supuesto, hay muchas maneras de manejar esto, como rastrear los asientos disponibles con "100 menos el número de filas en la tabla de invitados" o algún código que verifique que la información sea consistente, etc. Pero con una base de datos basada en transacciones motor como InnoDB, o TODAS las operaciones están confirmadas, o NINGUNA de ellas lo está. Esto puede ser útil en muchos casos, pero como dije, no es la ÚNICA forma de estar seguro, no (una buena manera, sin embargo, manejada por la base de datos, no por el programador / guionista).

Eso es todo "basado en transacciones" esencialmente significa en este contexto, a menos que me falte algo, que o bien toda la transacción tiene éxito como debería, o que nada se cambia, ya que hacer solo cambios parciales podría hacer que un MENOR SEVERA. base de datos, tal vez incluso corrompiéndola ...

Pero lo diré una vez más, no es la única forma de evitar hacer un desastre. Pero es uno de los métodos que maneja el propio motor, dejándolo en código / script con solo tener que preocuparse por "si la transacción fue exitosa o no, y qué debo hacer si no (como reintentar)", en lugar de hacerlo manualmente escribir código para verificarlo "manualmente" desde fuera de la base de datos, y hacer mucho más trabajo para tales eventos.

Por último, una nota sobre el bloqueo de tabla frente al bloqueo de fila:

DESCARGO DE RESPONSABILIDAD: puedo estar equivocado en todo lo que sigue con respecto a MySQL, y las situaciones hipotéticas / de ejemplo son aspectos a tener en cuenta, pero puedo estar equivocado en lo que es exactamente posible causar corrupción con MySQL. Sin embargo, los ejemplos son muy reales en la programación general, incluso si MySQL tiene más mecanismos para evitar tales cosas ...

De todos modos, estoy bastante seguro de estar de acuerdo con aquellos que han argumentado que el número de conexiones se permiten a la vez no no trabajar en torno a una tabla bloqueada. De hecho, ¡las conexiones múltiples son el punto completo de bloquear una mesa! Para que otros procesos / usuarios / aplicaciones no puedan dañar la base de datos al hacer cambios al mismo tiempo.

¿Cómo dos o más conexiones trabajando en la misma fila harían un DÍA REALMENTE MALO para usted? Supongamos que hay dos procesos que ambos desean / necesitan actualizar el mismo valor en la misma fila, digamos porque la fila es un registro de un recorrido en autobús, y cada uno de los dos procesos simultáneamente desea actualizar los "pasajeros" o "asientos disponibles" campo como "el valor actual más 1."

Hagamos esto hipotéticamente, paso a paso:

  1. El proceso uno lee el valor actual, digamos que está vacío, por lo tanto, '0' hasta ahora.
  2. El proceso dos también lee el valor actual, que sigue siendo 0.
  3. Proceso uno escribe (actual + 1) que es 1.
  4. El proceso dos debería escribir 2, pero como lee el valor actual antes del proceso uno escribe el nuevo valor, también escribe 1 en la tabla.

No estoy seguro de que dos conexiones puedan mezclarse así, ambas leen antes de que la primera escriba ... Pero si no, aún vería un problema con:

  1. El proceso uno lee el valor actual, que es 0.
  2. Proceso uno escribe (actual + 1), que es 1.
  3. El proceso dos lee el valor actual ahora. Pero mientras procesa una escritura DID (actualización), no ha confirmado los datos, por lo tanto, solo ese mismo proceso puede leer el nuevo valor que actualizó, mientras que todos los demás ven el valor anterior, hasta que haya una confirmación.

Además, al menos con las bases de datos Oracle, hay niveles de aislamiento, que no perderé nuestro tiempo tratando de parafrasear. Aquí hay un buen artículo sobre ese tema, y ​​cada nivel de aislamiento tiene sus pros y sus contras, lo que coincidiría con la importancia de los motores basados ​​en transacciones en una base de datos ...

Por último, es probable que existan diferentes salvaguardas dentro de MyISAM, en lugar de claves externas e interacción basada en transacciones. Bueno, por un lado, está el hecho de que una tabla completa está bloqueada, lo que hace que sea menos probable que se necesiten transacciones / FK .

Y, por desgracia, si está al tanto de estos problemas de concurrencia, sí, puede jugar con menos seguridad y simplemente escribir sus aplicaciones, configurar sus sistemas para que dichos errores no sean posibles (su código es responsable, en lugar de la base de datos). Sin embargo, en mi opinión, diría que siempre es mejor usar tantas salvaguardas como sea posible, programando a la defensiva y siempre consciente de que el error humano es imposible de evitar por completo. Le sucede a todos, y cualquiera que diga que es inmune a ella debe estar mintiendo, o no ha hecho más que escribir una aplicación / script "Hello World". ;-)

¡Espero que ALGO de eso sea útil para alguien, y aún más, espero que no solo haya sido un culpable de suposiciones y haya sido un humano por error! Mis disculpas si es así, pero es bueno pensar en los ejemplos, investigar el riesgo, etc., incluso si no son potenciales en este contexto específico.

Siéntase libre de corregirme, edite esta "respuesta", incluso vote hacia abajo. Solo intenta mejorar, en lugar de corregir una mala suposición mía con otra. ;-)

Esta es mi primera respuesta, así que por favor, perdona la longitud debido a todos los descargos de responsabilidad, etc. ¡Simplemente no quiero parecer arrogante cuando no estoy absolutamente seguro!

Arembjorn
fuente
5

En mi experiencia, MyISAM fue una mejor opción siempre que no haga DELETEs, ACTUALIZACIONES, una gran cantidad de INSERTOS, transacciones e indexación de texto completo. Por cierto, la tabla de verificación es horrible. A medida que la tabla envejece en términos de número de filas, no sabe cuándo terminará.

yogman
fuente
2
La indexación de texto completo solo es posible con MyISAM, no con InnoDB.
Pixel Elephant el
2
@PixelElephant, eso está comenzando a cambiar en MySQL 5.6. InnoDB tiene un tipo de índice de texto completo, pero hasta ahora no está listo para producción en mi humilde opinión.
Bill Karwin
1
"La indexación de texto completo solo es posible con MyISAM, no con InnoDB": ya no es cierto desde MySQL> = 5.6. Ver dev.mysql.com/doc/refman/5.6/en/fulltext-search.html .
Hibou57
5

He descubierto que, aunque Myisam tiene contención de bloqueo, sigue siendo más rápido que InnoDb en la mayoría de los escenarios debido al esquema de adquisición de bloqueo rápido que utiliza. He intentado varias veces Innodb y siempre recurro a MyIsam por una razón u otra. Además, InnoDB puede consumir mucha CPU en grandes cargas de escritura.

Ricardo
fuente
4

Cada aplicación tiene su propio perfil de rendimiento para usar una base de datos, y es probable que cambie con el tiempo.

Lo mejor que puede hacer es probar sus opciones. Cambiar entre MyISAM e InnoDB es trivial, así que cargue algunos datos de prueba y dispare jmeter contra su sitio y vea qué sucede.

Gary Richardson
fuente
4

Traté de ejecutar la inserción de datos aleatorios en las tablas MyISAM e InnoDB. El resultado fue bastante impactante. ¡MyISAM necesitó unos segundos menos para insertar 1 millón de filas que InnoDB por solo 10 mil!

usuario965748
fuente
2
Obtendrá el mismo rendimiento si utiliza la transacción y apaga la confirmación automática para el motor InnoDB.
stanleyxu2005
IDK si el mismo rendimiento, pero eso es lo que hago en aplicaciones más complejas y lo acelera.
user965748
1
No pudo proporcionar los detalles exactos de su experimento, ¿qué ajustes de configuración? ¿Qué había en la (s) mesa (s) antes? ¿Qué tipo de datos? y quizás lo más importante: ¿hubo inserciones secuenciales? ¿Paralela? ¿Cuál fue su momento? ¿Cuántos núcleos de CPU? ¿Hilos? etc.
einpoklum
3

myisam es un NOGO para ese tipo de carga de trabajo (escrituras de alta concurrencia), no tengo tanta experiencia con innodb (lo probé 3 veces y encontré en cada caso que el rendimiento apestaba, pero ha pasado un tiempo desde la última prueba) si no se ve obligado a ejecutar mysql, considere probar postgres ya que maneja las escrituras concurrentes MUCHO mejor

pfote
fuente
3

En resumen, InnoDB es bueno si está trabajando en algo que necesita una base de datos confiable que pueda manejar muchas instrucciones INSERT y UPDATE.

y, MyISAM es bueno si necesita una base de datos que en su mayoría tomará muchas instrucciones de lectura (SELECCIONAR) en lugar de escribir (INSERTAR y ACTUALIZAR), considerando su inconveniente en el bloqueo de la tabla.

es posible que desee verificar;
Pros y contras de InnoDB
Pros y contras de MyISAM

Light93
fuente
2

Sé que esto no será popular, pero aquí va:

myISAM carece de soporte para los elementos esenciales de la base de datos, como las transacciones y la integridad referencial, que a menudo resulta en aplicaciones con fallas / errores. No puede no aprender los fundamentos de diseño de bases de datos adecuados si ni siquiera los admite su motor db.

No usar integridad referencial o transacciones en el mundo de la base de datos es como no usar programación orientada a objetos en el mundo del software.

InnoDB existe ahora, ¡use eso en su lugar! Incluso los desarrolladores de MySQL finalmente han aceptado cambiar esto al motor predeterminado en las versiones más nuevas, a pesar de que myISAM es el motor original que era el predeterminado en todos los sistemas heredados.

No, no importa si está leyendo o escribiendo o qué consideraciones de rendimiento tiene, el uso de myISAM puede ocasionar una variedad de problemas, como el que acabo de encontrar: estaba realizando una sincronización de base de datos y al mismo tiempo alguien más accedió a una aplicación que accedió a una tabla establecida en myISAM. Debido a la falta de soporte de transacciones y la confiabilidad generalmente pobre de este motor, esto bloqueó toda la base de datos y tuve que reiniciar manualmente mysql.

En los últimos 15 años de desarrollo, he usado muchas bases de datos y motores. ¡myISAM se estrelló contra mí una docena de veces durante este período, otras bases de datos, solo una vez! Y esa fue una base de datos SQL de Microsoft donde algunos desarrolladores escribieron un código CLR defectuoso (Common Language Runtime, básicamente código C # que se ejecuta dentro de la base de datos) por cierto, no fue exactamente la falla del motor de la base de datos.

Estoy de acuerdo con las otras respuestas aquí que dicen que las aplicaciones de alta disponibilidad y alto rendimiento de calidad no deberían usar myISAM ya que no funcionará, no es lo suficientemente robusto o estable como para resultar en una experiencia libre de frustración. Vea la respuesta de Bill Karwin para más detalles.

PD: Me encanta cuando los fanáticos de myISAM votan negativamente, pero no puedo decirte qué parte de esta respuesta es incorrecta.

pilavdzice
fuente
55
No voté en contra, pero si lo hiciera sería para aconsejar nunca usar. la palabra nunca debe ser tachada en el vocabulario de un desarrollador ... la advertencia es 'nunca digas nunca'.
hubson bropa
1

Para esa proporción de lectura / escritura, supongo que InnoDB funcionará mejor. Como está bien con lecturas sucias, puede (si se lo permite) replicar a un esclavo y dejar que todas sus lecturas vayan al esclavo. Además, considere insertar en forma masiva, en lugar de un registro a la vez.

aise neal
fuente
1

Casi cada vez que comienzo un nuevo proyecto, busco en Google esta misma pregunta para ver si encuentro nuevas respuestas.

Eventualmente se reduce a: tomo la última versión de MySQL y ejecuto pruebas.

Tengo tablas donde quiero hacer búsquedas de clave / valor ... y eso es todo. Necesito obtener el valor (0-512 bytes) para una clave hash. No hay muchas transacciones en este DB. La tabla recibe actualizaciones ocasionalmente (en su totalidad), pero 0 transacciones.

Así que no estamos hablando de un sistema complejo aquí, estamos hablando de una simple búsqueda, y cómo (además de hacer que la tabla resida en RAM) podemos optimizar el rendimiento.

También hago pruebas en otras bases de datos (es decir, NoSQL) para ver si hay algún lugar donde pueda obtener una ventaja. La mayor ventaja que he encontrado es en el mapeo de teclas, pero en lo que respecta a la búsqueda, MyISAM actualmente los está superando a todos.

No obstante, no realizaría transacciones financieras con tablas MyISAM, pero para búsquedas simples, debería probarlo ... normalmente 2x a 5x las consultas / seg.

Pruébelo, agradezco el debate.

Cyberwip
fuente
1

Si tiene 70% de inserciones y 30% de lecturas, entonces es más como en el lado de InnoDB.

kta
fuente
0

Conclusión: si está trabajando sin conexión con selecciones en grandes cantidades de datos, MyISAM probablemente le brindará mejores (mucho mejores) velocidades.

Hay algunas situaciones en las que MyISAM es infinitamente más eficiente que InnoDB: cuando se manipulan grandes volcados de datos fuera de línea (debido al bloqueo de la tabla).

ejemplo: estaba convirtiendo un archivo csv (15M registros) de NOAA que usa los campos VARCHAR como claves. InnoDB estaba tardando una eternidad, incluso con grandes porciones de memoria disponibles.

Este es un ejemplo de CSV (el primer y el tercer campo son claves).

USC00178998,20130101,TMAX,-22,,,7,0700
USC00178998,20130101,TMIN,-117,,,7,0700
USC00178998,20130101,TOBS,-28,,,7,0700
USC00178998,20130101,PRCP,0,T,,7,0700
USC00178998,20130101,SNOW,0,T,,7,

Como lo que necesito hacer es ejecutar una actualización por lotes fuera de línea de fenómenos meteorológicos observados, uso la tabla MyISAM para recibir datos y ejecuto JOINS en las teclas para poder limpiar el archivo entrante y reemplazar los campos VARCHAR con teclas INT (que están relacionadas con tablas externas donde se almacenan los valores VARCHAR originales).

Tony Gil
fuente