Acerca de comparar formatos de almacenamiento en Hadoop: comencemos con ORC

Hadoop incluye productos que pueden trabajar con archivos de varios formatos. He buscado, leído y pensado en repetidas ocasiones qué formato es mejor. Cuando me encontré con el formato ORC de manera relativamente aleatoria, me interesé, leí (e incluso un poco codificado), y eso es lo que entendí: es incorrecto comparar formatos como tales. Más precisamente, generalmente se comparan, en mi opinión, de manera incorrecta. En realidad, un artículo sobre esto, así como sobre el formato ORC de Apache (en términos técnicos) y las oportunidades que ofrece.


Comenzaré con la pregunta: ¿cuál puede ser el tamaño de una tabla relacional (en bytes y muy aproximadamente), que consta de 10 mil filas (dos campos enteros por fila)? Por lo general, ponen un kat aquí, y la respuesta se coloca debajo del kat: responderé aquí: 628 bytes. Y los detalles y la historia se transferirán bajo cat.


Cómo comenzó todo: construí una biblioteca para trabajar con Apache ORC (consulte la página de inicio del proyecto: https://orc.apache.org ) y compilé su propio ejemplo sobre cómo escribir en ORC (para romper la cabeza, comenzamos con lo que funciona) , tenía 2 campos y 10 mil líneas. Lo comencé, recibí el archivo orco porque lo hice en algún lugar fuera de la oficina, por si acaso, reescribí la biblioteca y el archivo en una unidad flash (a toda prisa, no miré el tamaño, creo que la unidad flash puede manejarlo).


Pero de alguna manera respondí rápidamente ... Miré el tamaño: 628 bytes. Pensé que era un error, me senté y comencé a entender. Lancé la utilidad para ver ORC desde la misma biblioteca compilada: el contenido del archivo muestra que todo es honesto: 10 mil líneas. Después de eso, me pregunté cómo cabían 10 mil líneas en 628 bytes (ya sabía un poco sobre ORC en ese momento y me di cuenta de que también había metadatos: el formato era autosuficiente). Entendido, compartir.


Sobre el formato ORC


imagen


No repetiré aquí palabras generales sobre el formato: vea el enlace de arriba, está bien escrito allí. Me centraré en dos adjetivos en excelente forma de la imagen de arriba (la imagen está tomada de la página de inicio del proyecto): tratemos de descubrir por qué ORC es "el más rápido" y "el más compacto".


Velocidad


La velocidad puede ser diferente con respecto a los datos, al menos la velocidad de lectura o escritura (puede profundizar más, pero detengámonos por ahora). Dado que Hadoop se menciona explícitamente en el eslogan anterior, consideraremos principalmente la velocidad de lectura.


Para citar un poco más de la documentación de ORC:


Está optimizado para grandes lecturas de transmisión, pero con soporte integrado para encontrar filas requeridas rápidamente. El almacenamiento de datos en formato de columnas permite al lector leer, descomprimir y procesar solo los valores necesarios para la consulta actual.

Voy a traducir un poco:


  • formato optimizado para transmisión de lectura de grandes volúmenes
  • al mismo tiempo contiene soporte para búsqueda rápida de líneas necesarias
  • le permite leer solo los datos que necesita

Tamaño


No hubo cita, diré en mis propias palabras


  • formato almacena de manera óptima la metainformación
  • lograr un equilibrio entre la velocidad de lectura de transmisión y el almacenamiento compacto
  • soporte integrado para el almacenamiento más compacto de valores de columna

Brindando oportunidades


Quiero llamar su atención sobre la redacción de las citas anteriores: "optimizado para ...", "contiene soporte ...", "le permite leer ..." - el formato de archivo, como lenguaje de programación, es un medio (en este caso, asegurar almacenamiento eficiente y acceso a datos). El hecho de que el almacenamiento y el acceso a los datos sea realmente efectivo depende no solo de la herramienta, sino también de quién la usa y cómo.


Veamos qué formato proporciona el formato para velocidad y compacidad.


Almacenamiento de columna y franja


Los datos en el ORC se almacenan en forma de columnas, en primer lugar, afecta el tamaño. Para garantizar la velocidad de la lectura de transmisión, el archivo se divide en las llamadas "franjas", cada franja es autosuficiente, es decir se puede leer por separado (y, por lo tanto, en paralelo). Debido a las tiras, el tamaño del archivo aumentará (los valores de columna no únicos se almacenarán varias veces, en esas tiras donde se producen dichos valores), el mismo equilibrio de "velocidad - tamaño" (es un compromiso).


Índices


El formato ORC implica índices que le permiten determinar si la banda (o más bien, las partes de banda de 10 mil filas cada una, el llamado "grupo de filas") contiene los datos que está buscando o no. Los índices se construyen en cada una de las columnas. Esto afecta la velocidad de lectura, aumentando el tamaño. Al transmitir índices de lectura, por cierto, no puede leer.


Compresión


Todos los metadatos se almacenan en forma comprimida, y esto


  • información estadística y descriptiva (el formato le permite recrear la tabla que está almacenada en él, incluidos los nombres y tipos de campos)
  • índices
  • partición de información (en bandas y secuencias)

(a continuación veremos que los metadatos son una parte esencial del archivo)


Los valores de columna también se almacenan en forma comprimida. Al mismo tiempo, es posible leer y desempaquetar solo el bloque de datos que se necesita (es decir, no se comprime un archivo ni una tira completa). La compresión afecta tanto el tamaño como la velocidad de lectura.


Codificación


Los valores de la columna, y el archivo almacena exactamente estos valores, se almacenan en forma codificada. En la versión actual del formato (ORC v1) para enteros, por ejemplo, hay 4 opciones de codificación disponibles. Al mismo tiempo, no se codifica toda la columna, se codifican partes de la columna, cada parte se puede codificar de manera óptima para esta parte (dichas partes se denominan "ejecución" en la especificación). Por lo tanto, se logra la minimización de la longitud total de los datos almacenados. De nuevo, el efecto sobre el tamaño y la velocidad.


Veamos el archivo ORC


Veamos brevemente lo que hay dentro del archivo ORC (el que tiene 628 bytes). Para aquellos que no están muy interesados ​​en los detalles técnicos, desplácese hacia abajo a la siguiente sección (sobre comparación de formatos).


Así es como se definió nuestra tabla en el registro de ejemplo en ORC:


imagen


Metadatos


Información sobre las longitudes (doy capturas de pantalla del cuaderno jupyter, creo que es lo suficientemente claro)


imagen


Lo que vemos aquí:


  • en el "vástago" (y esto es PostScript + Pie de página + Metadatos) solo 1 + 23 + 115 + 50 = 189 bytes
  • en una sola banda, solo 3 + 436 = 439 bytes, total 628 bytes
  • la tira contiene un índice (73 bytes), datos (276 bytes), pie de página (87 bytes)

Prestemos atención aquí a la relación de volumen de datos y metadatos (276 a 352 bytes). Pero estos 276 bytes de datos no son solo datos, los datos contienen un poco de "superfluo" (aquí por brevedad no doy capturas de pantalla; es mucho tiempo con ellos, lo gestionaré solo con mis comentarios), que está incluido en los datos:


  • PRESENTES flujos para cada columna, hay tres de ellos (incluida una estructura de pseudocolumna común): 20 bytes por cada uno, un total de 60 bytes
  • flujos de datos (aquí la pseudocolumna no está representada) - 103 y 113 bytes (columnas "x" e "y", respectivamente)

Las corrientes PRESENTES son cadenas de bits que le permiten saber dónde están las columnas NULL. Para nuestro ejemplo, su presencia parece extraña (en las estadísticas de nuestro archivo está claramente escrito que no hay NULL en los datos, ¿por qué entonces incluir PRESENT? Parece una falla ...)


En total, los datos en sí ocupan 216 bytes, metadatos - 352.


También se puede ver en los metadatos que ambas columnas están codificadas usando el método DIRECT_V2 (para enteros, permite 4 tipos de representaciones, para detalles me refiero a la especificación, está en el sitio web del proyecto).


Datos


Veamos (nuevamente sin capturas de pantalla por brevedad) cómo caben 10 mil números en 103 bytes (para la columna "x"):


  • Se utiliza la codificación delta, en la que los parámetros son el valor inicial y el paso (un poco simplificado por brevedad)
  • siempre tenemos 1 paso, el valor inicial para la primera ejecución es 0, luego 511, 1022, etc.
  • run (un conjunto de datos codificados de una sola manera) en nuestro caso contiene 511 valores (el valor máximo posible para la codificación delta)
  • la longitud de cada ejecución en el archivo es de 4 a 6 bytes (la longitud de la ejecución aumenta debido al hecho de que el valor inicial se representa usando zigzag)
  • total para la columna "x" obtenemos en el archivo 20 ejecuciones con una longitud total de 103 bytes (lo comprobé, todo encaja)

Concluyendo la revisión de la presentación de nuestra tabla simple en un archivo, diré que los índices en este ejemplo son degenerados: indican el comienzo del flujo de datos. Trataré los índices con ejemplos de la vida real; probablemente los describiré en un artículo separado.


Para aquellos interesados: en el enlace puede encontrar el cuaderno jupyter, en el que "entendí" el formato interno. Puede usarlo y repetir (el archivo ORC también está adjunto allí).


Estoy seguro de que muchos lectores están "perdidos": sí, el formato ORC no es simple (tanto en términos de comprensión de los detalles como en términos de uso de las funciones proporcionadas).


Acerca de la comparación de formatos


Ahora pasemos al punto principal: comparación de formato incorrecta.


Con qué frecuencia se comparan los formatos: comparemos el tamaño de los archivos en formato A y B, la velocidad de lectura (diferentes tipos de lectura - aleatoria, transmisión, etc.) en formato A y B. Comparados, concluimos que el formato A es mejor que el formato B.


Usando el ejemplo de la última de las herramientas de compacidad (codificación) enumeradas anteriormente: ¿se pueden codificar los datos en el ORC de manera óptima? Sí, hay oportunidades, ver arriba. Pero igual de bien, ¡no puedes hacer esto! Depende del "escritor" (escritor en terminología ORC): en el ejemplo anterior, el escritor podría hacer esto. Pero él podría escribir 2 veces en 10 mil números y esto también sería correcto en términos de formato. Comparando formatos "por tamaño" comparamos no solo y no tanto los formatos como la calidad algorítmica de los sistemas de aplicación que usan estos formatos .


¿Quién es el "escritor" en Hadoop? Hay muchos de ellos, por ejemplo, Hive, que crea una tabla que almacena sus datos en archivos en formato ORC. Comparando, por ejemplo, ORC con Parquet en Hadoop, en realidad evaluamos la calidad de implementación del algoritmo de conversión de datos implementado en Hive. No comparamos formatos (como tales).


Característica importante de Hadoop


En el mundo relacional clásico, no teníamos forma de influir en el tamaño de la tabla en Oracle: de alguna manera estaba almacenada y solo Oracle sabía cómo hacerlo. En Hadoop, la situación es ligeramente diferente: podemos ver cómo se almacena esta o aquella tabla (qué tan bien Hive, por ejemplo, logró "codificarla"). Y, si vemos que esto puede mejorarse, tenemos una oportunidad real para esto: crear nuestro propio archivo ORC más óptimo y dárselo a Hive como una tabla externa.


Compare ORC y QVD


Recientemente describí el formato QVD que QlikVew / QlikSense está usando activamente. Vamos a ilustrar muy brevemente estos dos formatos en términos de las capacidades que brindan para lograr la máxima velocidad de lectura y minimizar el tamaño. Las capacidades de ORC se describen arriba, como en QVD:


Columna de almacenamiento


QVD puede considerarse un formato "columnar", no hay duplicación de valores de columna en él, los valores únicos se almacenan una vez. PERO no permite el procesamiento en paralelo: primero debe leer completamente los valores de todas las columnas, luego puede leer las filas en paralelo.


Y hay duplicación a nivel de fila: las filas almacenan valores de índice duplicados en una tabla de caracteres.


Compresión


No encontré archivos QVD comprimidos, no tuve éxito, hay una etiqueta en los metadatos, quizás cada una de las partes sobre las que hay un desplazamiento y longitud en los metadatos (y esta es cada tabla de caracteres y toda la tabla de cadenas) se puede comprimir. En este caso, una lectura paralela de las líneas es "adiós" ...


Índices


No hay forma de entender en el archivo QVD qué parte de él necesita leerse. En la práctica, debe analizar la tabla de caracteres byte a byte (cada uno). No es una forma muy eficiente ...


Codificación


La codificación en QVD no se usa, es posible dibujar una analogía del índice de bits en una tabla de cadenas con codificación, pero esta analogía se "compensa" duplicando números por cadenas en las tablas de caracteres (para más detalles, vea el artículo brevemente; el valor de la columna a menudo se representa por el número Y la cadena).


La conclusión de esta breve comparación que personalmente se me ocurrió es la siguiente: el formato QVD prácticamente no contiene capacidades que permitan un almacenamiento compacto y una lectura rápida de los datos contenidos en los archivos de este formato.


(Sonaba de alguna manera ofensivo para QVD, agregaré un poco: el formato se creó hace mucho tiempo, solo se usa QlikView / QlikSense y "almacenan" todos los datos en la memoria. Creo que el archivo QVD simplemente se lee todo "tal cual" en la memoria, y luego estos maravillosos productos de BI funcionan muy rápidamente con esta presentación, aquí son maestros ...)


En lugar de una conclusión


Criticó y todavía no ha ofrecido nada ... - Sugiero.


Me parece que los formatos deben compararse no por el ejemplo de su implementación específica, los formatos deben compararse en términos de las herramientas incluidas en ellos y la capacidad de usar estas herramientas para resolver nuestros problemas específicos. La velocidad de los procesadores está en constante crecimiento, ahora podemos permitirnos casi cualquier algoritmo de conversión de datos después de leerlos; de todos modos, la lectura desde el disco será más lenta. Es por eso que los "medios expresivos" de los formatos son importantes.


Arriba, enumeré brevemente interesantes, en mi opinión, las posibilidades del formato ORC. Todavía no tengo estadísticas sobre cómo están las cosas en la práctica (cuál de estas características y hasta qué punto utiliza Hive, por ejemplo). Cuando aparezca, escribiré. Los planes inmediatos son hacer una revisión similar de otro formato de almacenamiento popular: Parquet.


Bueno, y en conclusión, en el mundo moderno hay mucha información, desafortunadamente, parte de esta información es demasiado superficial. No nos rendiremos, miraremos la esencia.

Source: https://habr.com/ru/post/458552/


All Articles