Какой тип данных SQL лучше всего подходит для хранения строки JSON?

127

Какой тип данных SQL лучше всего подходит для хранения строки 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;
}

Какой тип данных SQL мы должны использовать для хранения такой строки, содержащей JSON?

  • NVARCHAR(255)?
  • TEXT?
  • VARBINARY(MAX)?
DatPT
источник
1
Просто какой-то случайный шум (комментарий, а не данные): его тоже можно сжать. В этом случае вам нужно что-то двоичное. С другой стороны: почему бы просто не создать правильные таблицы для данных?
Гвоздь
3
@The Nail: Иногда хранение чего-либо в формате JSON (или в виде «документа») подходит для нужд. Например, для механизма рабочего процесса или управления документами и т. Д. Я делаю это в текущем проекте, фактически перехожу от реляционного подхода к документированному для командной части моей реализации CQRS. Это очень быстро, если вы используете сериализатор, такой как ServiceStack или JSON.Net.
swannee

Ответы:

198

Конечно, НЕ :

  • TEXT, NTEXT: эти типы устарели с SQL Server 2005 и не должны использоваться для новых разработок. Используйте VARCHAR(MAX)или NVARCHAR(MAX)вместо

  • IMAGE, VARBINARY(MAX): IMAGEустарело TEXT/NTEXT, и на самом деле нет смысла хранить текстовую строку в двоичном столбце ....

Таким образом, в основном оставляет VARCHAR(x)или NVARCHAR(x): VARCHARхранит строки, отличные от Unicode (1 байт на символ), и NVARCHARсохраняет все в режиме Unicode с 2 байтами на символ. Так вам нужен Unicode? Есть ли в ваших строках символы арабского, иврита, китайского или других неевропейского происхождения? Тогда иди сNVARCHAR

Эти (N)VARCHARколонны в двух вариантах: либо определить максимальную длину , что приводит к 8000 байт или меньше ( VARCHARдо 8000 символов, NVARCHARдо 4000), или , если этого недостаточно, использовать (N)VARCHAR(MAX)версии, которые хранят до 2 Гбайт данных.

Обновление: SQL Server 2016 будет иметь встроенную поддержку JSON - будет представлен новый JSONтип данных (на основе которого nvarchar), а также FOR JSONкоманда для преобразования вывода запроса в формат JSON.

Обновление №2: в конечном продукте Microsoft не включила отдельный JSONтип данных - вместо этого существует ряд JSON-функций (для упаковки строк базы данных в JSON или для синтаксического анализа JSON в реляционные данные), которые работают со столбцами типаNVARCHAR(n)

marc_s
источник
25
NVARCHAR должен быть предпочтительным выбором, поскольку sql server 2016 будет использовать его для своей собственной поддержки JSON blogs.msdn.com/b/jocapc/archive/2015/05/16/…
Loudenvier
@marc_s Правильно ли ваше "обновление"? Я не могу найти официальных типов данных JSON ...?
Nix
2
@Nix: я думаю, что в конце концов SQL Server поддерживает функции JSON, которые работают с NVARCHAR(n)типами данных
marc_s
2
Возможно, вы захотите обновить свой ответ, чтобы не указывать, что существует тип данных Json
Nix,
1
varbinary (max) может использоваться при использовании сжатия
Марат Галлямов
31

Я пойду за nvarchar(max). Это должно соответствовать требованиям.

Обновление: в SQL Server 2016 и Azure SQL есть много дополнительных собственных возможностей JSON. Это может положительно повлиять на ваш дизайн или подход. Вы можете прочитать это подробнее: https://docs.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server

Kangkan
источник
8
Вам действительно нужно хранилище Unicode с 2 байтами на символ ?? В зависимости от ваших данных - он может просто тратить вдвое больше байтов, чем необходимо ... (но если вам ДЕЙСТВИТЕЛЬНО нужен Unicode - тогда это единственный выход, я согласен!)
marc_s
5
nvarchar - потому что данные не определены. Если мы чувствуем, что системе не нужен юникод, мы можем сэкономить, перейдя на varchar (max)
Кангкан,
5
Кроме того, использование nvarcharпозволяет избежать проблем с сопоставлением, которые в конечном итоге могут возникнуть при использовании varchar, но он будет медленнее по производительности запросов, чем varchar. Отличный вопрос DBA с дополнительной информацией.
Scotty.NET
5
Как этот вопрос получил столько голосов? Итак, он говорит, какой тип данных использовать, хорошо ... но он даже не пытается объяснить, почему это был бы правильный выбор.
stakx - больше не вносит свой вклад
1
Вы всегда можете использовать varchar и избегать любых символов Unicode. Это хороший подход, если у вас будут только случайные символы Unicode в вашем тексте, поскольку это экономит место при использовании nvarchar
chrisb
3

Я бы рекомендовал использовать, nvarchar(max)если вы планируете использовать функции JSON в SQL 2016 или Azure SQL.

Если вы не планируете использовать эти функции, вы можете использовать функции в varbinary(max)сочетании с COMPRESSDECOMPRESS). Дополнительная информация: https://blogs.msdn.microsoft.com/sqlserverstorageengine/2015/11/23/storing-json-in-sql-server/

Функции COMPRESS и DECOMPRESS используют стандартное сжатие GZip. Если ваш клиент может обрабатывать сжатие GZip (например, браузер, который понимает содержимое gzip), вы можете напрямую вернуть сжатый контент. Обратите внимание, что это компромисс между производительностью и объемом памяти. Если вы часто запрашиваете сжатые данные, производительность при переносе будет ниже, потому что текст нужно каждый раз распаковывать.

Марат Галлямов
источник
какие функции JSON есть в SQL 2016 ?
Kiquenet
0

nvarchar (max) лучше для этого, также вы можете сделать еще кое-что.

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

   
}
Давиндер Сингх
источник