2010-11-26 14 views
11

Estoy leyendo Hadoop: la guía definitiva de Tom White. En el capítulo 13.6 "HBase vs RDMS", dijo que si tiene una gran cantidad de datos, incluso consultas simples como obtener 10 artículos recientes son extremadamente caros y tuvieron que reescribirlos usando Python y PL/SQL.Son RDBMS tan malos como se describen en Hadoop: ¿La guía definitiva?

Se da la siguiente consulta de ejemplo:

SELECT id, stamp, type FROM streams 
WHERE type IN ('type1','type2','type3','type4',...,'typeN') 
ORDER BY stamp DESC LIMIT 10 OFFSET 0; 

Y dice: "Una consulta de RDBMS planificador trata esta consulta como sigue:

MERGE (
    SELECT id, stamp, type FROM streams 
    WHERE type = 'type1' ORDER BY stamp DESC, 
    ..., 
    SELECT id, stamp, type FROM streams 
    WHERE type = 'typeK' ORDER BY stamp DESC 
) ORDER BY stamp DESC LIMIT 10 OFFSET 0; 

El problema aquí es que estamos después de solo los 10 principales identificadores, pero la consulta planificador realmente materializa una fusión completa y luego limita al final .... Fuimos tan lejos como para escribir un guión PL/Python personalizado que realizó un heapsort. ... En casi todos los casos, este superó la implementación de SQL nativo y la estrategia del planificador consulta ...

perforamnce esperado y los resultados expermiental

no podía imaginar el conjunto de datos eso causará tales problemas que tienes que escribir pl/python para hacer una consulta tan simple a la derecha. Así que he jugado durante un tiempo sobre este problema y se produjeron las siguientes observaciones:

El rendimiento de dicha consulta está limitado por O (KlogN). Debido a que puede ser traducido a lo que algo de la siguiente manera:

SELECT * FROM (
    SELECT id, stamp, type FROM streams 
    WHERE type = 'type1' ORDER BY stamp DESC LIMIT 10, 
    UNION 
    ..., 
    SELECT id, stamp, type FROM streams 
    WHERE type = 'typeK' ORDER BY stamp DESC LIMIT 10 
) t ORDER BY stamp DESC LIMIT 10; 

(Nota de la LÍMITE 10 'a cada consulta BTW Yo sé que no puedo limitar y uniones de orden pero yo he despojado a cabo envolviendo a las selecciones. en aras de la legibilidad)

Cada sub consulta debe ejecutarse tan rápido como encontrar la posición correcta en un índice O (logN) y devolver 10 elementos. Si repetimos esa K veces obtenemos O (KlogN).

Y aunque el planificador de consultas es tan malo que no puede optimizar la primera consulta siempre podemos traducirlo a la consulta con uniones y obtener el rendimiento deseado sin escribir nada en pl/python.

Para verificar mis cálculos, he realizado las consultas sobre un postgresql lleno con 9,000,000 de registros de prueba. Los resultados confirmaron mis expectativas de que ambas consultas fueron bastante rápidas, 100 ms para la primera consulta y 300 ms para la segunda (la que tenía los sindicatos).

Así que si la consulta se ejecuta en 100ms para 9,000,000 (logn = 23) de registros, entonces para 9,000,000,000 (logn = 33) de registros debe ejecutarse en 140ms.

Preguntas

  • , ¿existen otras fallas en el razonamiento anterior?
  • ¿Se imagina un conjunto de datos en el que necesitaría volver a escribir la consulta anterior en pl/python?
  • ¿Ve alguna situación en la que dicha consulta no funcionaría en O (K log n)?
+0

No, no lo son. ¿Qué base de datos consulta una tabla completa una vez para cada elemento en un filtro de un campo, fusiona todos los registros, los ordena y luego limita al final? – MkV

Respuesta

6

Su afirmación de que un planificador de consultas RDMBS lleva esa solución a la consulta es incorrecta, al menos para Postgresql 9.0, y debería imaginar para otras plataformas también. Hice una prueba rápida con una consulta similar:

explain select * from client_attribute where client_attribute_type_code in ('UAG', 'RFR', 'IPA', 'FVD') order by client_attribute_id desc limit 10; 

                 QUERY PLAN 
----------------------------------------------------------------------------------------------------------------------- 
Limit (cost=0.00..0.93 rows=10 width=85) 
    -> Index Scan Backward using client_attribute_pkey on client_attribute (cost=0.00..15516.47 rows=167234 width=85) 
     Filter: (client_attribute_type_code = ANY ('{UAG,RFR,IPA,FVD}'::bpchar[])) 
(3 rows) 

Aquí client_attribute_id está indexada, por lo que hace exactamente como desear, camina de vuelta a través del índice, se aplica el filtro y se detiene cuando la salida golpea el límite.

Si la columna de ordenación no está indexado, un recorrido de tabla y clasificar es requierd, pero sólo una mesa de exploración:

explain analyze select * from client_attribute where client_attribute_type_code in ('UAG', 'RFR', 'IPA', 'FVD') order by updated desc limit 10; 

                   QUERY PLAN 
--------------------------------------------------------------------------------------------------------------------------------------- 
Limit (cost=13647.00..13647.03 rows=10 width=85) (actual time=180.961..180.964 rows=10 loops=1) 
    -> Sort (cost=13647.00..14065.09 rows=167234 width=85) (actual time=180.960..180.961 rows=10 loops=1) 
     Sort Key: updated 
     Sort Method: top-N heapsort Memory: 26kB 
     -> Seq Scan on client_attribute (cost=0.00..10033.14 rows=167234 width=85) (actual time=0.010..106.791 rows=208325 loops=1) 
       Filter: (client_attribute_type_code = ANY ('{UAG,RFR,IPA,FVD}'::bpchar[])) 

Este utiliza un heapsort para mantener los 10 primeros resultados en el transcurso de la exploración secuencial , que suena exactamente como la solución que ellos mismos escribieron.

4

No creo que Tom White diga que las bases de datos relacionales son "malas"; no son óptimos para datos no relacionales ni basados ​​en conjuntos.

Es bien sabido desde hace mucho tiempo que los gráficos de objetos profundos no se prestan bien a las bases de datos relacionales. Normalmente se encuentran en problemas como las representaciones CAD de datos geométricos, donde los ensamblajes se componen de conjuntos de conjuntos de partes. Las cadenas de referencia son muy largas, de hecho.

Las bases de datos de objetos y gráficos han sido la solución a ese tipo de problemas, ya que los conocía a principios de los años 90.

Las bases de datos relacionales son excelentes para los datos relacionales basados ​​en conjuntos. Pero todos los datos no entran en esa categoría. Es por eso que NoSQL está ganando parte de la mente.

Creo que eso es lo que dice el ejemplo que usted cita.

+3

Lo que parece estar diciendo es que los planificadores de consultas en RDBMS son malos, escribirlo en Python es mejor, pero usar un ejemplo inventado que no es representativo de los planificadores de consultas reales utilizados por RDBMS reales. – MkV

1

RDBMS es para las consultas que no ha pensado. Una vez que esté seguro de lo que desea, puede aplicar la solución más óptima.

1

Con SQL o NoSQL, el rendimiento será horrible si diseña sus consultas de forma incorrecta.

Arreglaré ese ejemplo agregando una marca de tiempo a la cláusula where. Si tiene muchos datos, probablemente pueda suponer que las 10 entradas más recientes son del último minuto, entonces, ¿por qué intentar leer y ordenar todo el último mes?

Podría fácilmente idear el mismo ejemplo para hacer que NoSQL se vea mal al afirmar que, como por defecto solo puede encontrar registros por ID, tendrá que cargar todo el conjunto de datos para encontrar el registro que necesita, ignorando la capacidad de configure varios índices secundarios/personalizados que le harán mejor que el rendimiento de SQL para las consultas que importan.

Cuestiones relacionadas