tutorial spark read sql apache-spark apache-spark-sql in-memory-database bigdata

read - spark sql tutorial



¿Por qué Spark SQL considera que el soporte de índices no es importante? (2)

Citando el manual Spark DataFrames, Datasets y SQL :

Un puñado de optimizaciones de Hive aún no están incluidas en Spark. Algunos de estos (como los índices) son menos importantes debido al modelo computacional en memoria de Spark SQL. Otros están ranurados para futuras versiones de Spark SQL.

Siendo nuevo en Spark, estoy un poco desconcertado por esto por dos razones:

  1. Spark SQL está diseñado para procesar Big Data, y al menos en mi caso de uso, el tamaño de los datos supera con creces el tamaño de la memoria disponible. Suponiendo que esto no es raro, ¿qué significa "modelo computacional en memoria de Spark SQL"? ¿Se recomienda Spark SQL solo para los casos en que los datos encajan en la memoria?

  2. Incluso suponiendo que los datos encajen en la memoria, un escaneo completo de un conjunto de datos muy grande puede llevar mucho tiempo. Leí este argumento contra la indexación en la base de datos en memoria, pero no estaba convencido. El ejemplo allí discute un escaneo de una tabla de 10,000,000 de registros, pero eso no es realmente un gran dato. Escanear una tabla con miles de millones de registros puede hacer que las consultas simples del tipo "SELECCIONE x DONDE y = z" tomen para siempre en lugar de regresar inmediatamente.

Entiendo que los índices tienen desventajas, como INSERT / UPDATE más lento, requisitos de espacio, etc. Pero en mi caso de uso, primero proceso y cargo un gran lote de datos en Spark SQL y luego exploro estos datos como un todo, sin más modificaciones. Spark SQL es útil para el procesamiento distribuido inicial y la carga de los datos, pero la falta de indexación hace que la exploración interactiva sea más lenta y más engorrosa de lo que esperaba.

Me pregunto por qué el equipo de Spark SQL considera que los índices no son importantes hasta el punto en que están fuera de su mapa de ruta. ¿Existe un patrón de uso diferente que pueda proporcionar los beneficios de la indexación sin recurrir a la implementación de algo equivalente de manera independiente?


En general, la utilidad de los índices es cuestionable en el mejor de los casos. En cambio, la partición de datos es más importante. Son cosas muy diferentes, y solo porque su base de datos de elección admita índices no significa que tengan sentido dado lo que Spark está tratando de hacer. Y no tiene nada que ver con "en la memoria".

Entonces, ¿qué es un índice?

En los días en que el almacenamiento permanente era una locura costosa (en lugar de esencialmente gratuita), los sistemas de bases de datos relacionales tenían que ver con minimizar el uso del almacenamiento permanente. El modelo relacional, por necesidad, dividió un registro en múltiples partes, normalizó los datos, y los almacenó en diferentes ubicaciones. Para leer un registro de cliente, tal vez lea una tabla de customer , una tabla customerType , saque un par de entradas de una tabla de address , etc. Si tenía una solución que requería que leyera toda la tabla para encontrar lo que deseaba, es muy costoso, porque tienes que escanear tantas tablas.

Pero esta no es la única forma de hacer las cosas. Si no necesitó columnas de ancho fijo, puede almacenar todo el conjunto de datos en un solo lugar. En lugar de hacer un escaneo de tabla completa en varias tablas, solo necesita hacerlo en una sola tabla. Y eso no es tan malo como crees, especialmente si puedes dividir tus datos.

40 años después, las leyes de la física han cambiado. Las velocidades de lectura / escritura aleatorias del disco duro y las velocidades de lectura / escritura lineales han divergido drásticamente. Básicamente puedes hacer 350 movimientos de cabeza por segundo por disco. (Un poco más o menos, pero ese es un buen número promedio). Por otro lado, una sola unidad de disco puede leer aproximadamente 100 MB por segundo. Qué significa eso?

Haga los cálculos y piense al respecto, significa que si está leyendo menos de 300 KB por movimiento de la unidad de disco, está acelerando el rendimiento de la unidad .

Seriouusly. Piense en eso un segundo.

El objetivo de un índice es permitirle mover el cabezal de disco a la ubicación precisa en el disco que desea y simplemente leer ese registro; digamos solo el registro de address unido como parte de su registro de customer . Y digo, eso es inútil.

Si estuviera diseñando un índice basado en la física moderna, solo necesitaría acercarme a 100KB más o menos de la pieza de datos objetivo (suponiendo que mis datos se hubieran presentado en grandes porciones, pero de todos modos estamos hablando de teoría). . De acuerdo con los números anteriores, cualquier precisión adicional es simplemente un desperdicio.

Ahora regrese a su diseño de mesa normalizado. Supongamos que un registro de customer realmente está dividido en 6 filas en 5 tablas. 6 movimientos totales de la cabeza del disco (supongo que el índice está almacenado en la memoria caché, por lo que no hay movimiento del disco). Eso significa que puedo leer 1.8 MB de registros de clientes lineales / des-normalizados y ser igual de eficientes.

¿Y qué hay de la historia del cliente? Supongamos que quisiera no solo ver cómo se ve el cliente hoy en día: ¿imagino que quiero la historia completa o un subconjunto de la historia? Multiplique todo lo anterior por 10 o 20 y obtendrá la imagen.

Lo que sería mejor que un índice sería la partición de datos, asegurándose de que todos los registros de los clientes terminen en una partición. De esa manera, con un único movimiento de cabezal de disco, puedo leer todo el historial del cliente. Un movimiento de cabeza de disco.

Dime otra vez por qué quieres índices.

Índices vs ___?

No me malinterprete, hay un valor en "precocinar" sus búsquedas. Pero las leyes de la física sugieren una mejor manera de hacerlo que los índices tradicionales. En lugar de almacenar el registro del cliente en exactamente una ubicación y crear un puntero al mismo, un índice, ¿por qué no almacenar el registro en múltiples ubicaciones?

Recuerde, el espacio en el disco es esencialmente gratuito. En lugar de intentar minimizar la cantidad de almacenamiento que utilizamos, un artefacto obsoleto del modelo relacional, simplemente use su disco como su caché de búsqueda.

Si cree que alguien desea ver a los clientes detallados por geografía y por representante de ventas, haga copias múltiples de los registros de sus clientes almacenados de manera que optimicen esas búsquedas. Como dije, usa el disco como tu en memoria caché. En lugar de construir su caché en memoria juntando piezas dispares de datos persistentes, cree sus datos persistentes para duplicar su caché en memoria, de modo que todo lo que tiene que hacer es leerlo. De hecho, ni siquiera te molestes en intentar almacenarlo en la memoria, solo léelo directamente del disco cada vez que lo necesites.

Si crees que eso suena loco, considera esto: si lo guardas en la memoria, es probable que lo guardes en caché dos veces. Es probable que su controlador de sistema operativo / unidad use la memoria principal como caché. ¡No te molestes en guardar los datos en caché porque ya lo está alguien!

Pero yo divago...

Para resumir, Spark definitivamente admite el tipo de indexación correcto: la capacidad de crear datos derivados complicados a partir de datos brutos para hacer que los usos futuros sean más eficientes. Simplemente no lo hace de la manera en que lo desea.


Datos de entrada de indexación

  • La razón fundamental por la cual la indexación sobre fuentes de datos externas no está en el alcance de Spark es que Spark no es un sistema de administración de datos sino un motor de procesamiento de datos por lotes. Como no posee los datos que está utilizando, no puede monitorear de manera confiable los cambios y, en consecuencia, no puede mantener los índices.
  • Si la fuente de datos es compatible con la indexación, Spark puede utilizarla indirectamente a través de mecanismos como la inserción de predicados.

Indexación de estructuras de datos distribuidos :

  • las técnicas de indexación estándar requieren una distribución de datos persistente y bien definida, pero los datos en Spark suelen ser efímeros y su distribución exacta no es determinista.
  • el diseño de datos de alto nivel logrado mediante una partición adecuada combinada con almacenamiento y compresión en columnas puede proporcionar un acceso distribuido muy eficiente sin una sobrecarga de creación, almacenamiento y mantenimiento de índices. Este es un patrón común utilizado por diferentes sistemas columnares en memoria.

Dicho esto, existen algunas formas de estructuras indexadas en el ecosistema Spark. En particular, Databricks proporciona Data Skipping Index en su plataforma.

Otros proyectos, como Succinct (en su mayoría inactivo hoy en día) adoptan un enfoque diferente y usan técnicas avanzadas de compresión con soporte de acceso aleatorio.

Por supuesto, esto plantea una pregunta: si se requiere un acceso aleatorio eficiente, ¿por qué no utilizar un sistema que es el diseño como una base de datos desde el principio? Hay muchas opciones, incluidas al menos algunas mantenidas por la Fundación Apache. Al mismo tiempo, Spark como proyecto evoluciona, y la cita que usó podría no reflejar completamente las futuras direcciones de Spark.