Colma il divario SQL-NoSQL con Apache Phoenix

Apache Phoenix è un progetto Java open source relativamente nuovo che fornisce un driver JDBC e l'accesso SQL al database NoSQL di Hadoop: HBase. È stato creato come progetto interno in Salesforce, open source su GitHub, ed è diventato un progetto Apache di primo livello nel maggio 2014. Se hai forti capacità di programmazione SQL e desideri poterle utilizzare con un potente database NoSQL, Phoenix potrebbe essere esattamente quello che stai cercando!

Questo tutorial introduce gli sviluppatori Java ad Apache Phoenix. Poiché Phoenix viene eseguito su HBase, inizieremo con una panoramica di HBase e di come si differenzia dai database relazionali. Imparerai come Phoenix colma il divario tra SQL e NoSQL e come è ottimizzato per interagire in modo efficiente con HBase. Dopo aver tolto queste nozioni di base, passeremo il resto dell'articolo a imparare come lavorare con Phoenix. Configurerai e integrerai HBase e Phoenix, creerai un'applicazione Java che si connette a HBase tramite Phoenix e scriverai la tua prima tabella, inserirai dati ed eseguirai alcune query su di essa.

Quattro tipi di archivio dati NoSQL

È interessante (e un po 'ironico) che gli archivi dati NoSQL siano classificati in base a una caratteristica che mancano, vale a dire SQL. Gli archivi dati NoSQL sono disponibili in quattro versioni generali:

  1. Memorizza chiave / valore mappare una chiave specifica a un valore, che può essere un documento, un array o un tipo semplice. Esempi di archivi chiave / valore includono Memcached, Redis e Riak.
  2. Gli archivi di documenti gestiscono i documenti, che di solito sono strutture senza schema, come JSON, che possono essere di complessità arbitraria. La maggior parte degli archivi di documenti fornisce supporto per indici primari, indici secondari e query complesse. Esempi di archivi di documenti includono MongoDB e CouchBase.
  3. I database di grafici si concentrano principalmente sulle relazioni tra gli oggetti in cui i dati sono archiviati nei nodi e nelle relazioni tra i nodi. Un esempio di database a grafo è Neo4j.
  4. I database orientati alle colonne memorizzano i dati come sezioni di colonne di dati anziché come righe di dati. HBase è un database orientato alle colonne, così come Cassandra.

HBase: un primer

Apache HBase è un database NoSQL che viene eseguito su Hadoop come un big data store distribuito e scalabile. HBase è un database orientato alle colonne che sfrutta le capacità di elaborazione distribuita di Hadoop Distributed File System (HDFS) e il paradigma di programmazione MapReduce di Hadoop. È stato progettato per ospitare tabelle di grandi dimensioni con miliardi di righe e potenzialmente milioni di colonne, tutte in esecuzione su un cluster di hardware di base.

Apache HBase combina la potenza e la scalabilità di Hadoop con la capacità di eseguire query per singoli record ed eseguire processi MapReduce.

Oltre alle funzionalità ereditate da Hadoop, HBase è un potente database a sé stante: combina query in tempo reale con la velocità di un archivio chiave / valore, una solida strategia di scansione delle tabelle per individuare rapidamente i record e supporta l'elaborazione batch utilizzando MapReduce. In quanto tale, Apache HBase combina la potenza e la scalabilità di Hadoop con la capacità di eseguire query per singoli record ed eseguire processi MapReduce.

Modello di dati di HBase

HBase organizza i dati in modo diverso dai database relazionali tradizionali, supportando un modello di dati quadridimensionale in cui ogni "cella" è rappresentata da quattro coordinate:

  1. Chiave di riga : ogni riga ha una chiave di riga univoca rappresentata internamente da una matrice di byte, ma non ha alcun tipo di dati formale.
  2. Famiglia di colonne : i dati contenuti in una riga vengono partizionati in famiglie di colonne ; ogni riga ha lo stesso insieme di famiglie di colonne, ma non è necessario che ciascuna famiglia di colonne mantenga lo stesso insieme di qualificatori di colonna. Si può pensare che le famiglie di colonne siano simili alle tabelle in un database relazionale.
  3. Qualificatore di colonna : sono simili alle colonne in un database relazionale.
  4. Versione : ogni colonna può avere un numero di versioni configurabile . Se richiedi i dati contenuti in una colonna senza specificare una versione, ricevi l'ultima versione, ma puoi richiedere versioni precedenti specificando un numero di versione.

La figura 1 mostra come queste coordinate quadridimensionali sono correlate.

Steven Haines

Il modello nella Figura 1 mostra che una riga è composta da una chiave di riga e da un numero arbitrario di famiglie di colonne. Ogni chiave di riga è associata a una raccolta di "righe nelle tabelle", ciascuna delle quali ha le proprie colonne. Sebbene ogni tabella debba esistere, le colonne nelle tabelle potrebbero essere diverse tra le righe. Ogni famiglia di colonne ha un insieme di colonne e ogni colonna ha un insieme di versioni che mappano ai dati effettivi nella riga.

Se stessimo modellando una persona, la chiave di riga potrebbe essere il numero di previdenza sociale della persona (per identificarla in modo univoco) e potremmo avere famiglie di colonne come indirizzo, impiego, istruzione e così via. All'interno della famiglia di colonne degli indirizzi potremmo avere colonne via, città, stato e codice postale e ogni versione potrebbe corrispondere a dove la persona viveva in un dato momento. L'ultima versione potrebbe elencare la città "Los Angeles", mentre la versione precedente potrebbe elencare "New York". Puoi vedere questo modello di esempio nella Figura 2.

Steven Haines

In sintesi, HBase è un database orientato alle colonne che rappresenta i dati in un modello quadridimensionale. Si basa sull'Hadoop Distributed File System (HDFS), che partiziona i dati su potenzialmente migliaia di computer comuni. Gli sviluppatori che utilizzano HBase possono accedere ai dati direttamente accedendo a una chiave di riga, eseguendo la scansione su un intervallo di chiavi di riga o utilizzando l'elaborazione batch tramite MapReduce.

Ricerca fondamentale

Potresti o meno avere familiarità con i famosi (per i geek) White Paper sui Big Data. Pubblicati da Google Research tra il 2003 e il 2006, questi white paper hanno presentato la ricerca per tre pilastri dell'ecosistema Hadoop come lo conosciamo:

  • Google File System (GFS): Hadoop Distributed File System (HDFS) è un'implementazione open source di GFS e definisce il modo in cui i dati vengono distribuiti su un cluster di macchine comuni.
  • MapReduce: un paradigma di programmazione funzionale per l'analisi dei dati distribuiti in un cluster HDFS.
  • Bigtable: un sistema di archiviazione distribuito per la gestione dei dati strutturati progettato per scalare a dimensioni molto grandi: petabyte di dati su migliaia di computer comuni. HBase è un'implementazione open source di Bigtable.

Colmare il divario NoSQL: Apache Phoenix

Apache Phoenix è un progetto Apache di primo livello che fornisce un'interfaccia SQL a HBase, mappando i modelli HBase a un mondo di database relazionale. Naturalmente, HBase fornisce la propria API e shell per eseguire funzioni come scan, get, put, list e così via, ma più sviluppatori hanno familiarità con SQL rispetto a NoSQL. L'obiettivo di Phoenix è fornire un'interfaccia comunemente compresa per HBase.

In termini di funzionalità, Phoenix fa quanto segue:

  • Fornisce un driver JDBC per interagire con HBase.
  • Supporta gran parte dello standard ANSI SQL.
  • Supporta operazioni DDL come CREATE TABLE, DROP TABLE e ALTER TABLE.
  • Supporta operazioni DML come UPSERT e DELETE.
  • Compila le query SQL nelle scansioni HBase native e quindi mappa la risposta ai ResultSet JDBC.
  • Supporta schemi con versione.

Oltre a supportare una vasta gamma di operazioni SQL, Phoenix offre anche prestazioni molto elevate. Analizza le query SQL, le suddivide in più scansioni HBase e le esegue in parallelo, utilizzando l'API nativa invece dei processi MapReduce.

Phoenix utilizza due strategie - co-processori e filtri personalizzati - per avvicinare i calcoli ai dati:

  • I coprocessori eseguono operazioni sul server, riducendo al minimo il trasferimento di dati client / server.
  • I filtri personalizzati riducono la quantità di dati restituiti in una risposta alla query dal server, riducendo ulteriormente la quantità di dati trasferiti. I filtri personalizzati vengono utilizzati in alcuni modi:
    1. Quando si esegue una query, è possibile utilizzare un filtro personalizzato per identificare solo le famiglie di colonne essenziali richieste per soddisfare la ricerca.
    2. Un filtro per saltare la scansione utilizza SEEK_NEXT_USING_HINT di HBase per passare rapidamente da un record al successivo, il che accelera le query di punti.
    3. Un filtro personalizzato può "salare i dati", nel senso che aggiunge un byte hash all'inizio della chiave di riga in modo che possa individuare rapidamente i record.

In sintesi, Phoenix sfrutta l'accesso diretto alle API HBase, ai coprocessori e ai filtri personalizzati per offrirti prestazioni di livello millisecondo per set di dati di piccole dimensioni e prestazioni di secondo livello per quelli giganteschi. Soprattutto, Phoenix espone queste capacità agli sviluppatori tramite una familiare interfaccia JDBC e SQL.

Inizia con Phoenix

Per utilizzare Phoenix, è necessario scaricare e installare sia HBase che Phoenix. Puoi trovare la pagina di download di Phoenix (e le note sulla compatibilità di HBase) qui.

Scarica e installa

Al momento della stesura di questo documento, l'ultima versione di Phoenix è 4.6.0 e la pagina di download dice che 4.x è compatibile con la versione HBase 0.98.1+. Per il mio esempio, ho scaricato l'ultima versione di Phoenix configurata per funzionare con HBase 1.1. Lo si può trovare nella cartella: phoenix-4.6.0-HBase-1.1/.

Ecco la configurazione:

  1. Download and decompress this archive and then use one of the recommended mirror pages here to download HBase. For instance, I selected a mirror, navigated into the 1.1.2 folder, and downloaded hbase-1.1.2-bin.tar.gz.
  2. Decompress this file and create an HBASE_HOME environment variable that points to it; for example, I added the following to my ~/.bash_profile file (on Mac): export HBASE_HOME=/Users/shaines/Downloads/hbase-1.1.2.

Integrate Phoenix with HBase

The process to integrate Phoenix into HBase is simple:

  1. Copy the following file from the Phoenix root directory to the HBase lib directory: phoenix-4.6.0-HBase-1.1-server.jar.
  2. Start HBase by executing the following script from HBase's bin directory:./start-hbase.sh.
  3. With HBase running, test that Phoenix is working by executing the SQLLine console, by executing following command from Phoenix's bin directory: ./sqlline.py localhost.

The SQLLine console

sqlline.py is a Python script that starts a console that connects to HBase's Zookeeper address; localhost in this case. You can walk through an example that I am going to summarize in this section here.

First, let's view all of the tables in HBase by executing !table:

 0: jdbc:phoenix:localhost> !tables +------------------------------------------+------------------------------------------+------------------------------------------+------------------------------------------+--------------------------+ | TABLE_CAT | TABLE_SCHEM | TABLE_NAME | TABLE_TYPE | REMARKS | +------------------------------------------+------------------------------------------+------------------------------------------+------------------------------------------+--------------------------+ | | SYSTEM | CATALOG | SYSTEM TABLE | | | | SYSTEM | FUNCTION | SYSTEM TABLE | | | | SYSTEM | SEQUENCE | SYSTEM TABLE | | | | SYSTEM | STATS | SYSTEM TABLE | | +------------------------------------------+------------------------------------------+------------------------------------------+------------------------------------------+--------------------------+ 

Because this is a new instance of HBase the only tables that exist are system tables. You can create a table by executing a create table command:

 0: jdbc:phoenix:localhost>create table test (mykey integer not null primary key, mycolumn varchar); No rows affected (2.448 seconds) 

This command creates a table named test, with an integer primary key named mykey and a varchar column named mycolumn. Now insert a couple rows by using the upsert command:

 0: jdbc:phoenix:localhost>upsert into test values (1,'Hello'); 1 row affected (0.142 seconds) 0: jdbc:phoenix:localhost>upsert into test values (2,'World!'); 1 row affected (0.008 seconds) 

UPSERTè un comando SQL per inserire un record se non esiste o per aggiornare un record se esiste. In questo caso, abbiamo inserito (1, 'Hello') e (2, 'World!'). Puoi trovare il riferimento completo al comando Phoenix qui. Infine, interroga la tua tabella per vedere i valori che hai inserito eseguendo select * from test:

 0: jdbc:phoenix:localhost>select * from test; +------------------------------------------+------------------------------------------+ | MYKEY | MYCOLUMN | +------------------------------------------+------------------------------------------+ | 1 | Hello | | 2 | World! | +------------------------------------------+------------------------------------------+ 2 rows selected (0.111 seconds) 

Come previsto, vedrai i valori che hai appena inserito. Se vuoi pulire la tabella, esegui un drop table testcomando.