esquema eficiente de MySQL con la partición de gran conjunto de datos (7.300.000.000 filas y más o menos 80 GB de datos)

StackOverflow https://stackoverflow.com/questions/666374

Pregunta

Esta es una continuación de mi pregunta "almacenar eficientemente 7.300.000.000 filas" ( eficientemente el almacenamiento de 7.300.000.000 filas ).

He decidido utilizar MySQL con la partición y el esquema preliminar se ve así:

CREATE TABLE entity_values (
  entity_id MEDIUMINT UNSIGNED DEFAULT 0 NOT NULL, # 3 bytes = [0 .. 16.777.215]
  date_id SMALLINT UNSIGNED DEFAULT 0 NOT NULL, # 2 bytes = [0 .. 65.535]
  value_1 MEDIUMINT UNSIGNED DEFAULT 0 NOT NULL, # 3 bytes = [0 .. 16.777.215]
  value_2 MEDIUMINT UNSIGNED DEFAULT 0 NOT NULL, # 3 bytes = [0 .. 16.777.215]
  UNIQUE KEY (entity_id, date_id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 PARTITION BY HASH(entity_id) PARTITIONS 25;

Esto da:

  • Filas = 7.300.000.000 filas (según los requisitos indicados en la entrada anterior)
  • Tamaño / fila = 11 bytes (3 + 2 + 3 + 3)
  • tamaño total = 7.300.000.000 filas * 11 bytes = 80.300.000.000 bytes = 80.3 GB
  • Particiones = 25 (3,2 GB / partición, el tamaño de partición es algo arbitraria)

Tenga en cuenta que se me ha caído la clave principal del diseño original ya no se utilizará la columna "ID".

Ahora a mi pregunta - teniendo en cuenta los requisitos descritos en mi post anterior y el esquema anterior, ¿tiene alguna sugerencia sobre optimizaciones / ajustes que se pueden hacer? ¿O es el esquema anterior "óptima", dado que he decidido utilizar MySQL?

Actualización: He intentado cargar el conjunto de datos en el esquema anterior y los 8.570.532 filas tomaron 212.000.000 bytes pena de espacio en disco, lo que da aproximadamente 24,7 bytes por fila

Actualización:. Tenga en cuenta que el índice de cobertura entity_id + date_id se utilizará también para las consultas de orientación única entity_id

¿Fue útil?

Solución

Una cosa que no entiendo muy bien, es cómo va a podar sus datos. Usted tiene filas 2M por día, pero no se ha especificado la cantidad de datos que va a mantener. En algún momento tendrá que expiran los datos por edad (con toda probabilidad).

En este punto, tendrá que hacerlo dejando caer particiones, NO mediante la ejecución de una eliminación, que encierra cada partición individual para un tiempo increíblemente largo (ya que tiene que hacer un escaneo completo de tabla para encontrar las filas para borrar ), luego se va a su mesa sin más pequeña que las particiones están llenas de agujeros.

La partición de hash del entity_id podría parecer razonable para la búsqueda, pero la partición por el tiempo podría aliviar la contención cuando se llega a podar los datos antiguos, y sin duda será una buena cosa.

MyISAM tiene una característica llamada "inserciones concurrentes" que casi sin duda tendrá que utilizar todo el tiempo con el fin de lograr la simultaneidad y el rendimiento; esto exige una regla de "no hay eliminaciones", lo que significa que sólo se puede hacer eliminaciones dejando caer las particiones.

Pero dejando caer las particiones también es bueno porque se puede obtener el espacio de disco trasero.

Una vez dicho todo esto, 80G no es tan grande y podría haber sido tentado para almacenar todo en una sola tabla, y el uso de InnoDB para permitir el acceso concurrente.

Oh, sí, y si se ha utilizado InnoDB, usted podría tener una clave principal de entity_id, date_id, lo que significa que sería agrupar filas con el mismo entity_id. Usted probablemente querrá un índice secundario en date_id para permitir la poda eficiente.

Por favor, probar esto con sus tamaños de los datos de producción y háganos saber lo que encuentre!

Otros consejos

Si suele recuperar todas (o la mayoría) de los datos para una identificación de entidad debe tener en cuenta lo que el índice simplemente Identificación entidad y no (entity_id, date_id) -. A menos que necesite la base de datos para hacer controles únicos

El efecto es hacer que el índice más pequeño para que pueda obtener más de lo mismo en la memoria. Su objetivo debe ser conseguir que el índice sea en la memoria. Incluso si usted tiene que hacer SELECT..ORDER POR FECHA encontrará que MySQL puede ordenar 3650 valores en una fracción de segundo sobre la marcha (sin el índice). Este problema es el tiempo para leer las filas de disco.

Sin embargo, su principal problema es el rendimiento que los insertos como resultado datos de una entidad hacia fuera a través del disco que requiere un acceso a disco de cada uno (entidad, fecha) que harán de su consulta ejecutada en unos pocos cientos de filas por segundo. Su partición no ayudará este becaause cada entidad se encuentra en una sola partición y las filas se extienden a través de su disco. (RAID 0 en los discos ayudará un poco).

Para obtener la recuperación eficiente que necesita para obtener los datos para una entidad que ser contiguos en el disco, lo que significa reordenar los datos de la orden INSERT. Usted puede hacer esto con MySQL ALTER TABLE .. ORDER BY ... pero se necesita siempre. He tenido una fila de la tabla 182M haciendo un ALTER TABLE .. ORDER BY corriente durante las últimas 2 semanas y no ha terminado todavía.

Es por eso que escribí un motor de almacenamiento a medida!

Por cierto, no estoy seguro de que se gana nada en absoluto por reparto a menos que esté particionando a través de múltiples servidores - o al menos discos múltiples. El duro trabajo que MySQL tiene que ver no se hace más fácil con el particionamiento. Es todo acerca de los tiempos de acceso al disco.

Poner cada partición en un disco diferente podría ayudar. No tendría más de dos veces tantas particiones como tiene discos físicos. 2 veces, en lugar de 1 vez, darían algunos beneficios de colas, pero dudo que tendría mucho efecto. Dudo que usted consigue mucho mejor que una sola tabla sin particiones utilizando RAID 0 entre tantos discos como sea posible.

El rendimiento de esta aplicación se determina por el número de búsquedas en disco, y por lo tanto ayudó a si se puede hacer más busca por segundo.

Se gana cierto paralelismo de procesamiento (suponiendo que tiene varios procesadores) con el particionado, pero el sistema va a ser de E / S de la envolvente, no obligado procesador. Si usted recibe su utilización del procesador de hasta el 2% es probable que esté haciendo algo que no es necesario hacer (o algo que no es su aplicación).

He estado escribiendo, optimizar y operar este tipo de aplicación para los nueve años usando MySQL ... y tengo todas las cicatrices que se podría esperar de la experiencia. Una vez que sus datos están mucho más grande que el tamaño de la memoria (que es mi definición de "enorme"), todo el problema de rendimiento es Disco / S que significa primaria el número de busca disco I . Buena suerte !!

Según indica en su pregunta anterior que se va a recuperar todas las filas de una entity_id; Sin embargo, si usted planea en la recuperación de los intervalos de fechas de entidades específicas, se puede usar Sub-Paritioning (también conocido como partición compuesto) . Dependiendo de su uso, usted podría tener su partición principal se ENTITY_ID y el sub-partición como el año u otro intervalo de fechas. También puede invertir que si tiene sentido en su sistema.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top