Progetto NoSQL
Progetto NoSQL
468800
Progetto NoSQL
Confronto prestazionale tra i database Oracle e Neo4j
Tra i cambiamenti più evidenti non si può non notare l'impennata che hanno subito gli
acquisti online, risposta naturale alle restrizioni dovute alla pandemia.
3) Truffe sui prodotti: aziende che vendono prodotti non approvati o con marchi
errati. FinCEN ha ricevuto segnalazioni relative alla commercializzazione
fraudolenta di forniture relative al COVID-19, come alcune mascherine.
1
Krishnakumaran Sivakumaran - 468800
TECNOLOGIE UTILIZZATE
I DBMS che verranno utilizzati sono:
Per gli esperimenti si è fatto uso di una serie di dataset di dimensione crescente (25%,
50%, 75% e 100%) che, nel complesso, rappresentano una struttura dati dove sono
descritte le sentenze alle aziende che sono state giudicate colpevoli di frodi
riconducibili alle categorie elencate nell'introduzione in un arco temporale di circa 2
anni (da marzo 2020 a gennaio 2022). I dataset sono in formato .csv.
I dataset per i vari esperimenti sono stati generati attraverso la libreria Faker
disponibile per il linguaggio di programmazione Python (versione 3.10) e nel
medesimo linguaggio sono stati realizzati gli script per eseguire le operazioni previste
per la realizzazione del benchmark in maniera automatizzata. Per semplicità nella
manipolazione dei dati, si è scelto di suddividere i dati da importare nei DBMS in file
.csv separati, ciascuno dei quali rappresenta un elemento differente nelle relazioni tra
i dati.
Il caricamento dei dati nelle tabelle di Oracle è stato realizzato attraverso il tool
SQL*Loader 19.3 fornito da Oracle e già presente nel container. Analogamente, è
stato il tool utilizzato "Neo4j-admin" per il caricamento dei dati, per la creazione dei
nodi e l'aggiunta di "etichette" (label) a ciascun nodo.
2
Krishnakumaran Sivakumaran - 468800
È un ORDBMS, fa parte della famiglia dei database di tipo SQL. Troviamo, quindi, il
supporto al linguaggio SQL, vantaggio notevole considerando l'espressività che lo
caratterizza e che è definito da uno standard, a differenza dei linguaggi disponibili
nelle soluzioni NoSQL.
Neo4j
L'informazione è contenuta nelle proprietà nei nodi che compongono il grafo. Gli archi
che collegano i singoli nodi sono sempre orientati, rappresentano le relazioni tra le
entità, e possono avere anch'essi delle proprietà.
Il linguaggio impiegato per l'interazione con DBMS è Cypher, creato con l'intento di
essere il più semplice ed intuitivo possibile nella sintassi. Abbiamo anche la possibilità
di poter interagire con il DB sfruttando anche altri linguaggi di programmazione
attraverso degli adattatori/driver ufficiali oppure sviluppati dalla community.
3
Krishnakumaran Sivakumaran - 468800
PROGETTAZIONE
Come detto precedentemente, il contenuto dei file che costituiscono i vari dataset
rappresentano uno storico delle sentenze emesse nei confronti delle varie aziende. Si
è scelto di inserire record provenienti da tutto il mondo e le aziende, per semplicità,
sono tutte multinazionali.
Di seguito lo schema che descrive la struttura delle tabelle presenti all'interno dei
database e il diagramma E-R.
4
Krishnakumaran Sivakumaran - 468800
Diagramma E-R
5
Krishnakumaran Sivakumaran - 468800
IMPLEMENTAZIONE
Gli script realizzati per l’esecuzione automatizzata del benchmark per Oracle e Neo4j
presentano una struttura simile. Possiamo distinguere 3 sezioni principali:
Il dataset per le sanzioni contiene al massimo 250000 record, quello dei giudici
100000 e quello delle aziende 200000.
Inizialmente erano stati creati dataset di maggiori dimensioni (fino al milione di record)
ma il processo di creazione delle relazioni tra i nodi in neo4j richiede un quantitativo
di risorse tale da generare l’arresto del container. Spesso dopo questi arresti anomali
il container non poteva più essere avviato e doveva essere sostituito. Con dimensioni
non troppo superiori ai 250000 record per il dataset delle sanzioni viene restituito il
seguente messaggio:
6
Krishnakumaran Sivakumaran - 468800
Oracle
Il setup e l’interazione con il container Oracle non è stata del tutto semplice, spesso a
causa di variabili di ambiente che dovevano essere necessariamente settate
dall’esterno. Sono state incontrate delle difficoltà, ad esempio, nella condivisione di
una cartella tra il filesystem locale dell’host e quello del container. A differenza di
Neo4j, è stato usato il comando docker cp per trasferire i dataset all’interno del
container. Completato il caricamento è possibile lanciare il tool per l'inserimento.
Esempio:
Vengono passati come argomenti di SQL*Loader non solo i file .csv ma anche i
“control file”, con estensione .ctl, che sono necessari per il caricamento tramite sqlldr.
Contengono infatti le istruzioni per il posizionamento delle informazioni nelle tabelle.
Esempio:
load data
infile 'ds1_aziende.csv' "str '\n'"
append
into table SYS.AZIENDE
fields terminated by ','
OPTIONALLY ENCLOSED BY '"' AND '"'
trailing nullcols
7
Krishnakumaran Sivakumaran - 468800
( ID_AZIENDA,
NOME CHAR(60),
SEDE CHAR(100),
DIRETTORE CHAR(30),
TELEFONO,
EMAIL CHAR(60),
NUMERO_DIPENDENTI,
BUDGET
)
Una volta completato il caricamento dei dati all’interno delle tabelle del database si
procede con la fase di esecuzione delle query. Queste vengono passate come
argomento del metodo execute di un oggetto della libreria cx_Oracle disponibile per
Python. Una limitazione di Oracle, se il DBMS è in esecuzione tramite container, non
permette di creare nuovi utenti per l'interazione con il database. Per la connessione al
database è stato utilizzato l'utente preesistente "SYS".
Per la misura del tempo di esecuzione delle query si è fatto uso della libreria time e
della sua funzione time() in maniera tale da salvare la durata dell’intervallo di tempo
necessario all’istruzione. Dato che il valore generato da time è espresso in secondi,
moltiplichiamo opportunamente per ottenere il valore in millisecondi.
prima = time()
cursore.execute(query)
dopo = time()
tempo_esecuzione = (dopo-prima)*1000
Una volta terminata l’esecuzione delle query si svuotano le tabelle e, prima di passare
eventualmente al dataset successivo, si procede alla cancellazione della cache del
database. Come altri DBMS, anche Oracle fa uso di meccanismi di caching per
migliorare le prestazioni.
8
Krishnakumaran Sivakumaran - 468800
Ai fini dell’analisi che si sta portando avanti è opportuno cancellare i dati presenti in
maniera tale da poter valutare meglio le prestazioni del sistema.
# svuoto la cache
cursore.execute("alter system flush buffer_cache")
cursore.execute("alter system flush shared_pool")
Query eseguite
# query 1
select sanzioni.id_sentenza from sanzioni,tribunali where
sanzioni.tribunale = tribunali.id_tribunale and tribunali.stato =
'Italy'
# query 2
SELECT tribunali.stato, COUNT(*) FROM sanzioni, parti_lese,
tribunali WHERE sanzioni.sanzione_econ > 80000 AND (
sanzioni.data_sent BETWEEN TO_DATE('22-05-20', 'DD/MM/YY') AND
TO_DATE('31-12-20', 'DD/MM/YY') )
AND sanzioni.cat_parte_lesa IN (SELECT
parti_lese.id_tipo_soggetto FROM parti_lese WHERE
parti_lese.descrizione = 'aziende')
AND tribunali.id_tribunale = sanzioni.tribunale
GROUP BY tribunali.stato
# query 3
SELECT * FROM aziende, sanzioni WHERE aziende.id_azienda IN (SELECT
aziende.id_azienda FROM aziende WHERE numero_dipendenti > 35000)
AND sanzioni.azienda_sanz = aziende.id_azienda AND (
sanzioni.cat_parte_lesa IN (SELECT parti_lese.id_tipo_soggetto
FROM parti_lese
WHERE parti_lese.descrizione = 'privati'))ORDER BY
sanzioni.data_sent DESC
# query 4
select aziende.id_azienda from aziende, sanzioni, parti_lese,
9
Krishnakumaran Sivakumaran - 468800
tribunali, metodi_frode
where sanzioni.azienda_sanz = aziende.id_azienda
and sanzioni.sanzione_econ >= 150000
and sanzioni.tribunale = tribunali.id_tribunale and
tribunali.stato like '% %'
and aziende.numero_dipendenti < 50000
and metodi_frode.metodo = 'phishing'
order by sanzioni.sanzione_econ desc
Neo4j
La struttura del codice realizzato è analoga allo script creato per gli esperimenti con
Oracle. In questo caso l’intero processo è più agevole in quanto il container risulta
essere già configurato per la maggior parte delle operazioni.
Il tool usato per il caricamento dei dati nel database, neo4j-admin, è anch’esso a riga
di comando e consente di poter inserire nella fase di caricamento delle informazioni
anche le label da associare a ciascun nodo. Il processo è in generale molto semplice
ma non veloce come SQL*Loader. L’opzione --force consente di poter forzare la
sovrascrittura delle informazioni già contenute nel database.
Di default i dati inseriti tramite neo4j-admin vengono salvati nei nodi come delle
stringhe. Possiamo specificare il tipo di dato desiderato per l'importazione all'interno
del file csv modificando l'header del file. Nel caso di Oracle il tipo di dato viene
specificato nel control file (file .ctl) che viene passato in input ad SQL*Loader.
10
Krishnakumaran Sivakumaran - 468800
KEY,NOME,SEDE,DIRETTORE,TELEFONO,EMAIL,NUMERO_DIPENDENTI,BUDGET
KEY,NOME,SEDE,DIRETTORE,TELEFONO,EMAIL,NUMERO_DIPENDENTI:int,BUDGET:
int
Il caricamento dei dati tramite il tool, per quanto vada a buon fine, in alcune
circostanze può non mostrare alcun effetto immediato. Ciò è più evidente se si fa uso
dell’applicativo Neo4j Desktop. La soluzione più efficace risulta quella di riavviare il
servizio del database, in questo caso fermare ed avviare nuovamente il container.
Nell’ambito di questi esperimenti, il container verrà riavviato più volte per consentire
di svuotare la cache che il sistema può avere generato per le stesse ragioni viste in
Oracle.
Dopo il riavvio si procede alla creazione delle relazioni, quindi degli archi, tra i vari
nodi creati a seguito dell’importazione.
L’esecuzione e la raccolta dei tempi delle query risulta, generalizzando, analoga per
quanto riguarda la strutturazione a quanto visto negli esperimenti di Oracle.
L'esecuzione delle query è realizzata tramite gli strumenti forniti dalla libreria ufficiale
di Neo4j per Python.
11
Krishnakumaran Sivakumaran - 468800
Query eseguite
# query 1
match (a:sanzioni)-[r:sede]->(b:tribunali {TRIBUNALE : "Italy"})
return a,b
# query 2
# query 3
# query 4
12
Krishnakumaran Sivakumaran - 468800
13
Krishnakumaran Sivakumaran - 468800
Query 1 - Neo4j
14
Krishnakumaran Sivakumaran - 468800
Query 2 - Oracle
15
Krishnakumaran Sivakumaran - 468800
Query 2 - Neo4j
16
Krishnakumaran Sivakumaran - 468800
Query 3 - Oracle
17
Krishnakumaran Sivakumaran - 468800
Query 3 - Neo4j
18
Krishnakumaran Sivakumaran - 468800
Query 4 - Oracle
19
Krishnakumaran Sivakumaran - 468800
Query 4 - Neo4j
20
Krishnakumaran Sivakumaran - 468800
GRAFICI
21
Krishnakumaran Sivakumaran - 468800
22
Krishnakumaran Sivakumaran - 468800
CONCLUSIONI
Da quanto risulta dagli esperimenti svolti, è possibile notare che, con datamodel di
questa tipologia, le prestazioni di Oracle risultano essere generalmente superiori,
specialmente considerando i tempi misurati per la query numero 3. Notevole risulta
essere il caso della quarta query dove possiamo notare che, nonostante i tempi per la
prima esecuzione (quindi successiva all'eliminazione della cache) siano minori per
Oracle, Neo4j riesce ad avere prestazioni in media superiori.
Osservando i grafici si può notare gli effetti del caching sui tempi di esecuzione delle
query, in particolare in Neo4j: per ciascun dataset, dopo aver svuotato le informazioni
salvate in memoria con i meccanismi appositi, è possibile notare come la prima
esecuzione, rappresentata come colonna a parte, richieda più tempo rispetto alle
esecuzioni successive (tranne in alcuni casi).
Nel corso degli esperimenti si è potuto osservare come il database Oracle sia più
"robusto" rispetto a Neo4j. Come accennato in precedenza, sono stati molteplici i casi
in cui, a causa di errori nella fase di caricamento dei dati o della creazione delle
relazioni, il database di Neo4j si è "corrotto" al punto tale da non consentire alcuna
interazione, giungendo in uno stato irrecuperabile. Nel caso di Oracle invece non si
sono verificati risultati paragonabili.
23