Qual é o melhor tipo de dados SQL para armazenar a string JSON?

127

Qual é o melhor tipo de dados SQL para armazenar a string 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;
}

Que tipo de dados SQL devemos usar para armazenar uma string contendo JSON?

  • NVARCHAR(255)?
  • TEXT?
  • VARBINARY(MAX)?
DatPT
fonte
1
Apenas algum ruído aleatório (o comentário, não os dados): você também pode compactá-lo. Nesse caso, você precisa de algo binário. Por outro lado: por que não apenas criar tabelas apropriadas para os dados?
The Nail
3
@ The Nail: Às vezes, armazenar algo como JSON (ou como um "documento") é adequado para a necessidade. Como para um mecanismo de fluxo de trabalho ou gerenciamento de documentos, etc ... Estou fazendo isso em um projeto atual, passando de abordagem relacional para documento para o lado de comando da minha implementação do CQRS. É muito rápido se você usar um serializador, como ServiceStack ou JSON.Net.
Swannee

Respostas:

198

Certamente NÃO :

  • TEXT, NTEXT: esses tipos estão obsoletos no SQL Server 2005 e não devem ser usados ​​para novos desenvolvimentos. UsarVARCHAR(MAX) ou em NVARCHAR(MAX)vez disso

  • IMAGE, VARBINARY(MAX): IMAGEé preterido da mesma forma TEXT/NTEXTe não há realmente nenhum sentido em armazenar uma sequência de texto em uma coluna binária ....

De modo que basicamente deixa VARCHAR(x)ou NVARCHAR(x): VARCHARarmazena cadeias não Unicode (1 byte por caractere) e NVARCHARarmazena tudo no modo Unicode de 2 bytes por caractere. Então você precisa de Unicode? Você tem caracteres árabes, hebraicos, chineses ou outros caracteres que não sejam da Europa Ocidental em suas cordas, potencialmente? Então vá comNVARCHAR

As (N)VARCHARcolunas têm dois tipos: você define um comprimento máximo que resulta em 8000 bytes ou menos ( VARCHARaté 8000 caracteres, NVARCHARaté 4000) ou, se isso não for suficiente, use as (N)VARCHAR(MAX)versões que armazenam até 2 GByte de dados.

Atualização: o SQL Server 2016 terá suporte JSON nativo - um novo JSONtipo de dados (baseado emnvarchar ) será introduzido, bem como um FOR JSONcomando para converter a saída de uma consulta no formato JSON

Atualização # 2: no produto final, a Microsoft não incluiu um JSONtipo de dados separado . Em vez disso, existem várias funções JSON (para empacotar linhas do banco de dados em JSON ou para analisar JSON em dados relacionais) que operam em colunas do tipoNVARCHAR(n)

marc_s
fonte
25
NVARCHAR deve ser a escolha preferida como sql server 2016 usá-lo para o seu apoio JSON nativa blogs.msdn.com/b/jocapc/archive/2015/05/16/...
Loudenvier
@marc_s Sua declaração de "atualização" está correta? Não consigo encontrar nenhum tipo oficial de dados JSON ...?
Nix
2
@Nix: Eu acho que no final, o SQL Server suporta funções JSON que operam em NVARCHAR(n)tipos de dados
marc_s
2
Você pode querer atualizar sua resposta a não estado há um tipo de dados Json
Nix
1
varbinary (max) pode ser utilizado quando se usa a compressão
Marat Gallyamov
31

Eu irei nvarchar(max). Isso deve atender ao requisito.

Atualização: com o SQL Server 2016 e o ​​SQL do Azure, há muitos recursos JSON nativos adicionais. Isso pode impactar positivamente seu design ou abordagem. Você pode ler isso para obter mais informações: https://docs.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server

Kangkan
fonte
8
Você realmente precisa do armazenamento Unicode de 2 bytes por caractere? Dependendo de seus dados - ele só poderia estar perdendo o dobro de bytes conforme necessário ... (mas se você FAZER necessidade Unicode - então essa é a única maneira de ir, eu concordo!)
marc_s
5
nvarchar - porque os dados não estão definidos. Se sentirmos que o sistema não vai precisar de unicode, podemos economizar mudando para varchar (max)
Kangkan
5
Além disso, o uso nvarcharevita os problemas de agrupamento que você eventualmente terá ao usar varchar, mas será mais lento no desempenho da consulta do que varchar. Ótima pergunta sobre DBA com mais informações.
Scotty.NET
5
Como essa pergunta recebeu tantos votos positivos? Então diz qual tipo de dados usar, tudo bem ... mas nem tenta explicar por que essa seria a escolha certa.
stakx - não está mais contribuindo
1
Você sempre pode usar varchar e escapar de qualquer caractere unicode. Esta é uma abordagem bom se você só terá caracteres Unicode ocasionais em seu texto, pois economiza espaço sobre usando um nvarchar
chrisb
3

Eu recomendaria usar nvarchar(max)se você planeja usar os recursos JSON no SQL 2016 ou SQL do Azure.

Se você não planeja usar esses recursos, poderá usar varbinary(max)combinado com as funções COMPRESS(e DECOMPRESS). Mais informações: https://blogs.msdn.microsoft.com/sqlserverstorageengine/2015/11/23/storing-json-in-sql-server/

As funções COMPRESS e DECOMPRESS usam a compressão GZip padrão. Se o seu cliente puder lidar com a compactação GZip (por exemplo, navegador que entende o conteúdo gzip), você poderá retornar diretamente o conteúdo compactado. Observe que isso é uma troca de desempenho / armazenamento. Se você consulta dados compactados com frequência, seu desempenho é mais lento porque o texto deve ser descompactado a cada vez.

Marat Gallyamov
fonte
quais são os recursos JSON no SQL 2016 ?
21418 Kiquenet
0

nvarchar (max) é melhor para isso, também mais uma coisa que você pode fazer assim.

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
fonte