La diferencia entre RDD, DataFrame y DataSet
RDD, DataFrame y DataSet son conceptos que se confunden fácilmente. Debes compararlos entre sí para conocer las similitudes y diferencias.
RDD y DataFrame
RDD-DataFrame
La figura anterior refleja intuitivamente la diferencia entre DataFrame y RDD. Aunque el RDD [Persona] de la izquierda usa Persona como parámetro de tipo, el marco Spark en sí no comprende la estructura interna de la clase Persona
. El DataFrame de la derecha proporciona información estructural detallada, lo que permite a Spark
SQL saber claramente qué columnas están incluidas en el conjunto de datos y cuál es el nombre y tipo de cada columna. DataFrame tiene más información estructural de los datos, es decir, esquema. RDD es una colección de
objetos Java distribuidos. DataFrame es una colección distribuida de objetos Row. Además de proporcionar operadores más completos que RDD, las características más importantes de DataFrame son la eficiencia de ejecución mejorada, la lectura de datos reducida y la optimización de los planes de ejecución, como la eliminación de filtros, el recorte, etc.
Mejorar la eficiencia de ejecución
RDD
La API es funcional y enfatiza la inmutabilidad. En la mayoría de los escenarios, tiende a crear nuevos objetos en lugar de modificar objetos antiguos. Aunque esta característica brinda una API limpia y ordenada, también hace que las aplicaciones Spark tiendan a crear una gran cantidad de objetos temporales durante el tiempo de ejecución, lo que ejerce presión sobre el GC. Sobre la base de la
API RDD existente, ciertamente podemos usar el método mapPartitions para sobrecargar el método de creación de datos dentro de un único fragmento RDD y usar el método de reutilización de objetos variables para reducir la asignación de objetos y p>
Sobrecarga de GC, pero esto sacrifica la legibilidad del código y requiere que los desarrolladores tengan cierta comprensión del mecanismo de tiempo de ejecución de Spark, y el umbral es alto. Por otro lado, Spark
SQL ha hecho todo lo posible para reutilizar objetos en cada situación posible dentro del marco. Aunque hacerlo romperá la invariancia internamente, aún así hará que los datos se devuelvan al usuario. Reconvertir a datos inmutables. Al desarrollar utilizando
API DataFrame, puede disfrutar de estos efectos de optimización de forma gratuita.
Reducir la lectura de datos
La forma más rápida de analizar big data es ignorarlo. "Ignorar" aquí no significa hacer la vista gorda, sino podar adecuadamente de acuerdo con las condiciones de la consulta.
La poda de particiones mencionada anteriormente cuando se analizan las tablas particionadas es una de ellas: cuando las condiciones del filtro de consulta involucran columnas de partición, podemos podar aquellas que definitivamente no contienen los datos de destino según las condiciones del directorio de partición de la consulta. reduciendo así la IO.
Para algunos formatos de datos "inteligentes", Spark
SQL también puede realizar una poda basada en la información estadística adjunta al archivo de datos. En pocas palabras, en este tipo de formato de datos, los datos se guardan en segmentos y cada segmento de datos tiene información estadística básica, como el valor máximo, el valor mínimo, el número de valores nulos, etc.
Cuando un determinado segmento de datos del nombre de la tabla de información estadística definitivamente no incluye datos de destino que cumplan con las condiciones de la consulta, el segmento de datos se puede omitir directamente (por ejemplo, el valor máximo de un determinado segmento de una columna entera a es 100, y la consulta
Las condiciones de consulta requieren un > 200).
Además, Spark SQL también puede aprovechar al máximo las ventajas de los formatos de almacenamiento de columnas como RCFile, ORC y Parquet para escanear solo las columnas realmente involucradas en la consulta e ignorar los datos de otras columnas.
Realización de la optimización
Ejemplo de análisis de datos de población
Para ilustrar la optimización de consultas, veamos el ejemplo de análisis de datos de población que se muestra en la figura anterior. En la figura, se construyen dos DataFrames y se realiza una operación de filtrado después de unirlos. Si
si este plan de ejecución se ejecuta sin cambios, la eficiencia de ejecución final no será alta. Dado que la unión es una operación costosa, también puede producir un conjunto de datos más grande.
Si podemos presionar el filtro
debajo de la unión, filtrar primero el marco de datos y luego unir el conjunto de resultados más pequeño filtrado, podemos acortar efectivamente el tiempo de ejecución. Y el optimizador de consultas de Spark
SQL hace exactamente esto. En resumen, la optimización del plan de consultas lógicas es un proceso que utiliza transformaciones equivalentes basadas en álgebra relacional para reemplazar operaciones de alto costo con operaciones de bajo costo.
En el proceso de convertir el plan de ejecución optimizado obtenido en un plan de ejecución física, las condiciones de filtrado también se pueden enviar a la fuente de datos de acuerdo con las características de la fuente de datos específica. La razón por la que Filter desaparece en el plan de ejecución física en el extremo derecho es porque se disuelve en el nodo de escaneo de la tabla utilizado para realizar la operación de lectura final.
Para los desarrolladores comunes, la importancia del optimizador de consultas es que incluso las consultas subóptimas escritas por programadores sin experiencia se pueden convertir en una forma de ejecución lo más eficiente posible.
RDD y DataSet
DataSet está representado por el plan de ejecución lógica de Catalyst, y los datos se almacenan en forma binaria codificada y operaciones como clasificación y reproducción aleatoria se pueden realizar sin deserialización.
La creación de un conjunto de datos requiere un codificador explícito para serializar el objeto en binario y asignar el esquema del objeto al tipo SparkSQl. Sin embargo, RDD se basa en el mecanismo de reflexión del tiempo de ejecución.
A través de los dos puntos anteriores, el rendimiento de DataSet es mucho mejor que el de RDD.
DataFrame y DataSet
Dataset se puede considerar un caso especial de DataFrame. La principal diferencia es que cada registro de Dataset almacena un valor fuertemente tipado en lugar de una fila. Por lo tanto, tiene las siguientes tres características:
DataSet puede verificar el tipo en tiempo de compilación
y es una interfaz de programación orientada a objetos. Utilice el recuento de palabras como ejemplo:
//DataFrame
// Cargue un archivo de texto e interprete cada línea como java.lang.String
val ds = sqlContext.read.text("/home/spark/1.6/lines").as[String]
val resultado = ds
.flatMap(_.split(" ") ) // Dividir en espacios en blanco
.filter(_ != "") // Filtrar palabras vacías
.toDF() // Convertir a DataFrame para realizar agregación/clasificación p>
.groupBy($"value") // Cuenta el número de apariciones de cada palabra
.agg(count("*") as "numOccurances")
.orderBy ($"numOccurances" desc) // Mostrar primero las palabras más comunes
Las versiones posteriores de DataFrame heredarán DataSet como una interfaz para Spark SQL.
//DataSet, use la programación Scala por completo, no cambie a DataFrame
val wordCount =
ds.flatMap(_.split(" "))
.filter(_ != "")
.groupBy(_.toLowerCase()) // En lugar de agrupar en una expresión de columna (es decir, $"valor") pasamos una función lambda
.count()
DataFrame y DataSet se pueden convertir entre sí. df.as[ElementType] puede convertir DataFrame en DataSet, ds.toDF() puede convertir. DataSet en Convertir a DataFrame.