Qual è il tipo di dati SQL migliore per l'archiviazione della stringa JSON?


127

Qual è il miglior tipo di dati SQL per l'archiviazione della stringa JSON?

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;
}

Quale tipo di dati SQL dovremmo usare per archiviare una tale stringa contenente JSON?

  • NVARCHAR(255)?
  • TEXT?
  • VARBINARY(MAX)?

1
Solo un po 'di rumore casuale (il commento, non i dati): potresti volerlo comprimere anche tu. In tal caso hai bisogno di qualcosa di binario. D'altra parte: perché non progettare solo tabelle adeguate per i dati?
The Nail,

3
@The Nail: A volte la memorizzazione di qualcosa come JSON (o come "documento") è appropriata per la necessità. Come per un motore di flusso di lavoro o per la gestione dei documenti, ecc ... Lo sto facendo su un progetto attuale, passando dall'approccio relazionale a quello documentale per il lato comando della mia implementazione CQRS. È molto veloce se si utilizza un serializzatore come ServiceStack o JSON.Net.
Swannee,

Risposte:


198

Certamente NON :

  • TEXT, NTEXT: questi tipi sono obsoleti a partire da SQL Server 2005 e non devono essere utilizzati per nuovi sviluppi. Usa VARCHAR(MAX)o NVARCHAR(MAX)invece

  • IMAGE, VARBINARY(MAX): IMAGEè deprecato proprio come TEXT/NTEXT, e non ha davvero senso archiviare una stringa di testo in una colonna binaria ....

Quindi praticamente lascia VARCHAR(x)o NVARCHAR(x): VARCHARmemorizza stringhe non Unicode (1 byte per carattere) e NVARCHARmemorizza tutto in modalità Unicode a 2 byte per carattere. Quindi hai bisogno di Unicode? Possiedi potenzialmente caratteri arabi, ebraici, cinesi o di altri paesi non dell'Europa occidentale? Quindi vai conNVARCHAR

Le (N)VARCHARcolonne sono disponibili in due versioni: o si definisce una lunghezza massima che risulta in 8000 byte o meno ( VARCHARfino a 8000 caratteri, NVARCHARfino a 4000) oppure, se ciò non bastasse, utilizzare le (N)VARCHAR(MAX)versioni che memorizzano fino a 2 GByte di dati.

Aggiornamento: SQL Server 2016 avrà il supporto JSON nativo: verrà introdotto un nuovo JSONtipo di dati (basato su nvarchar) e un FOR JSONcomando per convertire l'output di una query in formato JSON

Aggiornamento n. 2: nel prodotto finale, Microsoft non includeva un JSONtipo di dati separato - invece, ci sono un certo numero di funzioni JSON (per impacchettare le righe del database in JSON o per analizzare JSON in dati relazionali) che operano su colonne di tipoNVARCHAR(n)


25
NVARCHAR dovrebbe essere la scelta preferita poiché SQL Server 2016 lo utilizzerà per il suo supporto nativo JSON blogs.msdn.com/b/jocapc/archive/2015/05/16/…
Loudenvier

@marc_s L'istruzione "update" è corretta? Non riesco a trovare alcun tipo di dati JSON ufficiale ...?
Nix,

2
@Nix: Penso che alla fine SQL Server supporti le funzioni JSON che operano su NVARCHAR(n)tipi di dati
marc_s,

2
Potresti voler aggiornare la tua risposta per non dichiarare che esiste un tipo di dati Json
Nix,

1
varbinary (max) potrebbe essere usato quando si utilizza la compressione
Marat Gallyamov il

31

Ci andrò per nvarchar(max). Questo dovrebbe soddisfare il requisito.

Aggiornamento: con SQL Server 2016 e Azure SQL sono disponibili molte altre funzionalità JSON native. Ciò potrebbe avere un impatto positivo sul tuo design o approccio. Puoi leggere questo per ulteriori informazioni: https://docs.microsoft.com/en-us/sql/relational-d database / json / json-data - sql - server


8
Hai davvero bisogno dell'archiviazione Unicode a 2 byte per carattere ?? A seconda dei dati - potrebbe solo essere sprecando il doppio dei byte in base alle esigenze ... (ma se si DO necessità Unicode - allora questo è l'unico modo per andare, sono d'accordo!)
marc_s

5
nvarchar: perché i dati non sono definiti. Se riteniamo che il sistema non avrà bisogno dell'unicode, possiamo salvare il passaggio a varchar (max)
Kangkan,

5
Inoltre, l'utilizzo nvarcharevita i problemi di confronto che alla fine si verificheranno durante l'utilizzo varchar, ma sarà più lento nelle prestazioni della query rispetto a varchar. Ottima domanda DBA con ulteriori informazioni.
Scotty.NET,

5
In che modo questa domanda ha ottenuto così tanti voti? Quindi dice quale tipo di dati usare, bene ... ma non prova nemmeno a spiegare perché sarebbe la scelta giusta.
stakx - non contribuisce più al

1
Puoi sempre usare varchar e sfuggire a qualsiasi carattere unicode. Questo è un buon approccio se nel tuo testo avrai solo caratteri Unicode occasionali poiché risparmierà spazio usando un nvarchar
chrisb

3

Consiglierei di usarlo nvarchar(max)se prevedi di usare le funzionalità JSON su SQL 2016 o Azure SQL.

Se non si prevede di utilizzare tali funzionalità, è possibile utilizzare in varbinary(max)combinazione con COMPRESS(e DECOMPRESS) funzioni. Ulteriori informazioni: https://blogs.msdn.microsoft.com/sqlserverstorageengine/2015/11/23/storing-json-in-sql-server/

Le funzioni COMPRESS e DECOMPRESS utilizzano la compressione GZip standard. Se il tuo client è in grado di gestire la compressione GZip (ad es. Browser che comprende il contenuto di gzip), puoi restituire direttamente il contenuto compresso. Si noti che questo è un compromesso tra prestazioni / archiviazione. Se esegui spesso query su dati compressi, le prestazioni potrebbero essere più lente perché il testo deve essere decompresso ogni volta.


quali sono le funzionalità JSON su SQL 2016 ?
Kiquenet,


0

nvarchar (max) è meglio per questo, anche un'altra cosa che puoi fare in questo modo.

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; 
    }

   
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.