Wann kann ich JSON- oder XML-Daten in einer SQL-Tabelle speichern?

70

Bei Verwendung von SQLoder MySQL(oder einer anderen relationalen Datenbank) - Ich verstehe, dass das Speichern der Daten in regulären Spalten für die Indizierung und andere Zwecke besser ist ...

Das Laden und Speichern von JSONDaten ist manchmal viel einfacher - und erleichtert die Entwicklung.

Gibt es "goldene Regeln" zum Speichern von Rohdaten JSONin der DB?

Ist es absolut eine schlechte Praxis, dies zu tun?

animuson
quelle
2
Ich würde mir vorstellen, dass das Abfragen bestimmter Eigenschaften innerhalb des JSON selbst zu Engpässen führen könnte. Wenn im JSON bestimmte Felder für die Abfrage erforderlich sind, sind sie möglicherweise Kandidaten für die Extraktion in eine eigene Spalte. Einige DBs haben sogar "json" -Datentypen, obwohl ich nicht weiß, welche Art von Optimierungen mit diesem Typ durchgeführt werden.
Kritner
Vielen Dank, dass Sie diese Frage gestellt haben. Sie haben mir viel Ärger erspart, da es für mich schwierig ist, von NoSQL zu SQL-DBs zu wechseln.
Mr.L

Antworten:

90

Die Hauptfragen sind

  • Was machen Sie mit diesen Daten? und
  • Wie filtern / sortieren / verbinden / bearbeiten Sie diese Daten?

JSON (wie XML) eignet sich hervorragend für den Datenaustausch, kleinen Speicher und allgemein definierte Strukturen, kann jedoch nicht an typischen Aktionen teilnehmen, die Sie in Ihrem RDBMS ausführen. In den meisten Fällen ist es besser, Ihre JSON-Daten in normale Tabellen zu übertragen und den JSON bei Bedarf neu zu erstellen.

XML / JSON und 1.NF

Die erste Regel der Normalisierung schreibt vor, niemals mehr als ein Informationsbit in einer Spalte zu speichern. Sie sehen eine Spalte "PersonName" mit einem Wert wie "Mickey Mouse"? Sie zeigen darauf und rufen: Ändern Sie das sofort!

Was ist mit XML oder JSON? Brechen diese Typen 1.NF? Nun ja und nein ... 

Es ist vollkommen in Ordnung, eine vollständige Struktur als ein Informationsbit zu speichern, wenn es sich tatsächlich um ein Informationsbit handelt . Sie erhalten eine SOAP-Antwort und möchten diese speichern, da Sie diese möglicherweise zum späteren Nachschlagen benötigen (Sie werden diese Daten jedoch nicht für Ihre eigenen Prozesse verwenden ). Bewahren Sie es einfach so auf, wie es ist !

Stellen Sie sich nun eine komplexe Struktur (XML oder JSON) vor, die eine Person darstellt (mit ihrer Adresse, weiteren Details ...). Jetzt setzen Sie dies in eine Spalte alsPersonInCharge . Ist das falsch? Sollte dies nicht eher in ordnungsgemäß gestalteten verwandten Tabellen mit einer Fremdschlüsselreferenz anstelle von XML / JSON erfolgen? Insbesondere wenn dieselbe Person in vielen verschiedenen Zeilen vorkommt, ist es definitiv falsch, einen XML / JSON-Ansatz zu verwenden.

Stellen Sie sich nun die Notwendigkeit vor, historische Daten zu speichern. Sie wollen beharren die Person , die Daten für einen bestimmten Zeitpunkt. Einige Tage später teilt Ihnen die Person eine neue Adresse mit? Kein Problem! Die alte Adresse befindet sich in einem XML / JSON, falls Sie sie jemals benötigen ...

Fazit: Wenn Sie die Daten nur speichern, um sie zu behalten, ist das in Ordnung. Wenn diese Daten ein eindeutiger Teil sind, ist es in Ordnung ...
Aber wenn Sie die internen Teile regelmäßig benötigen oder wenn dies redundanten doppelten Speicher bedeuten würde, ist es nicht in Ordnung ...

Physische Speicherung

Das Folgende gilt für SQL Server und kann bei anderen RDBMs unterschiedlich sein.

XML wird nicht als angezeigter Text gespeichert, sondern als Hierarchiebaum. Dies abzufragen ist erstaunlich gut! Diese Struktur wird nicht auf String-Ebene analysiert!
JSON in SQL Server (2016+) lebt in einer Zeichenfolge und muss analysiert werden. Es gibt keinen echten nativen JSON-Typ (wie es einen nativen XML-Typ gibt). Dies könnte später kommen, aber im Moment würde ich davon ausgehen, dass JSON unter SQL Server nicht so leistungsfähig ist wie XML (siehe Abschnitt UPDATE 2 ). Jede Notwendigkeit, einen Wert aus JSON zu lesen, erfordert eine Menge versteckter String-Methodenaufrufe ...

Was bedeutet das für dich?

Ihr liebenswerter DB-Künstler :-D weiß, dass das Speichern von JSON so wie es ist gegen die allgemeinen Prinzipien von RDBMs verstößt. Er weiß,

  • dass ein JSON höchstwahrscheinlich 1.NF bricht
  • dass sich ein JSON mit der Zeit ändern könnte (gleiche Spalte, unterschiedlicher Inhalt).
  • dass ein JSON nicht einfach zu lesen ist und es sehr schwer ist, danach zu filtern / suchen / verbinden oder zu sortieren.
  • dass solche Operationen eine gewisse zusätzliche Last auf den armen kleinen DB-Server verlagern

Es gibt einige Problemumgehungen (abhängig vom verwendeten RDBMS), aber die meisten funktionieren nicht so, wie Sie es möchten ...

Die Antwort auf Ihre Frage kurz

JA

  • Wenn Sie keine Daten verwenden möchten, die in Ihrem JSON für teure Vorgänge gespeichert sind (Filtern / Verknüpfen / Sortieren).
    Sie können dies so speichern, wie jeder andere nur vorhandene Inhalt. Wir speichern viele Bilder als BLOBs, aber wir würden nicht versuchen, nach allen Bildern mit einer Blume zu filtern ...
  • Wenn Sie sich überhaupt nicht darum kümmern, was sich darin befindet (speichern Sie es einfach und lesen Sie es als eine Information)
  • Wenn die Strukturen variabel sind, würde es schwieriger sein, physische Tabellen zu erstellen, als mit JSON-Daten zu arbeiten.
  • Wenn die Struktur tief verschachtelt ist, ist der Speicher in physischen Tabellen zu viel Aufwand

NEIN

  • Wenn Sie die internen Daten wie die Daten einer relationalen Tabelle verwenden möchten (Filter, Indizes, Verknüpfungen ...)
  • Wenn Sie Duplikate speichern würden (Redundanz erstellen)
  • Im Allgemeinen: Wenn Sie auf Leistungsprobleme stoßen (sicher werden Sie in vielen typischen Szenarien auftreten!)

Sie können mit dem JSON in einer Zeichenfolgenspalte oder als BLOB beginnen und dies bei Bedarf in physische Tabellen ändern. Meine magische Kristallkugel sagt mir, das könnte morgen sein :-D

AKTUALISIEREN

Einige Ideen zur Leistung und zum Speicherplatz finden Sie hier: https://stackoverflow.com/a/47408528/5089204

UPDATE 2: Mehr zur Leistung ...

Im Folgenden wird die JSON- und XML-Unterstützung in SQL Server 2016 behandelt

User @ mike123 verwies auf einen Artikel in einem offiziellen Microsoft-Blog, der in einem Experiment zu beweisen scheint, dass das Abfragen eines JSON 10-mal schneller ist als das Abfragen eines XML in SQL-Server.

Einige Gedanken dazu:

Einige Gegenprüfungen mit dem "Experiment":

  • Das "Experiment" misst viel, aber nicht die Leistung von XML im Vergleich zu JSON . Es ist kein realistisches Szenario, dieselbe Aktion gegen dieselbe (unveränderte) Zeichenfolge wiederholt auszuführen
  • Die getesteten Beispiele sind für eine allgemeine Aussage viel zu einfach !
  • Der gelesene Wert ist immer der gleiche und wird nicht einmal verwendet. Der Optimierer wird dies sehen ...
  • Kein einziges Wort über die mächtige XQueryUnterstützung! Suchen Sie ein Produkt mit einer bestimmten ID in einem Array? JSON muss das gesamte Los lesen und anschließend einen Filter verwenden WHERE, während XMLein interner zulässig ist XQuery predicate. Nicht zu sprechenFLWOR ...
  • Der Code "Experimente", wie er auf meinem System vorhanden ist, zeigt Folgendes an: JSON scheint 3x schneller zu sein (aber nicht 10x).
  • Durch Hinzufügen /text()zu XPathwird dies auf weniger als 2x reduziert . In dem verwandten Artikel hat Benutzer "Mister Magoo" bereits darauf hingewiesen, aber der Titel des Klick-Köders bleibt unverändert ...
  • Mit einem so einfachen JSON wie im "Experiment" angegeben war der schnellste reine T-SQL-Ansatz eine Kombination aus SUBSTRINGund CHARINDEX:-D

Der folgende Code zeigt ein realistischeres Experiment

  • Verwenden eines JSON und eines identischen XML mit mehr als einem Product(JSON-Array vs. Geschwisterknoten)
  • JSON und XML ändern sich geringfügig (10000 laufende Nummern) und werden in Tabellen eingefügt.
  • Es gibt einen ersten Anruf gegen beide Tabellen, um eine Verzerrung beim ersten Anruf zu vermeiden
  • Alle 10000 Einträge werden gelesen und die abgerufenen Werte in eine andere Tabelle eingefügt.
  • Mit GO 10wird dieser Block zehnmal durchlaufen, um eine Verzerrung beim ersten Anruf zu vermeiden

Das Endergebnis zeigt deutlich, dass JSON langsamer als XML ist (nicht so viel, etwa 1,5x in einem noch sehr einfachen Beispiel).

Die abschließende Aussage:

  • Mit einem übermäßig vereinfachten Beispiel kann JSON unter unangemessenen Umständen schneller als XML sein
  • Der Umgang mit JSON ist reine String-Aktion , während XML analysiert und transformiert wird. Dies ist in der ersten Aktion ziemlich teuer, beschleunigt aber alles, sobald dies erledigt ist.
  • JSON ist in einer einmaligen Aktion möglicherweise besser (vermeidet den Aufwand beim Erstellen einer internen hierarchischen Darstellung eines XML).
  • Mit einem immer noch sehr einfachen, aber realistischeren Beispiel wird XML beim einfachen Lesen schneller
  • Immer wenn ein bestimmtes Element aus einem Array gelesen werden muss, um alle Einträge zu filtern, in denen eine bestimmte ProductID im Array enthalten ist, oder um auf dem Pfad auf und ab zu navigieren, kann JSON nicht halten. Es muss vollständig aus einer Zeichenfolge heraus analysiert werden - jedes Mal, wenn Sie sich daran festhalten müssen ...

Der Testcode

USE master;
GO
--create a clean database
CREATE DATABASE TestJsonXml;
GO
USE TestJsonXml;
GO
--create tables
CREATE TABLE TestTbl1(ID INT IDENTITY,SomeXml XML);
CREATE TABLE TestTbl2(ID INT IDENTITY,SomeJson NVARCHAR(MAX));
CREATE TABLE Target1(SomeString NVARCHAR(MAX));
CREATE TABLE Target2(SomeString NVARCHAR(MAX));
CREATE TABLE Times(Test VARCHAR(10),Diff INT)
GO
--insert 10000 XMLs into TestTbl1
WITH Tally AS(SELECT TOP 10000 ROW_NUMBER() OVER(ORDER BY (SELECT NULL))*2 AS Nmbr FROM master..spt_values AS v1 CROSS APPLY master..spt_values AS v2)
INSERT INTO TestTbl1(SomeXml)
SELECT 
N'<Root>
    <Products>
    <ProductDescription>
        <Features>
            <Maintenance>' + CAST(Nmbr AS NVARCHAR(10)) + ' year parts and labor extended maintenance is available</Maintenance>
            <Warranty>1 year parts and labor</Warranty>
        </Features>
        <ProductID>' + CAST(Nmbr AS NVARCHAR(10)) + '</ProductID>
        <ProductName>Road Bike</ProductName>
    </ProductDescription>
    <ProductDescription>
        <Features>
            <Maintenance>' + CAST(Nmbr + 1 AS NVARCHAR(10)) + ' blah</Maintenance>
            <Warranty>1 year parts and labor</Warranty>
        </Features>
        <ProductID>' + CAST(Nmbr + 1 AS NVARCHAR(10)) + '</ProductID>
        <ProductName>Cross Bike</ProductName>
    </ProductDescription>
    </Products>
</Root>'
FROM Tally;

--insert 10000 JSONs into TestTbl2
WITH Tally AS(SELECT TOP 10000 ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nmbr FROM master..spt_values AS v1 CROSS APPLY master..spt_values AS v2)
INSERT INTO TestTbl2(SomeJson)
SELECT 
N'{
    "Root": {
        "Products": {
            "ProductDescription": [
                {
                    "Features": {
                        "Maintenance": "' + CAST(Nmbr AS NVARCHAR(10)) + ' year parts and labor extended maintenance is available",
                        "Warranty": "1 year parts and labor"
                    },
                    "ProductID": "' + CAST(Nmbr AS NVARCHAR(10)) + '",
                    "ProductName": "Road Bike"
                },
                {
                    "Features": {
                        "Maintenance": "' + CAST(Nmbr + 1 AS NVARCHAR(10)) + ' blah",
                        "Warranty": "1 year parts and labor"
                    },
                    "ProductID": "' + CAST(Nmbr + 1 AS NVARCHAR(10)) + '",
                    "ProductName": "Cross Bike"
                }
            ]
        }
    }
}'
FROM Tally;
GO

--Do some initial action to avoid first-call-bias
INSERT INTO Target1(SomeString)
SELECT SomeXml.value('(/Root/Products/ProductDescription/Features/Maintenance/text())[1]', 'nvarchar(4000)')
FROM TestTbl1;
INSERT INTO Target2(SomeString)
SELECT JSON_VALUE(SomeJson, N'$.Root.Products.ProductDescription[0].Features.Maintenance')
FROM TestTbl2;
GO

--Start the test
DECLARE @StartDt DATETIME2(7), @EndXml DATETIME2(7), @EndJson DATETIME2(7);

--Read all ProductNames of the second product and insert them to Target1
SET @StartDt = SYSDATETIME();
INSERT INTO Target1(SomeString)
SELECT SomeXml.value('(/Root/Products/ProductDescription/ProductName/text())[2]', 'nvarchar(4000)')
FROM TestTbl1
ORDER BY NEWID();
--remember the time spent
INSERT INTO Times(Test,Diff)
SELECT 'xml',DATEDIFF(millisecond,@StartDt,SYSDATETIME());

--Same with JSON into Target2
SET @StartDt = SYSDATETIME();
INSERT INTO Target2(SomeString)
SELECT JSON_VALUE(SomeJson, N'$.Root.Products.ProductDescription[1].ProductName')
FROM TestTbl2
ORDER BY NEWID();
--remember the time spent
INSERT INTO Times(Test,Diff)
SELECT 'json',DATEDIFF(millisecond,@StartDt,SYSDATETIME());

GO 10 --do the block above 10 times

--Show the result
SELECT Test,SUM(Diff) AS SumTime, COUNT(Diff) AS CountTime
FROM Times
GROUP BY Test;
GO
--clean up
USE master;
GO
DROP DATABASE TestJsonXml;
GO

Das Ergebnis (SQL Server 2016 Express auf einem Acer Aspire v17 Nitro Intel i7, 8 GB RAM)

Test    SumTime 
------------------
json    2706    
xml     1604    
Shnugo
quelle
Dieser Artikel schlägt vor, dass json x10 besser als xml blogs.msdn.microsoft.com/sqlserverstorageengine/2017/11/13/…
mike123
Könnten Sie in DATEDIFF Nanosekunden anstelle von Millisekunden eingeben?
Jovan MSFT
@JovanMSFT Sicher: json: 2281502100 und xml: 1296990300. Das bedeutet, dass XML fast doppelt so schnell ist ...
Shnugo
Welche Version verwenden Sie 2016, 2017? Auf SQL 2017 Express bekomme ich enge Zahlen: json 1918864000 xml 1807237200
Jovan MSFT
@JovanMSFT Wie oben beschrieben, habe ich dafür SQL Server 2016 Express verwendet. Ich habe dies gerade mit 10 Einträgen pro Array / Geschwisterknoten wiederholt und das 9. Element abgerufen. Xml war mehr als doppelt so schnell. Jetzt haben Sie selbst enge Zahlen (mit XML voraus), aber Ihr Blog schreit immer noch 10x schneller als XML . Mein Kommentar wird nicht einmal angezeigt? Haben Sie versucht, in Tausenden von JSONs zu suchen, ob ein Produkt mit ProductID=1234existiert? Haben Sie versucht, den JSON zu manipulieren? Haben Sie dies mit tieferen verschachtelten Hierarchien versucht?
Shnugo
13

Dies ist zu lang für einen Kommentar.

Wenn es "absolut falsch" wäre, würden die meisten Datenbanken es nicht unterstützen. Okay, die meisten Datenbanken unterstützen Kommas in der FROMKlausel und ich sehe das als "absolut falsch" an. Die Unterstützung für JSON ist jedoch eine Neuentwicklung und keine abwärtskompatible "Funktion".

Ein offensichtlicher Fall ist, wenn die JSON-Struktur einfach ein BLOB ist, das an die Anwendung zurückgegeben wird. Dann gibt es keine Debatte - abgesehen vom Aufwand für das Speichern von JSON, der für strukturierte Daten mit gemeinsamen Feldern in jedem Datensatz unnötig ausführlich ist.

Ein anderer Fall ist der Fall "spärlicher" Spalten. Sie haben Zeilen mit vielen möglichen Spalten, die jedoch von Zeile zu Zeile variieren.

Ein anderer Fall ist, wenn Sie "verschachtelte" Datensätze in einem Datensatz speichern möchten. JSON ist mächtig.

Wenn der JSON gemeinsame Felder für Datensätze hat, für die Sie eine Abfrage durchführen möchten, sollten Sie diese normalerweise besser in die richtigen Datenbankspalten einfügen. Daten sind jedoch kompliziert und es gibt einen Platz für Formate wie JSON.

Gordon Linoff
quelle
12

Ich werde meinen Zauberstab schwingen. Poof! Goldene Regeln für die Verwendung von JSON:

  • Wenn MySQL nicht suchen müssen innerhalb der JSON, und die Anwendung muss einfach eine Sammlung von Sachen, dann ist JSON gut, vielleicht sogar besser.

  • Wenn Sie auf Daten suchen wird, die im Inneren ist und Sie haben MariaDB 10.0.1 oder MySQL 5.7 (mit JSON - Datentyp und Funktionen), dann JSON könnte praktisch sein. Die "dynamischen" Spalten von MariaDB 5.3 sind eine Variante davon.

  • Wenn Sie "Entity-Attribute-Value" machen, dann ist JSON nicht gut, aber es ist das geringste von mehreren Übeln. http://mysql.rjweb.org/doc.php/eav

  • Für die Suche nach einer indizierten Spalte ist es ein großes Plus, wenn der Wert nicht in JSON vergraben ist.

  • Für die Suche nach einem Bereich in einer indizierten Spalte oder einer FULLTEXTSuche oder SPATIAList JSON nicht möglich.

  • Denn WHERE a=1 AND b=2der "zusammengesetzte" Index INDEX(a,b)ist großartig; kann JSON wahrscheinlich nicht nahe kommen.

  • JSON funktioniert gut mit "spärlichen" Daten; INDEXing funktioniert damit aber nicht so gut. (Ich beziehe mich auf Werte, die für viele Zeilen 'fehlen' oder NULL sind.)

  • JSON kann Ihnen "Arrays" und "Bäume" geben, ohne auf zusätzliche Tabellen zurückgreifen zu müssen. Aber graben Sie in solche Arrays / Bäume nur in der App, nicht in SQL.

  • JSON ist um Welten besser als XML. (Meine Meinung)

  • Wenn Sie nur über die App in die JSON-Zeichenfolge gelangen möchten, empfehle ich, sie (im Client) zu komprimieren und in einer zu speichern BLOB. Stellen Sie es sich wie eine JPG-Datei vor - da sind Dinge drin, aber SQL ist das egal.

Geben Sie Ihre Bewerbung an. Vielleicht können wir genauer sein.

Rick James
quelle
Die Kugeln sind gut, wenn Sie ein eindeutiges "Wann" und "Wann nicht" machen könnten, könnte dies noch besser machen
1
@levi - Ja, aber einige sind nicht unbedingt zu / nicht; Vielmehr hängen sie von Details in der Situation ab.
Rick James
2
JSON ist um Welten besser als XML. (Meine Meinung) Nun, JSON besteht aus weniger Zeichen ... Was können Sie mit JSON tun, was können Sie mit XML nicht tun? Der wichtigste Teil ist: Wie wird dieser Typ behandelt? Das Parsen von XML oder JSON mit String-Methoden ist ein Problem. Die Umwandlung der Struktur in einen Objektbaum ermöglicht viel bessere Ansätze. SQL Server speichert XML nativ in einem Baum, aber JSON wird - AFAIK - in einer Zeichenfolge leben ... Warum bevorzugen Sie JSON als Welten besser ?
Shnugo
2
@Shnugo - Einfacher zu lesen, kürzer, im Wesentlichen eine eindeutige Art, ein Array darzustellen. (XML hat mehrere, von denen die meisten durch Duplizieren des Schlüssels oder was auch immer missbraucht werden können.) Das Gleiche gilt für Hash. Dies macht die Zuordnung zu / von den meisten Computersprachen unkompliziert. (Ja, das ist meine "Meinung".)
Rick James
@RickJames Ich möchte es so ausdrücken, dass "JSON keine Klasse hat" (im Sinne von Klassen in einer Programmiersprache) - es eignet sich hervorragend für vollständig generische Listen und Hashes, wird jedoch sofort komplexer, wenn Sie bestimmte definieren möchten benutzerdefinierte Datenstrukturen. Im Kontext einer Datenbank wäre XML (falls unterstützt) offensichtlich besser, wenn die Eingabe XML ist, als sie irgendwie in JSON zu konvertieren (die Leute tun es, und die Ergebnisse sind nie schön).
IMSoP
9

New SQL Server bietet Funktionen zur Verarbeitung von JSON-Text. Als JSON formatierte Informationen können als Text in Standard-SQL Server-Spalten gespeichert werden, und SQL Server bietet Funktionen, mit denen Werte von diesen JSON-Objekten abgerufen werden können.

    DROP TABLE IF EXISTS Person

 CREATE TABLE Person 
 ( _id int identity constraint PK_JSON_ID primary key,
 value nvarchar(max)
 CONSTRAINT [Content should be formatted as JSON]
 CHECK ( ISJSON(value)>0 )
 )

Diese einfache Struktur ähnelt der Standard-NoSQL-Sammlung, die Sie in NoSQL-Datenbanken (z. B. Azure DocumentDB oder MongoDB) erstellen können, in denen Sie nur einen Schlüssel haben, der die ID darstellt, und einen Wert, der JSON darstellt.

Beachten Sie, dass NVARCHAR nicht nur ein einfacher Text ist. SQL Server verfügt über einen integrierten Textkomprimierungsmechanismus, mit dem auf der Festplatte gespeicherte Daten transparent komprimiert werden können. Die Komprimierung hängt von der Sprache ab und kann je nach Ihren Daten bis zu 50% betragen (siehe UNICODE-Komprimierung).

Der Hauptunterschied zwischen SQL Server und anderen einfachen NoSQL-Datenbanken besteht darin, dass Sie mit SQL Server ein hybrides Datenmodell verwenden können, in dem Sie mehrere JSON-Objekte in derselben „Sammlung“ speichern und mit regulären relationalen Spalten kombinieren können.

Stellen Sie sich beispielsweise vor, wir wissen, dass jede Person in Ihrer Sammlung Vor- und Nachnamen hat und dass Sie allgemeine Informationen über die Person als ein JSON-Objekt und Telefonnummern / E-Mail-Adressen als separate Objekte speichern können. In SQL Server 2016 können wir diese Struktur ohne zusätzliche Syntax einfach erstellen:

DROP TABLE IF EXISTS Person

CREATE TABLE Person (

 PersonID int IDENTITY PRIMARY KEY,

 FirstName nvarchar(100) NOT NULL,

 LastName nvarchar(100) NOT NULL,

 AdditionalInfo nvarchar(max) NULL,

 PhoneNumbers nvarchar(max) NULL,

 EmailAddresses nvarchar(max) NULL
 CONSTRAINT [Email addresses must be formatted as JSON array]
 CHECK ( ISJSON(EmailAddresses)>0 )

 )

Anstelle eines einzelnen JSON-Objekts können Sie Ihre Daten in dieser „Sammlung“ organisieren. Wenn Sie die Struktur jeder JSON-Spalte nicht explizit überprüfen möchten, müssen Sie nicht für jede Spalte eine JSON-Überprüfungsbeschränkung hinzufügen (in diesem Beispiel habe ich die CHECK-Einschränkung nur für die Spalte EmailAddresses hinzugefügt).

Wenn Sie diese Struktur mit der Standard-NoSQL-Sammlung vergleichen, werden Sie möglicherweise feststellen, dass Sie schneller auf stark typisierte Daten (Vorname und Nachname) zugreifen können. Daher ist diese Lösung eine gute Wahl für Hybridmodelle, bei denen Sie einige Informationen identifizieren können, die für alle Objekte wiederholt werden, und andere variable Informationen als JSON gespeichert werden können. Auf diese Weise können Sie Flexibilität und Leistung kombinieren.

Wenn Sie diese Struktur mit dem Schema der Personentabelle AdventureWorks vergleichen, stellen Sie möglicherweise fest, dass wir viele verwandte Tabellen entfernt haben.

Neben der Einfachheit des Schemas sind Ihre Datenzugriffsvorgänge im Vergleich zu komplexen relationalen Strukturen einfacher. Jetzt können Sie eine einzelne Tabelle lesen, anstatt mehrere Tabellen zu verbinden. Wenn Sie eine neue Person mit verwandten Informationen (E-Mail-Adressen, Telefonnummern) einfügen müssen, können Sie einen einzelnen Datensatz in eine Tabelle einfügen, anstatt einen Datensatz in die AdventureWorks Person-Tabelle einzufügen. Verwenden Sie dabei die Identitätsspalte, um den Fremdschlüssel zu finden, der zum Speichern von Telefonen verwendet wird , E-Mail-Adressen usw. Darüber hinaus können Sie in diesem Modell problemlos einzelne Personenzeilen löschen, ohne Kaskadenlöschungen mithilfe von Fremdschlüsselbeziehungen durchzuführen.

NoSQL-Datenbanken sind für einfache Operationen zum Lesen, Einfügen und Löschen optimiert. Mit SQL Server 2016 können Sie dieselbe Logik in relationalen Datenbanken anwenden.

JSON-Einschränkungen In den vorherigen Beispielen haben wir gesehen, wie einfache Einschränkungen hinzugefügt werden, die überprüfen, ob der in der Spalte gespeicherte Text ordnungsgemäß formatiert ist. Obwohl JSON kein starkes Schema hat, können Sie auch komplexe Einschränkungen hinzufügen, indem Sie Funktionen kombinieren, die Werte aus JSON lesen, und Standard-T-SQL-Funktionen:

ALTER TABLE Person
 ADD CONSTRAINT [Age should be number]
 CHECK ( ISNUMERIC(JSON_VALUE(value, '$.age'))>0 )

 ALTER TABLE Person
 ADD CONSTRAINT [Person should have skills]
 CHECK ( JSON_QUERY(value, '$.skills') IS NOT NULL)
First constraint will take the value of $.age property and check is this numeric value. Second constraint will try to find JSON object in $.skills property and verify that it exists. The following INSERT statements will fail due to the violation of constraints:



INSERT INTO Person(value)
 VALUES ('{"age": "not a number", "skills":[]}')

 INSERT INTO Person(value)
 VALUES ('{"age": 35}')

Beachten Sie, dass CHECK-Einschränkungen Ihre Einfüge- / Aktualisierungsprozesse verlangsamen können, sodass Sie sie möglicherweise vermeiden, wenn Sie eine schnellere Schreibleistung benötigen.

Komprimierter JSON-Speicher Wenn Sie großen JSON-Text haben, können Sie JSON-Text mithilfe der integrierten COMPRESS-Funktion explizit komprimieren. Im folgenden Beispiel wird komprimierter JSON-Inhalt als Binärdaten gespeichert, und wir haben eine Spalte berechnet, die JSON als Originaltext mithilfe der DECOMPRESS-Funktion dekomprimiert:

CREATE TABLE Person

 ( _id int identity constraint PK_JSON_ID primary key,

 data varbinary(max),

 value AS CAST(DECOMPRESS(data) AS nvarchar(max))

 )



 INSERT INTO Person(data)

 VALUES (COMPRESS(@json))

Die Funktionen COMPRESS und DECOMPRESS verwenden die Standard-GZip-Komprimierung. Wenn Ihr Client die GZip-Komprimierung verarbeiten kann (z. B. ein Browser, der GZIP-Inhalte versteht), können Sie komprimierte Inhalte direkt zurückgeben. Beachten Sie, dass dies ein Kompromiss zwischen Leistung und Speicher ist. Wenn Sie häufig komprimierte Daten abfragen, ist die Leistung möglicherweise geringer, da der Text jedes Mal dekomprimiert werden muss.

Hinweis: JSON-Funktionen sind nur in SQL Server 2016+ und in der Azure SQL-Datenbank verfügbar.

Weitere Informationen finden Sie in der Quelle dieses Artikels

https://blogs.msdn.microsoft.com/sqlserverstorageengine/2015/11/23/storing-json-in-sql-server/

AMRESH PANDEY
quelle
5

Die "goldene Regel", die ich auf eine Art von Handwelle verwende, lautet: Wenn ich JSON in seinem Rohformat benötige, ist es in Ordnung, es zu speichern. Wenn ich einen besonderen Punkt beim Parsen machen muss, dann ist es nicht.

Wenn ich beispielsweise eine API erstelle, die unformatiertes JSON sendet, und sich dieser Wert aus irgendeinem Grund nicht ändert, ist es in Ordnung , ihn als unformatiertes JSON zu speichern. Wenn ich es analysieren, ändern, aktualisieren usw. muss, dann nicht so sehr.

piisexactly3
quelle
4

Die Frage, die Sie stellen müssen, lautet:

Bin ich daran gebunden, nur diese Datenbank zu verwenden?

TUN

  1. Wenn Sie zum Speichern von JSON eine andere Datenbank verwenden können, verwenden Sie eine Dokumentenspeicherlösung wie CouchDB, DynamoDB oder MongoDB.
  2. Verwenden Sie die Fähigkeit dieser Dokumentenspeicher-Datenbank, hierarchische Daten zu indizieren und zu durchsuchen.
  3. Verwenden Sie eine relationale Datenbank für Ihre relationalen Daten.
  4. Verwenden Sie eine relationale Datenbank für Berichterstellung, Data Warehousing und Data Mining.

NICHT

  1. Speichern Sie JSON nach Möglichkeit als Zeichenfolge.
  2. Versuchen Sie, die maximale Länge der JSON-Daten zu ermitteln.
  3. Verwenden Sie varchar, um JSON zu speichern (verwenden Sie Text / Blob, wenn Sie müssen).
  4. Versuchen Sie, gespeicherten JSON nach Werten zu durchsuchen.
  5. Sorgen Sie sich, JSON zu entkommen, um es als Zeichenfolge zu speichern.
Anand
quelle
Dies ist die Formation, nach der ich gesucht habe, sauber und einfach. Einige der wichtigen Themen, die in den anderen Antworten behandelt werden, sind jedoch nicht enthalten. Wenn andere Fälle hinzugefügt werden könnten, wäre großartig
2

Jsons sind nicht großartig in relationalen DBs. Wenn Sie den JSON in Spalten aufklappen und in einer Datenbank speichern, ist dies großartig, aber das Speichern eines JSON als Blob ist neben der Verwendung als Datenarchivierungssystem.

Es kann mehrere Gründe geben, ein json nicht zu entfalten und in einer einzelnen Spalte zu speichern, aber die Entscheidung wäre getroffen worden, da die Werte in diesem json-Feld nicht für Abfragen verwendet würden (oder die Werte bereits in Spalten entfaltet wurden).

Außerdem würde der größte Teil der JSON-Verarbeitung, wenn das Feld überhaupt abgefragt wurde, außerhalb der SQL-Umgebung liegen, da SQL einfach nicht für die JSON-Verarbeitung gedacht ist. Die eigentliche Frage lautet dann: Wo speichere ich diesen JSON, lasse ich ihn einfach als Flatfiles und frage ihn bei Bedarf über ein anderes System (spark / hive / etc) ab.

Ich würde Ihrem DB-Künstler zustimmen, verwenden Sie RDBMS nicht für die Archivierung. Es gibt günstigere Optionen. Außerdem können JSON-Blobs sehr groß werden und mit der Zeit den DB-Speicherplatz blockieren.

Satyadev
quelle
0

PostgreSQL hat einen eingebauten, jsonund jsonbDatentyp

Dies sind einige Beispiele:

CREATE TABLE orders (
 ID serial NOT NULL PRIMARY KEY,
 info json NOT NULL
);

INSERT INTO orders (info)
VALUES
 (
 '{ "customer": "Lily Bush", "items": {"product": "Diaper","qty": 24}}'
 ),
 (
 '{ "customer": "Josh William", "items": {"product": "Toy Car","qty": 1}}'
 ),
 (
 '{ "customer": "Mary Clark", "items": {"product": "Toy Train","qty": 2}}'
 );

PostgreSQL bietet zwei einheimische Betreiber ->und ->>zur Abfrage JSON - Daten.

Der Operator ->gibt das JSON-Objektfeld per Schlüssel zurück.

Der Operator ->>gibt das JSON-Objektfeld per Text zurück.

SELECT
 info -> 'customer' AS customer
FROM
 orders;

SELECT
 info ->> 'customer' AS customer
FROM
 orders
WHERE
 info -> 'items' ->> 'product' = 'Diaper'
Galina Alperovich
quelle