Domanda

Sto leggendo Hadoop:La guida definitiva da Tom Bianco.Nel capitolo 13.6 "HBase vs RDMS", ha detto che se si dispone di un sacco di dati, anche di semplici query come sempre di 10 elementi recenti sono extreamly costosi e hanno dovuto riscrivere loro utilizzando python e PL/SQL.

Egli dà il seguente query di esempio:

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

E dice:"un RDBMS query planner considera questa query come segue:

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;

Il problema qui è che ci sono dopo solo i primi 10 Id, ma la query planner in realtà si materializza un intera unione e quindi i limiti al fine.....Siamo andati così lontano come per scrivere una custom PL/Python script che ha eseguito un heapsort....In quasi tutti i casi, questo ha superato nativo di SQL attuazione e la query planner strategia...

Previsto perforamnce e expermiental risultati

Non potevo immaginare che il set di dati che saranno la causa di questi problemi che si devono scrivere pl/python per fare query semplice diritto.Così ho giocato per un po ' su questo problema e si avvicinò con le seguenti osservazioni:

Le prestazioni di tale query è delimitato da O(KlogN).Perché può essere tradotto in qualcosa di così come segue:

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: il LIMITE di 10' a ogni query.BTW mi sa che non si limita ordine e sindacati, ma ho spogliato avvolgimento seleziona per motivi di leggibilità)

Ogni subquery deve correre veloce come trovare la giusta collocazione in un indice O(logN) e la restituzione di 10 elementi.Se ripetiamo che K volte, si ha O(KlogN).

E anche se la query planner è così male che non può ottimizzare la prima query, possiamo sempre tradurre query con i sindacati e ottenere il rendimento desiderato senza scrivere nulla in pl/python.

Per controllare i miei calcoli ho eseguito la query di sopra di una postgresql riempito con 9,000,000 di record di test.I risultati hanno confermato le mie aspettative, sia le richieste che sono state abbastanza veloce 100ms per la prima query e 300ms per il secondo (quello con i sindacati).

Quindi, se la query viene eseguita in 100ms per 9.000.000 di (logn=23) di record quindi per 9,000,000,000 (logn=33) di record deve essere eseguito in 140 ms.

Domande

  • Si fa a vedere tutti i difetti nel ragionamento di cui sopra?
  • Si può immaginare un set di dati di cui si avrebbe bisogno di riscrivere la query come sopra in pl/python?
  • Vedi tutte le situazioni in cui tali query non O(K log n)?
È stato utile?

Soluzione

La loro affermazione che un RDMBS query planner si occupa di questa soluzione per la query non è corretto, almeno per Postgresql 9.0, e immagino anche per altre piattaforme.Ho fatto una prova veloce con una query simile:

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)

Qui client_attribute_id è indicizzato, così si fa esattamente come desiderato - torna indietro attraverso l'indice, si applica il filtro e si ferma quando l'uscita raggiunge il limite.

Se l'ordine di colonna non è indicizzato, un tavolo di analisi e di ordinamento è requierd, ma solo una scansione della tabella:

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[]))

Questo utilizza un heapsort per mantenere i primi 10 risultati con il corso di analisi sequenziale, che suona esattamente come la soluzione che hanno scritto loro stessi.

Altri suggerimenti

Non credo che Tom White dice che i database relazionali sono "cattivo";non sono ottimali per i non-relazionale, camere non-base di dati.

È stato conosciuto per lungo tempo che profondo grafici oggetto non si presta bene a database relazionali.Sono presenti di solito in problemi come il CAD rappresentazioni di dati geometrici, dove le assemblee sono fatte di assemblee di assemblaggi di pezzi.Il riferimento catene sono molto lunghi, anzi.

Oggetto del grafico e i database sono state le soluzioni a questo tipo di problemi, in quanto ero a conoscenza di loro nei primi anni ' 90.

I database relazionali sono formidabili per la dimensione relazionale, basata su set di dati.Ma tutti i dati che non rientrano in tale categoria.Ecco perché NoSQL sta guadagnando quote di mente.

Penso che l'esempio si citano sta dicendo.

RDBMS è per le query non hai pensato.Una volta che si è certi di ciò che si vuole, si può quindi applicare più la soluzione ottimale.

Con SQL o NoSQL, le prestazioni saranno orribile se si progetta la query in modo sbagliato.

Vorrei risolvere questo esempio aggiungendo un controllo sulla data e ora per la clausola where.Se si dispone di un sacco di dati, probabilmente si può presumere che il più recente 10 voci sono l'ultimo minuto, perché tenta di lettura e di smistamento di tutto, dal mese scorso?

Ho appena come facilmente potrebbe creare lo stesso esempio per rendere NoSQL male sostenendo che, poiché per impostazione predefinita, è possibile trovare solo i record con l'ID è necessario caricare l'intero set di dati per trovare i record, ignorando la possibilità di impostare i vari scuola media/indici personalizzati che meglio di prestazioni di SQL per le query che importa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top