Articles

Microsoft server ‘ s Graph – et forsøg, der faldt kort (for nu)

Posted by admin
TRAN Ngoc Thach
TRAN Ngoc Thach

Følg

Jun 29, 2020 * 9 min læst

ansvarsfraskrivelse: udtalelsen i denne artikel er min alene, baseret på min begrænsede eksponering for CVR-serverens graf. Jeg er på ingen måde en ekspert på Kbh Server. Jeg kan være forudindtaget mod Neo4j.

med den stigende brug af grafdatabase og neo4js dominans på dette nichemarked såvel som dets betydelige præstationsgevinst ved forespørgsel af stærkt forbundne data er det forståeligt, at Microsoft ikke ønsker at blive udeladt af denne megatrend.

fra og med server 2017 tilbød server Graph funktionaliteter med introduktionen af nøgleordetMATCH. I 2019-versionen blev der blandt andet tilføjet to nye bemærkelsesværdige funktioner: Kantbegrænsninger og brugen af afledte tabeller i MATCH forespørgsler. Dykning i denne teknologi længe nok, jeg har et indtryk af, at, fra nu af:

  • Neo4j.
  • tilføjelsen af funktionalitet er langsomt Inkremental.
  • Graffunktionen er modvilligt monteret i Relationsdatabasens tankegang.

lad os komme i detaljer!

fordele& ulemper

nøgleordet MATCH er efter min mening kun et Syntatisk sukker. I stedet for:

SELECT *
FROM NodeTable1 nt1 JOIN EdgeTable et ON nt1.$node_id = et.$from_id JOIN NodeTable2 nt2 ON nt2.$node_id = et.$to_id

… brugere kan stort set forkorte forespørgslen som:

SELECT *
FROM NodeTable1 nt1, EdgeTable et, NodeTable2 nt2
WHERE MATCH(nt1-(et)->nt2)

den forkortede forespørgsel er utvivlsomt behagelig for øjnene. I. net-verdenen kan Enhedsrammer dog foretrækkes til dataorienterede applikationer; som et resultat af hvilket der ikke er behov for almindelige tekstkommandoer. Udviklere lader bare rammen generere optimale forespørgsler til dem, mens de er fokuseret på abstraktioner på højt niveau. Ved denne logik er den behagelige effekt af MATCH pludselig irrelevant. Værre, i øjeblikket er der endda ingen køreplan til støtte for disse graffunktioner i enhedsramme (kerne).

sammenligning til Neo4j, ser igen på ovenstående forespørgsler, er det uundgåeligt for brugerne at bøje deres graf tankegang i relationel Database verden. Vi er stadig nødt til at erklære på forhånd, hvilke tabeller, i FROM klausul, for at udføre matchningen (skal det snarere være grafen, der betragtes som en ‘gennemgående helhed’, og man behøver ikke at bekymre sig om detaljeret dataorganisation?). Når man kender pilretningen i MATCH er et must, kommer brugerne til at indse 1-1-kortlægningen mellem MATCH – klausulen og den oprindelige JOIN – klausul i den forstand, at man skal skelne Kildeknudepunktet og Målknudepunktet. I modsætning hertil tillader Neo4js Cypher-syntaks at se bort fra denne sondring. Alle disse er ikke nødvendigvis en game-changer; men blot et spørgsmål om bekvemmelighed og glæde af udvikling. (Senere, i 1. Studiesag, ser vi, at vi skal gøre en UNION ALL på grund af dette.)

en nøgle til høj ydeevne af native Graph Database i gennemkører tilsluttede data er indeks-fri adjacency. Desværre er der ikke sådan noget med Graph-funktionen i:

vi opretholder ikke en adjacency-liste på hver node; i stedet lagrer vi edge-data i tabeller. Fordi det er en relationsdatabase, var lagring af data i form af tabeller et mere naturligt valg for os

et andet irriterende problem er manglen på visualiseringsværktøjer skræddersyet til Graf, for både skema og data. Som en løsning kan brugerne stadig oprette et Skemadiagram i SSMS, men disse noder og Kanttabeller ender som individuelle, frakoblede tabeller, selv hvis de har Kantbegrænsninger. Grafteknologi bør blandt andet også medføre visuelle appeller, hvilket gør det lettere for brugerne at konstruere korrekte forespørgsler. Manglende sådanne værktøjer er frustrerende og skadeligt for udviklernes produktivitet.

Diagram til Graftabeller

så hvad gør vi for at få Grafskemaet? Jeg antager, at vi åbner hver Kanttabel for manuelt at se begrænsningerne og derefter begrunde dem ved hjælp af et stykke papir for at finde ud af hele Grafskemaet.

Graph ‘ s Edge begrænsninger

med hensyn til datavisualisering forsøgte jeg Microsoft magt BI med Force-Directed Graph addon. Dette værktøj er dog ikke gratis, og det understøtter ikke serverens graffunktioner uden for boksen, hvilket betyder, at det ser noder og kanter tabeller som normale databasetabeller. Når man nøje undersøger kolonnelisterne, er der underlige kolonnenavne, f.eks. graph_id_...,from_obj_id.... Det er interne kolonner, der automatisk genereres, når du opretter Node/Edge tabeller, utilgængelige udefra. En fejl er rejst, som nedenfor, af magt BI ‘ s Get Data funktion, hvis adgang til disse kolonner.

strøm BI – “Hent Data” fra Graftabeller

for at løse dette problem skal man oprette en Databasevisning, der kun indeholder relevante/tilgængelige kolonner, f. eks. from_id og to_id i Edge Table, node_id i Node Table. Derefter i magt BI, udtrække dataene gennem denne visning. Forhåbentlig tager jeg ikke fejl, magt BI kraft rettet graf synes at kræve en enkelt tabel, som består af kolonner Source, Target, Weight, Source Type, Target Type, Link Type. Vores prøveskema er forenklet; således er det trivielt at oprette denne enkelt tabel. Hvad hvis skemaet indeholdt + 20 noder tabeller og + 10 kanter bord, kunne vi ende med en enkelt tabel for at visualisere hele grafen med magt BI?

# opdateret den 04.07.2020: Ved anden tanke er dette helt sikkert muligt, selvom det stadig er besværligt. Man skal starte ved Kanttabeller, hvor hver $from_id og $to_id er forbundet med relevante Nodetabeller for at oversætte til delte egenskaber for alle noder, f.eks. Name eller Id. Så gør UNION ALL for alle at kombinere i den endelige enkelt tabel kræves af magt BI.

forespørgsel til noder og kanter er en af mulighederne for Grafteknologi. Hvad der kan få en grafdatabase til at skille sig ud er den indbyggede, men udvidelige understøttelse af Grafalgoritmer, såsom PageRank og Louvain Community Detection (aka. Louvain modularitet). Desværre igen, ingen sådanne analytics funktionaliteter til rådighed i Server graf, som sagt:

nogle grafdatabaser giver dedikerede grafanalytiske funktioner som” korteste sti “eller” siderangering.” giver ikke sådanne funktioner i denne udgivelse. Igen kan t-SKL-sløjfer og temp-tabeller bruges til at skrive en løsning for disse scenarier.

i Neo4j er disse algoritmer let tilgængelige i produktionskvalitet takket være Graph Data Science Library. Plus, det er åbent. Generelt er dokumentation nyttig, men engang ikke tilstrækkelig. Med open source, udviklere kan hente og dykke ned i, hvordan en bestemt algoritme implementeres; eller endda kompilere biblioteket, med yderligere logning info, for yderligere at forstå. Implementering af PageRank er mulig, men mere kompleks algoritme som Louvain modularitet kan være udfordrende. Ikke desto mindre foretrækker mange programmelingeniører at være mere generet af forretningslogik i stedet for at blive kørt ned med tekniske detaljer på lavt niveau.

sidst men ikke mindst er almindelig Tabeludtryk efter min mening en slags afledte tabeller. Siden 2019 skal denne teknik officielt være brugbar med Graph:

fælles tabel udtryk (CTE) med Graf tabeller og MATCH klausul

men hvis følgende visning skabelse, det er do-stand:

se skabelse med Graf tabeller og MATCH klausul

jeg tror, det er et tegn på inkonsekvens. Den 2. tilgang kræver en permanent oprettet visning, da det ikke er muligt at oprette midlertidig visning i . Normalt overvinder brugerne dette med CTE, men igen fungerer CTE ikke med Graph, som vist ovenfor.

Studiesager

et eksempelscenarie: studerende og lærere.

Neo4j ‘ s Cypher:

CREATE (S1:NStudents {name: "S1"}), (S2:NStudents {name: "S2"}), (T1:NTeachers {name: "T1"}), (S3:NStudents {name: "S3"}), (T2:NTeachers {name: "T2"}), (S4:NStudents {name: "S4"}), (S1)-->(S2), (S2)-->(T1), (T1)-->(T2), (T2)-->(S4), (S3)-->(T1)

server 2019 ‘ s graf:

CREATE TABLE NStudents ( NVARCHAR(MAX) NOT NULL, INT NOT NULL) AS NODE;CREATE TABLE NTeachers ( NVARCHAR(MAX) NOT NULL, FLOAT NOT NULL) AS NODE;CREATE TABLE Talks (CONSTRAINT EC_Talk CONNECTION (NStudents TO NStudents, NStudents TO NTeachers, NTeachers TO NStudents, NTeachers TO NTeachers) ON DELETE CASCADE) AS EDGE;INSERT INTO NStudents VALUES ('S1',1),('S2',2),('S3',3),('S4',4);
INSERT INTO NTeachers VALUES ('T1',123), ('T2',456);
INSERT INTO Talks VALUES (
(SELECT $node_id FROM NStudents WHERE = 'S1'),
(SELECT $node_id FROM NStudents WHERE = 'S2'));
INSERT INTO Talks VALUES (
(SELECT $node_id FROM NStudents WHERE = 'S2'),
(SELECT $node_id FROM NTeachers WHERE = 'T1'));
INSERT INTO Talks VALUES (
(SELECT $node_id FROM NTeachers WHERE = 'T1'),
(SELECT $node_id FROM NTeachers WHERE = 'T2'));
INSERT INTO Talks VALUES (
(SELECT $node_id FROM NTeachers WHERE = 'T2'),
(SELECT $node_id FROM NStudents WHERE = 'S4'));
INSERT INTO Talks VALUES (
(SELECT $node_id FROM NStudents WHERE = 'S3'),
(SELECT $node_id FROM NTeachers WHERE = 'T1'));

sag 1: alle indgående og udgående forbindelser af noder

Motivation: at tælle disse forbindelser for hver node er en måde at finde ud af, hvilke der er vigtigst.

Neo4j ‘ scypher:

MATCH (n)--()
RETURN n.name, COUNT(r) AS allCons
ORDER BY allCons DESC

grafen for Server 2019:

--Create a View first, for convenience purpose.
CREATE VIEW view_AllPeople
AS
SELECT $node_id AS ,
FROM NStudents
UNION ALL
SELECT $node_id AS ,
FROM NTeachers;--Query using the View.
WITH CTE()
AS
(
SELECT ap1.
FROM view_AllPeople ap1, Talks t, view_AllPeople ap2
WHERE MATCH(ap1-(t)->ap2)
UNION ALL
SELECT ap1.
FROM view_AllPeople ap1, Talks t, view_AllPeople ap2
WHERE MATCH(ap1<-(t)-ap2)
)
SELECT , COUNT(*) AS allConns
FROM CTE
GROUP BY
ORDER BY allConns DESC

anmærkninger: Versionen er ikke kun længere, men også mere ubelejlig, da pilens retning i MATCH altid skal tages i betragtning.

sag 2: top længste stier

Motivation: lange afhængighedskæder er tilbøjelige til at være skrøbelige. For eksempel bibliotek afhængighed.

Neo4j ‘ scypher:

// The WHERE is to filter out duplicate paths, e.g. A->B = B->A.
MATCH p=(n)--(m)
WHERE ID(n) < ID(m)
RETURN n.name, m.name, length(p) AS len, AS node_list
ORDER BY len DESC

grafen for Server 2019:

WITH CTE(from_id, to_id, , )
AS
(
SELECT $from_id, $to_id, 1 AS , CONVERT(NVARCHAR(MAX), $to_id) AS
FROM Talks
UNION ALL
SELECT t.$from_id, t.$to_id, +1, CONVERT(NVARCHAR(MAX), CTE. + ',' + CONVERT(NVARCHAR(MAX), $to_id))
FROM Talks t JOIN CTE ON t.$to_id = CTE.
)
SELECT vap., ,
FROM CTE JOIN (SELECT MAX(c.) AS maxLevel FROM CTE c GROUP BY c.) myMax ON CTE. = myMax.maxLevel JOIN
view_AllPeople vap ON CTE. = vap.
ORDER BY DESC

anmærkninger: I server version, er man nødt til at benytte sig af rekursiv fælles tabel udtryk teknik. Det omfatter stort set relationel Database tankegang for at løse Grafproblemer.

konklusion

i Grafdomæne er en server ‘s kommando med graffunktion brugt eller ej, der bruges til at tackle Grafproblemer, typisk meget længere såvel som mere kompleks i sammenligning med Neo4j’ s Cypher. Dette fører til en implikation af, at koden vil være mere tidskrævende at udvikle og vanskelig at senere vedligeholde og udvide. En anden ingeniør eller endda den originale, der ser på det samme kodestykke en måned senere, vil finde det frustrerende at forstå alle dens aspekter. Et velkendt udtryk for at beskrive denne situation er teknisk gæld.

ved at kombinere alle de ovennævnte punkter, fra kodeaspekt, til funktionssupport, til værktøjs-/biblioteksøkosystem, mangler vi i øjeblikket Graph-funktionalitet, selvom det er opmuntrende, ikke forventningerne.

server er ekstremt moden med hensyn til relationsdatabase, men klart en nybegynder i grafdatabase. Denne Grafstøtte anses sandsynligvis for at være indeholdt i Relationsdatabasementalitet.

Related Post

Leave A Comment