Globali — spade-macchine per la memorizzazione dei dati. Alberi. Parte 2

Globali — spade-macchine per la memorizzazione dei dati. Alberi. Parte 2Inizio — vedi parte 1.

3. Varianti di struttura nell'uso dei globali

Una struttura come l'albero ordinato ha diversi casi particolari. Esaminiamo quelli che hanno valore pratico nell'uso dei globali.

3.1 Caso particolare 1. Un nodo senza rami


Globali — spade-macchine per la memorizzazione dei dati. Alberi. Parte 2I globali possono essere utilizzati non solo come un array, ma anche come variabili normali. Per esempio come contatore:

Set ^counter = 0  ; impostazione del contatore
Set id=$Increment(^counter) ;  incremento atomico

Inoltre, il globale può avere rami, oltre al valore. L'uno non esclude l'altro.

3.2 Caso particolare 2. Un vertice e molti rami

In generale, è un classico database chiave-valore. E se salviamo una tupla come valore, otteniamo una semplice tabella con una chiave primaria.

Globali — spade-macchine per la memorizzazione dei dati. Alberi. Parte 2

Per realizzare una tabella sui globali, dobbiamo formare noi stessi le righe dai valori delle colonne e poi salvarle nel globale per chiave primaria. Per poter separare nuovamente la riga in colonne durante la lettura, possiamo utilizzare:

  1. simboli delimitatori.
    Set ^t(id1) = "col11/col21/col31"
    Set ^t(id2) = "col12/col22/col32"
  2. uno schema rigido, in cui ogni campo occupa un numero di byte predefinito. Come avviene nei database relazionali.
  3. una funzione speciale $LB (presente in Cache), che crea una riga dai valori.
    Set ^t(id1) = $LB("col11", "col21", "col31")
    Set ^t(id2) = $LB("col12", "col22", "col32")

È interessante notare che non è difficile creare nei globali qualcosa di simile agli indici secondari nei database relazionali. Chiamiamo queste strutture globali indice. Un globale indice è un albero ausiliario per la ricerca rapida nei campi che non sono parti costitutive della chiave primaria del globale principale. Per compilarlo e utilizzarlo è necessario scrivere codice aggiuntivo.

Creiamo un globale indice per la prima colonna.

Set ^i("col11", id1) = 1
Set ^i("col12", id2) = 1

Ora, per una ricerca rapida delle informazioni nella prima colonna, dobbiamo guardare nel globale ^i e trovare le chiavi primarie (id) corrispondenti al valore desiderato della prima colonna.

Quando inseriamo un valore, possiamo creare subito sia il valore che i globali indice per i campi necessari. Per sicurezza, racchiudiamo tutto questo in una transazione.

TSTART
Set ^t(id1) = $LB("col11", "col21", "col31")
Set ^i("col11", id1) = 1
TCOMMIT

Dettagli su come farlo su M tabelle sui globali, emulazione di indici secondari.

Tali tabelle funzioneranno altrettanto velocemente quanto nei database tradizionali (o anche più velocemente), se le funzioni di inserimento/aggiornamento/rimozione delle righe vengono scritte in COS/M e compilate.Ho verificato questa affermazione attraverso test di massicci INSERT e SELECT su una tabella a due colonne, inclusi i comandi TSTART e TCOMMIT (transazioni).

Non ho testato scenari più complessi con accesso concorrente e transazioni parallele.

Senza l'uso di transazioni, la velocità degli inserti era di 778.361 inserimenti al secondo su un milione di valori.
Con 300 milioni di valori — 422.141 inserimenti al secondo.

Utilizzando le transazioni — 572.082 inserimenti al secondo su 50 milioni di inserimenti. Tutte le operazioni sono state eseguite da codice M compilato.
I dischi rigidi sono normali, non SSD. RAID5 con Write-back. Processore Phenom II 1100T.

Per testare un database SQL simile, è necessario scrivere una stored procedure che esegua inserimenti in un ciclo. Durante il test con MySQL 5.5 (storage InnoDB), ho ottenuto cifre non superiori a 11.000 inserimenti al secondo.
Sì, l'implementazione di tabelle sui globali appare più complessa rispetto ai database relazionali. Perciò i database industriali sui globali hanno accesso SQL per semplificare il lavoro con i dati tabellari.

Globali — spade-macchine per la memorizzazione dei dati. Alberi. Parte 2In generale, se lo schema dei dati non cambierà frequentemente, la velocità di inserimento non è critica e l'intero database può essere facilmente rappresentato come tabelle normalizzate, è più semplice lavorare con SQL, poiché offre un livello di astrazione più elevato.

Globali — spade-macchine per la memorizzazione dei dati. Alberi. Parte 2In questo caso particolare volevo mostrare che i globali possono fungere da costruttore per creare altri database. Come un assemblatore, su cui è possibile scrivere altri linguaggi. Ecco alcuni esempi di come creare sui globali equivalenti a key-value, liste, insiemi, database tabellari, orientati ai documenti.

Se è necessario creare un database non standard con minimi sforzi, vale la pena dare un'occhiata ai globali.

3.3 Caso particolare 3. Albero a due livelli, con un numero fisso di rami in ogni nodo di secondo livello

Globali — spade-macchine per la memorizzazione dei dati. Alberi. Parte 2Probabilmente lo avete indovinato: questa è un'implementazione alternativa di tabelle sui globali. Confrontiamo questa implementazione con la precedente.

Tabelle su albero a due livelli vs. su albero a un livello.

Contro
Pro

  1. Più lento nell'inserimento, poiché è necessario impostare il numero di nodi uguale al numero di colonne.
  2. Maggiore utilizzo di spazio su disco. Poiché gli indici globali (intesi come indici degli array) con i nomi delle colonne occupano spazio su disco e vengono duplicati per ogni riga.

  1. Accesso più veloce ai valori delle singole colonne, poiché non è necessario analizzare la stringa. Nei miei test, è stato più veloce del 11,5% su 2 colonne e ancora di più con un numero maggiore di colonne.
  2. Più semplice modificare lo schema dei dati
  3. Codice più chiaro

Conclusione: è soggettivo. Poiché la velocità è uno dei principali vantaggi degli globali, non ha quasi senso utilizzare questa implementazione, poiché probabilmente non funzionerà più velocemente delle tabelle nei database relazionali.

3.4 Casi generali. Alberi e alberi ordinati

Qualsiasi struttura dati che può essere rappresentata come un albero si adatta perfettamente agli globali.

3.4.1 Oggetti con sottoggetti

Globali — spade-macchine per la memorizzazione dei dati. Alberi. Parte 2

Questa è l'area di applicazione tradizionale degli globali. Nel settore medico, ci sono un'enorme varietà di malattie, farmaci, sintomi e metodi di trattamento. Creare una tabella con un milione di campi per ogni paziente non è razionale. Soprattutto considerando che il 99% dei campi saranno vuoti.

Immagina un database SQL con le tabelle: "paziente" ~ 100.000 campi, "Farmaco" — 100.000 campi, "Terapia" — 100.000 campi, "Complicazioni" — 100.000 campi, ecc. oppure si possono creare database con migliaia di tabelle, ognuna per un certo tipo di paziente (e questi possono sovrapporsi!), trattamento, farmaco e altre migliaia di tabelle per i legami tra queste tabelle.

Gli globali sono perfetti per la medicina, in quanto consentono di creare una descrizione accurata della storia clinica di ogni paziente, delle varie terapie e delle azioni dei farmaci, sotto forma di albero, senza sprecare spazio su disco su colonne vuote, come sarebbe nel caso relazionale.

Globali — spade-macchine per la memorizzazione dei dati. Alberi. Parte 2È conveniente creare database sulle persone utilizzando gli globali, quando è importante accumulare e sistematizzare il massimo di informazioni varie sul cliente. Questo è richiesto nel settore medico, bancario, marketing, archiviazione e in altri ambiti.

.
Certamente, è possibile emulare un albero anche con poche tabelle in SQL (EAV, 1,2,3,4,5,6,7,8,9,10), tuttavia è notevolmente più complesso e funzionerà più lentamente. Di fatto, bisognerebbe scrivere un globale operante su tabelle e nascondere tutto il lavoro con le tabelle sotto un livello di astrazione. È sbagliato emulare una tecnologia a basso livello (globali) con strumenti di livello più alto (SQL). Non è pratico.

Non è un segreto che modificare lo schema dei dati su tabelle gigantesche (ALTER TABLE) possa richiedere un tempo considerevole. MySQL, ad esempio, esegue ALTER TABLE ADD|DROP COLUMN copiando completamente le informazioni dalla vecchia alla nuova tabella (ho testato i motori MyISAM, InnoDB). Questo può bloccare un database operativo con miliardi di record per giorni, se non settimane.

Globali — spade-macchine per la memorizzazione dei dati. Alberi. Parte 2Modificare la struttura dei dati, se utilizziamo globali, non ci costa nulla. In qualsiasi momento possiamo aggiungere qualsiasi nuova proprietà necessaria a qualsiasi oggetto, a qualsiasi livello di gerarchia. Le modifiche relative alla rinominazione dei rami possono essere eseguite in background su un database attivo.


Pertanto, quando si tratta di memorizzare oggetti con un'enorme quantità di proprietà facoltative, i globali sono un'ottima scelta.

Inoltre, ricordo che l'accesso a qualsiasi proprietà è istantaneo, poiché in un globale tutti i percorsi rappresentano un B-tree.

I database basati su globali, in generale, sono una forma di database orientati ai documenti, con la possibilità di memorizzare informazioni gerarchiche. Pertanto, nell'ambito della memorizzazione delle cartelle cliniche, i globali possono competere con i database orientati ai documenti. Ma non è proprio la stessa cosa.Prendiamo ad esempio MongoDB. In questo campo perde rispetto ai globali per i seguenti motivi:

  1. La dimensione del documento. L'unità di memorizzazione è un testo in formato JSON (più precisamente BSON) con una dimensione massima di circa 16 MB. Questa limitazione è stata creata appositamente per evitare che il database JSON rallenti durante l'analisi, se viene memorizzato un enorme documento JSON e successivamente si accede a esso per campi. In questo documento deve essere concentrata tutta l'informazione riguardante il paziente. Tutti noi sappiamo quanto possano essere ingombranti le cartelle cliniche. La dimensione massima della cartella di 16 MB esclude immediatamente i pazienti la cui cartella delle malattie include file di risonanza magnetica, scansioni radiografiche e altri esami. In un unico ramo di un globale, invece, è possibile avere informazioni in gigabyte e terabyte. In effetti, qui si potrebbe già concludere, ma continuerò.
  2. Tempo di consapevolezza/cambiamento/rimozione delle nuove proprietà nella mappa del paziente. Tale DB deve caricare in memoria l'intera mappa (un grande volume!), analizzare BSON, aggiungere/modificare/rimuovere un nuovo nodo, aggiornare gli indici, impacchettare in BSON e salvare su disco. Per il globale è sufficiente fare riferimento a una proprietà specifica e operare su di essa.
  3. Velocità di accesso a singole proprietà. Con molte proprietà nel documento e la sua struttura multilivello, l'accesso a singole proprietà sarà più veloce poiché ogni percorso nel globale è un B-tree. Con BSON, invece, sarà necessario analizzare linearmente il documento per trovare la proprietà desiderata.

3.3.2 Array associativi

Gli array associativi (anche con array annidati) si adattano perfettamente ai globali. Ad esempio, questo array da PHP verrà visualizzato nella prima immagine 3.3.1.

$a = array(
  "name" => "Vince Medvedev",
  "city" => "Mosca",
  "threatments" => array(
    "surgeries" => array("apedicectomy", "biopsy"),
    "radiation" => array("gamma", "x-rays"),
    "physiotherapy" => array("knee", "shoulder")
  )
);

3.3.3 Documenti gerarchici: XML, JSON

Si conservano facilmente nei globali. Per la memorizzazione, si possono organizzare in vari modi.

XML
Il modo più semplice per distribuire XML sui globali è quando nei nodi conserviamo gli attributi dei tag. E se sarà necessario un accesso rapido agli attributi dei tag, possiamo estrarli in rami separati.

Globali — spade-macchine per la memorizzazione dei dati. Alberi. Parte 2

<note id="5">
<to>Vasya</to>
<from>Sveta</from>
<heading>Promemoria</heading>
<body>Chiamami domani!</body>
</note>

In COS questo corrisponderà al codice:

Set ^xml("note")="id=5"
Set ^xml("note","to")="Sasha"
Set ^xml("note","from")="Sveta"
Set ^xml("note","heading")="Promemoria"
Set ^xml("note","body")="Chiamami domani!"

Nota: Per XML, JSON, array associativi si possono pensare a molti modi diversi per la visualizzazione sui globali. In questo caso non abbiamo riflesso l'ordine dei tag annidati nel tag note. Nel globale ^xml i tag annidati verranno visualizzati in ordine alfabetico. Per riflettere rigorosamente l'ordine, si può utilizzare, ad esempio, questa visualizzazione:

Globali — spade-macchine per la memorizzazione dei dati. Alberi. Parte 2
JSON.
Nella prima immagine della sezione 3.3.1 è mostrata la rappresentazione di questo documento JSON:

var document = {
  "name": "Vince Medvedev",
  "city": "Mosca",
  "threatments": {
    "surgeries": ["apedicectomy", "biopsy"],
    "radiation": ["gamma", "x-rays"],
    "physiotherapy": ["knee", "shoulder"]
  },
};

3.3.4 Strutture identiche legate da relazioni gerarchiche

Esempi: struttura degli uffici vendite, posizione delle persone nella struttura MLM, database delle aperture negli scacchi.

Database delle aperture. È possibile utilizzare la valutazione della forza del movimento come valore dell'indice del nodo globale. Quindi, per scegliere il movimento più forte, sarà sufficiente selezionare il ramo con il peso maggiore. Nel globale, tutti i rami a ciascun livello saranno ordinati in base alla forza del movimento.

Globali — spade-macchine per la memorizzazione dei dati. Alberi. Parte 2

Struttura degli uffici vendite, struttura delle persone nel MLM. Nei nodi è possibile memorizzare alcuni valori di cache che riflettono le caratteristiche dell'intero sottoalbero. Ad esempio, il volume delle vendite di questo sottoalbero. In qualsiasi momento possiamo ottenere un numero che riflette i risultati di qualsiasi ramo.

Globali — spade-macchine per la memorizzazione dei dati. Alberi. Parte 2

4. In quali casi è più vantaggioso utilizzare i globali

Nella prima colonna sono presentati i casi in cui si otterrà un notevole guadagno in velocità utilizzando i globali, e nella seconda quando si semplificherà lo sviluppo o il modello di dati.

Velocità
Comodità nella gestione/visualizzazione dei dati

  1. Inserimento [con ordinamento automatico a ciascun livello], [indicizzazione per chiave primario]
  2. Rimozione di sottoalberi
  3. Oggetti con un gran numero di proprietà annidate, a cui è necessario un accesso individuale
  4. Struttura gerarchica con possibilità di attraversamento dei rami figli da qualsiasi, anche inesistente
  5. Attraversamento dei sottoalberi in profondità
  1. Oggetti/entità con un'enorme quantità di proprietà/entità opzionali [e/o annidate]
  2. Dati senza schema (schema-less). Quando nuovi attributi possono spesso apparire e vecchi scomparire.
  3. È necessario creare un database non standard.
  4. Basi di percorsi e alberi decisionali. Quando i percorsi sono convenienti da rappresentare come un albero.
  5. Rimozione di strutture gerarchiche senza utilizzare la ricorsione

Continua «I globali sono spade di acciaio per la memorizzazione dei dati. Arrays sparsi. Parte 3».

Avviso: Questo articolo e i miei commenti sono la mia opinione e non riflettono la posizione ufficiale della società InterSystems.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster