Globaler är skattsvärd för att lagra data. Träd. Del 2

Globaler är skattsvärd för att lagra data. Träd. Del 2Komma igång - se del 1.

3. Varianter av strukturer vid användning av globaler

En struktur som ett ordnat träd har olika specialfall. Låt oss överväga de som har praktiskt värde när vi arbetar med globala.

3.1 Specialfall 1. En nod utan grenar


Globaler är skattsvärd för att lagra data. Träd. Del 2Globaler kan användas inte bara som en array, utan också som vanliga variabler. Till exempel, som en räknare:

Set ^counter = 0  ; установка счётчика
Set id=$Increment(^counter) ;  атомарное инкрементирование

I det här fallet kan det globala, förutom sin betydelse, också ha grenar. Det ena utesluter inte det andra.

3.2 Specialfall 2. En vertex och många grenar

I allmänhet är detta en klassisk nyckel-värdebas. Och om vi sparar en tuppel av värden som ett värde får vi en mycket vanlig tabell med en primärnyckel.

Globaler är skattsvärd för att lagra data. Träd. Del 2

För att implementera en tabell på globaler måste vi generera rader själva från kolumnvärdena och sedan spara dem till den globala med hjälp av primärnyckeln. För att göra det möjligt att dela upp strängen i kolumner igen vid läsning kan du använda:

  1. avgränsningstecken.
    Set ^t(id1) = "col11/col21/col31"
    Set ^t(id2) = "col12/col22/col32"
  2. ett stelt schema där varje fält upptar ett förutbestämt antal byte. Som man gör i relationsdatabaser.
  3. en speciell funktion $LB (tillgänglig i Cache), som skapar en sträng av värden.
    Set ^t(id1) = $LB("col11", "col21", "col31")
    Set ^t(id2) = $LB("col12", "col22", "col32")

Intressant nog är det inte svårt att använda globaler för att göra något som liknar sekundära index i relationsdatabaser. Låt oss kalla sådana strukturer för index globaler. En indexglobal är ett hjälpträd för att snabbt söka efter fält som inte är en del av primärnyckeln för huvudglobalen. För att fylla i och använda den måste du skriva ytterligare kod.

Låt oss skapa ett globalt index i den första kolumnen.

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

Nu, för att snabbt söka efter information i den första kolumnen, måste vi titta in i det globala ^i och hitta primärnycklarna (id) som motsvarar det önskade värdet i den första kolumnen.

När vi infogar ett värde kan vi omedelbart skapa både värde- och indexglobalerna för de obligatoriska fälten. Och för pålitlighetens skull, låt oss slå in allt i en transaktion.

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

Detaljer om hur du gör det på M tabeller över globaler, emulering av sekundära index.

Sådana tabeller kommer att fungera lika snabbt som i traditionella databaser (eller ännu snabbare) om funktionerna för att infoga/uppdatera/ta bort rader skrivs i COS/M och kompileras.Jag kontrollerade detta uttalande med tester på bulk INSERT och SELECT i en tabell med två kolumner, inklusive att använda TSTART- och TCOMMIT-kommandona (transaktioner).

Jag har inte testat mer komplexa scenarier med samtidig åtkomst och parallella transaktioner.

Utan att använda transaktioner var insättningshastigheten 778 361 insättningar/sekund per miljon värden.
Med 300 miljoner värden - 422 141 inlägg/sekund.

Vid användning av transaktioner - 572 082 inlägg/sekund för 50 miljoner inlägg. Alla operationer utfördes från kompilerad M-kod.
Hårddiskar är vanliga, inte SSD. RAID5 med återskrivning. Phenom II 1100T-processor.

För att testa en SQL-databas på liknande sätt måste du skriva en lagrad procedur som kommer att utföra infogning i en loop. När jag testade MySQL 5.5 (InnoDB-lagring) fick jag med den här metoden siffror som inte var mer än 11K insättningar per sekund.
Ja, implementeringen av tabeller på globaler ser mer komplex ut än i relationsdatabaser. Därför har industriella databaser på globaler SQL-åtkomst för att förenkla arbetet med tabelldata.

Globaler är skattsvärd för att lagra data. Träd. Del 2I allmänhet, om dataschemat inte kommer att ändras ofta, insättningshastigheten är inte kritisk och hela databasen kan enkelt representeras i form av normaliserade tabeller, då är det lättare att arbeta med SQL, eftersom det ger en högre abstraktionsnivå .

Globaler är skattsvärd för att lagra data. Träd. Del 2I det här fallet ville jag visa det globals kan fungera som en konstruktor för att skapa andra databaser. Som en assembler där andra språk kan skrivas. Här är exempel på hur du kan skapa analoger på globaler nyckel-värde, listor, uppsättningar, tabellformade, dokumentorienterade databaser.

Om du behöver skapa någon form av icke-standardiserad databas med minimal ansträngning, bör du se till globala.

3.3 Specialfall 3. Tvånivåträd, varje nod på den andra nivån har ett fast antal grenar

Globaler är skattsvärd för att lagra data. Träd. Del 2Du har säkert gissat rätt: detta är en alternativ implementering av tabeller på globala. Låt oss jämföra denna implementering med den föregående.

Tabeller på ett tvånivåträd vs. på ett enplansträd.

Nackdelar
Fördelar

  1. Långsammare för insättning, eftersom du måste ställa in antalet noder lika med antalet kolumner.
  2. Mer diskutrymmesförbrukning. Eftersom globala index (förstås som arrayindex) med kolumnnamn tar upp diskutrymme och dupliceras för varje rad.

  1. Snabbare åtkomst till värdena för enskilda kolumner, eftersom det inte finns något behov av att analysera strängen. Enligt mina tester är det 11,5% snabbare på 2 kolumner och mer på ett större antal kolumner.
  2. Lättare att ändra dataschema
  3. Tydligare kod

Slutsats: inte för alla. Eftersom hastighet är en av de viktigaste fördelarna med globala, är det ingen mening med att använda denna implementering, eftersom den med största sannolikhet inte kommer att fungera snabbare än tabeller i relationsdatabaser.

3.4 Allmänt fall. Träd och beställda träd

Alla datastrukturer som kan representeras som ett träd passar perfekt med globaler.

3.4.1 Objekt med delobjekt

Globaler är skattsvärd för att lagra data. Träd. Del 2

Detta är området för traditionell användning av globaler. Inom det medicinska området finns det ett stort antal sjukdomar, mediciner, symtom och behandlingsmetoder. Det är irrationellt att skapa en tabell med en miljon fält för varje patient. Dessutom kommer 99% av fälten att vara tomma.

Föreställ dig en SQL-databas med tabeller: "patient" ~ 100 000 fält, "Medicin" - 100 000 fält, "Terapi" - 100 000 fält, "Komplikationer" - 100 000 fält, etc. och så vidare. Eller så kan du skapa en databas med många tusen tabeller, var och en för en specifik typ av patient (och de kan överlappa!), behandlingar, mediciner och tusentals fler tabeller för kopplingar mellan dessa tabeller.

Globaler är idealiska för medicin, eftersom de låter dig skapa för varje patient en korrekt beskrivning av hans sjukdomshistoria, olika terapier och medicinernas handlingar, i form av ett träd, utan att slösa extra diskutrymme på tomma kolumner, som skulle vara fallet i ett relationsfall.

Globaler är skattsvärd för att lagra data. Träd. Del 2Med hjälp av globals är det bekvämt att skapa en databas med data om människor, när det är viktigt att ackumulera och systematisera maximalt med olika uppgifter om klienten. Detta efterfrågas inom medicin, bank, marknadsföring, arkivering och andra områden

.
Naturligtvis, i SQL kan du också emulera ett träd med bara några tabeller (EAV-förlängning, 1,2,3,4,5,6,7,8,9,10), men detta är betydligt mer komplicerat och kommer att gå långsammare. I huvudsak skulle du behöva skriva en global som fungerar på tabeller och dölja allt arbete med tabeller under ett abstraktionslager. Det är fel att emulera teknik på lägre nivå (globals) med hjälp av högre nivåteknik (SQL). Olämplig.

Det är ingen hemlighet att det kan ta ganska lång tid att ändra dataschemat på jättetabeller (ALTER TABLE). MySQL, till exempel, gör ALTER TABLE ADD|DROP COLUMN genom att helt kopiera information från den gamla tabellen till den nya tabellen (testade MyISAM, InnoDB-motorer). Som kan hänga upp en fungerande databas med miljarder poster i dagar, om inte veckor.

Globaler är skattsvärd för att lagra data. Träd. Del 2Att ändra datastrukturen om vi använder globaler kostar oss ingenting. Vi kan när som helst lägga till alla nya egenskaper vi behöver till alla objekt, på vilken nivå som helst i hierarkin. Ändringar associerade med att byta namn på grenar kan köras i bakgrunden på en databas som körs.


Därför, när det gäller att lagra objekt med ett stort antal valfria egenskaper, är globaler ett utmärkt val.

Låt mig dessutom påminna dig om att tillgången till någon av fastigheterna är omedelbar, eftersom alla vägar i det globala är B-träd.

Globala databaser är i allmänhet en typ av dokumentorienterad databas med förmågan att lagra hierarkisk information. Därför kan dokumentorienterade databaser konkurrera med globala när det gäller lagring av journaler. Men det är fortfarande inte riktigt detsammaLåt oss ta MongoDB för jämförelse. I den här domänen det förlorar mot globalerna av följande skäl:

  1. Dokumentstorlek. Lagringsenheten är text i JSON-format (närmare bestämt BSON) med en maximal volym på cirka 16MB. Begränsningen gjordes specifikt så att JSON-databasen inte saktar ner under analys om ett enormt JSON-dokument lagras i den och sedan nås av fält. Detta dokument bör innehålla all information om patienten. Vi vet alla hur tjocka patientjournaler kan vara. Den maximala kortstorleken på 16 MB sätter omedelbart stopp för patienter vars sjukdomskort innehåller MRT-filer, röntgenbilder och andra studier. I en gren av världen kan du ha gigabyte och terabyte med information. I princip kan vi sätta stopp för detta, men jag fortsätter.
  2. Tidpunkt för medvetande/ändring/borttagning av nya egenskaper i patientens diagram. En sådan databas måste läsa in hela kartan i minnet (det här är en stor mängd!), analysera BSON, lägga till/ändra/ta bort en ny nod, uppdatera index, packa den i BSON och spara den på disk. En global behöver bara komma åt en specifik egenskap och manipulera den.
  3. Snabb tillgång till enskilda fastigheter. Med många egenskaper i ett dokument och dess struktur på flera nivåer, blir åtkomsten till enskilda egenskaper snabbare på grund av att varje sökväg i globalen är ett B-träd. I BSON måste du linjärt analysera dokumentet för att hitta den önskade egenskapen.

3.3.2 Associativa arrayer

Associativa arrayer (även med kapslade arrayer) passar perfekt på globaler. Till exempel kommer en sådan array från PHP att visas i den första bilden 3.3.1.

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

3.3.3 Hierarkiska dokument: XML, JSON

Också lätt att lagra i globals. Kan läggas ut på olika sätt för förvaring.

XML
Det enklaste sättet att dekomponera XML till globala filer är att lagra taggattribut i noder. Och om snabb åtkomst till taggattribut behövs kan vi flytta dem till separata grenar.

Globaler är skattsvärd för att lagra data. Träd. Del 2

<note id=5>
<to>Вася</to>
<from>Света</from>
<heading>Напоминание</heading>
<body>Позвони мне завтра!</body>
</note>

På COS skulle detta motsvara koden:

Set ^xml("note")="id=5"
Set ^xml("note","to")="Саша"
Set ^xml("note","from")="Света"
Set ^xml("note","heading")="Напоминание"
Set ^xml("note","body")="Позвони мне завтра!"

anmärkning: För XML, JSON, associativa arrayer kan du komma på många olika sätt att visa på globala. I det här fallet återspeglade vi inte ordningen på undertaggarna i anteckningstaggen. Globalt ^xml undertaggar kommer att visas i alfabetisk ordning. För att strikt återspegla beställningen kan du till exempel använda följande display:

Globaler är skattsvärd för att lagra data. Träd. Del 2
JSON.
Den första bilden från avsnitt 3.3.1 visar en återspegling av detta JSON-dokument:

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

3.3.4 Identiska strukturer kopplade av hierarkiska relationer

Exempel: försäljningskontorens struktur, var personerna befinner sig i en MLM-struktur, databasen över öppningar i schack.

Debuterar databas. Du kan använda uppskattningen av slagkraften som indexvärdet för den globala noden. Sedan, för att välja det starkaste draget, räcker det med att välja den gren med störst vikt. I den globala kommer alla grenar på varje nivå att sorteras efter rörelsestyrka.

Globaler är skattsvärd för att lagra data. Träd. Del 2

Strukturen för försäljningskontor, strukturen för människor i MLM. Noder kan lagra vissa cachingvärden som återspeglar egenskaperna hos hela underträdet. Till exempel försäljningsvolymen för ett givet underträd. När som helst kan vi få en siffra som återspeglar prestationerna för vilken gren som helst.

Globaler är skattsvärd för att lagra data. Träd. Del 2

4. I vilka fall är det mest fördelaktigt att använda globala?

Den första kolumnen presenterar fall där du kommer att få en betydande hastighetsökning genom att använda globaler, och den andra när designen eller datamodellen kommer att förenklas.

Скорость
Enkel databehandling/presentation

  1. Infogning [med automatisk sortering på varje nivå], [indexering med huvudnyckel]
  2. Ta bort underträd
  3. Objekt med många kapslade egenskaper som kräver individuell åtkomst
  4. Hierarkisk struktur med möjlighet att kringgå underordnade grenar från vilken gren som helst, även obefintlig
  5. Djup-första genomgång av underträd
  1. Objekt/entiteter med ett stort antal valfria [och/eller kapslade] egenskaper/entiteter
  2. Schemafri data. När nya fastigheter ofta kan dyka upp och gamla försvinner.
  3. Du måste skapa en anpassad databas.
  4. Stigbaser och beslutsträd. När det är lämpligt att representera stigar som ett träd.
  5. Ta bort hierarkiska strukturer utan att använda rekursion

Förlängning "Globals är skattsvärd för att lagra data. Glesa arrayer. del 3".

Villkor: Den här artikeln och mina kommentarer till den är min åsikt och har inget samband med InterSystems Corporations officiella position.

Källa: will.com

Lägg en kommentar