Was ist der beste SQL-Datentyp zum Speichern von JSON-Zeichenfolgen?

127

Was ist der beste SQL-Datentyp zum Speichern von JSON-Zeichenfolgen?

static List<ProductModel> CreateProductList()
{
    string json = @"[
        {
            ProductId: 1, 
            ProductCode: 'A', 
            Product: 'A'
        },
        {
            ProductId: 2, 
            ProductCode: 'B', 
            Product: 'B'
        }
    ]";

    IList<JToken> tokenList = JToken.Parse(json).ToList();
    List<ProductModel> productList = new List<ProductModel>();

    foreach (JToken token in tokenList)
    {
        productList.Add(JsonConvert.DeserializeObject<ProductModel>(token.ToString()));
    }

    return productList;
}

Welchen SQL-Datentyp sollten wir zum Speichern einer solchen Zeichenfolge verwenden, die JSON enthält?

  • NVARCHAR(255)?
  • TEXT?
  • VARBINARY(MAX)?
DatPT
quelle
1
Nur ein zufälliges Rauschen (der Kommentar, nicht die Daten): Vielleicht möchten Sie es auch komprimieren. In diesem Fall benötigen Sie etwas Binäres. Auf der anderen Seite: Warum nicht einfach die richtigen Tabellen für die Daten entwerfen?
Der Nagel
3
@ The Nail: Manchmal ist das Speichern von etwas als JSON (oder als "Dokument") für den Bedarf geeignet. Wie für eine Workflow-Engine oder ein Dokumentenmanagement usw. Ich mache dies in einem aktuellen Projekt und gehe tatsächlich vom relationalen zum Dokumentansatz für die Befehlsseite meiner CQRS-Implementierung über. Es ist sehr schnell, wenn Sie einen Serializer wie ServiceStack oder JSON.Net verwenden.
Swannee

Antworten:

198

Sicher NICHT :

  • TEXT, NTEXT: Diese Typen sind ab SQL Server 2005 veraltet und sollten nicht für Neuentwicklungen verwendet werden. Verwenden Sie VARCHAR(MAX)oder NVARCHAR(MAX)stattdessen

  • IMAGE, VARBINARY(MAX): IMAGEist genauso veraltet wie TEXT/NTEXTund es macht wirklich keinen Sinn, eine Textzeichenfolge in einer Binärspalte zu speichern ....

Das bedeutet also im Grunde genommen : VARCHAR(x)oder speichert Nicht-Unicode-Zeichenfolgen (1 Byte pro Zeichen) und speichert alles in einem Unicode-Modus mit 2 Byte pro Zeichen. Benötigen Sie Unicode? Haben Sie möglicherweise arabische, hebräische, chinesische oder andere nicht-westeuropäische Schriftzeichen in Ihren Zeichenfolgen? Dann geh mitNVARCHAR(x)VARCHARNVARCHARNVARCHAR

Die (N)VARCHARSpalten sind in zwei Varianten erhältlich: Entweder definieren Sie eine maximale Länge, die 8000 Byte oder weniger ergibt ( VARCHARbis zu 8000 Zeichen, NVARCHARbis zu 4000), oder wenn dies nicht ausreicht, verwenden Sie die (N)VARCHAR(MAX)Versionen, in denen bis zu 2 GByte Daten gespeichert sind.

Update: SQL Server 2016 wird native JSON-Unterstützung bieten - ein neuer JSONDatentyp (der darauf basiert nvarchar) wird eingeführt sowie ein FOR JSONBefehl zum Konvertieren der Ausgabe einer Abfrage in das JSON-Format

Update Nr. 2: Microsoft hat im Endprodukt keinen separaten JSONDatentyp hinzugefügt. Stattdessen gibt es eine Reihe von JSON-Funktionen (zum Packen von Datenbankzeilen in JSON oder zum Parsen von JSON in relationale Daten), die mit Spalten des Typs arbeitenNVARCHAR(n)

marc_s
quelle
25
NVARCHAR sollte die bevorzugte Wahl sein, da SQL Server 2016 es für seinen nativen JSON-Support verwendet. Blogs.msdn.com/b/jocapc/archive/2015/05/16/…
Loudenvier
@marc_s Ist Ihre "Update" -Anweisung korrekt? Ich kann keine offiziellen JSON-Datentypen finden ...?
Nix
2
@Nix: Ich denke, am Ende unterstützt SQL Server JSON-Funktionen , die mit NVARCHAR(n)Datentypen arbeiten
marc_s
2
Vielleicht möchten Sie Ihre Antwort aktualisieren, um nicht anzugeben, dass es einen Json-Datentyp gibt
Nix
1
varbinary (max) könnte verwendet werden, wenn Komprimierung verwendet wird
Marat Gallyamov
31

Ich werde gehen für nvarchar(max). Das sollte der Anforderung entsprechen.

Update: Mit SQL Server 2016 und Azure SQL gibt es viele zusätzliche native JSON-Funktionen. Dies kann sich positiv auf Ihr Design oder Ihren Ansatz auswirken. Weitere Informationen finden Sie unter: https://docs.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server

Kangkan
quelle
8
Benötigen Sie wirklich den Unicode-Speicher mit 2 Byte pro Zeichen? Je nach Ihren Daten - es könnte nur doppelt so viel Bytes verschwendet nach Bedarf ... (aber wenn Sie DO Notwendigkeit Unicode - dann , das ist der einzige Weg zu gehen, ich bin einverstanden!)
marc_s
5
nvarchar - weil die Daten nicht definiert sind. Wenn wir der Meinung sind, dass das System keinen Unicode benötigt, können wir die Umstellung auf varchar (max)
Kangkan
5
Durch die Verwendung werden auch nvarchardie Sortierprobleme vermieden, die bei der Verwendung auftreten können varchar, die Abfrageleistung ist jedoch langsamer als bei varchar. Tolle DBA-Frage mit weiteren Infos.
Scotty.NET
5
Wie hat diese Frage so viele positive Stimmen bekommen? Es heißt also, welcher Datentyp verwendet werden soll, okay ... aber es wird nicht einmal versucht zu erklären, warum dies die richtige Wahl wäre.
stakx - nicht mehr beitragen
1
Sie können jederzeit varchar verwenden und alle Unicode-Zeichen maskieren. Dies ist ein guter Ansatz, wenn Sie nur gelegentlich Unicode-Zeichen in Ihrem Text haben, da dies Platz spart, wenn Sie ein nvarchar
chrisb
3

Ich würde die Verwendung empfehlen, nvarchar(max)wenn Sie JSON-Funktionen in SQL 2016 oder Azure SQL verwenden möchten .

Wenn Sie diese Funktionen nicht verwenden möchten, können Sie varbinary(max)sie mit COMPRESS(und DECOMPRESS) kombinieren . Weitere Informationen: https://blogs.msdn.microsoft.com/sqlserverstorageengine/2015/11/23/storing-json-in-sql-server/

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.

Marat Gallyamov
quelle
welches ist JSON auf SQL 2016 verfügt ?
Kiquenet
0

nvarchar (max) ist dafür besser, auch eine Sache, die Sie so machen können.

public class TableName
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }
     
    public string FieldJson { get; set; }   //save json in this field and
      
    [NotMapped]
    public List<FieldList> FieldList  // get return list from this properity
    {
        get => !string.IsNullOrEmpty(FieldJson) ? JsonConvert.DeserializeObject<List<FieldList>>(FieldJson) : null; 
    }

   
}
Davinder Singh
quelle