Оптимизация обработки JSON с помощью выполняющейся в памяти OLTP
Область применения: SQL Server 2017 (14.x) и более поздних версий База данных SQL Azure Управляемый экземпляр SQL Azure
База данных SQL Azure и SQL Server позволяют работать с текстами в формате JSON. Чтобы повысить производительность запросов, обрабатывающих данные JSON, можно хранить документы JSON в таблицах, оптимизированных для памяти, с помощью стандартных строковых столбцов (тип nvarchar ). Хранение данных JSON в таблицах, оптимизированных для памяти, повышает производительность запросов с помощью доступа к данным без блокировки в памяти.
Хранение документов JSON в таблицах, оптимизированных для памяти
В примере ниже показана таблица Product
, оптимизированная для памяти, с двумя столбцами JSON — Tags
и Data
.
CREATE SCHEMA xtp;
GO
CREATE TABLE xtp.Product (
ProductID INT PRIMARY KEY NONCLUSTERED, --standard column
Name NVARCHAR(400) NOT NULL, --standard column
Price FLOAT, --standard column
Tags NVARCHAR(400), --JSON stored in string column
Data NVARCHAR(4000) --JSON stored in string column
)
WITH (MEMORY_OPTIMIZED = ON);
GO
Оптимизация обработки JSON с помощью дополнительных функций выполнения в памяти
Вы можете полностью интегрировать функции JSON с существующими технологиями OLTP в памяти. Вы сможете выполнять следующее:
- Проверять структуру документов JSON, хранящихся в таблицах, оптимизированных для памяти, с помощью компилируемых в собственном коде ограничений CHECK.
- Предоставлять строго типизированные значения, сохраненные в документах JSON, с помощью вычисляемых столбцов.
- Индексировать значения в документах JSON с помощью индексов, оптимизированных для памяти.
- Компилировать в собственном коде SQL-запросы, использующие значения из документов JSON или форматирующие результаты в виде текста JSON.
Проверка столбцов JSON
Вы можете добавить встроенные скомпилированные ограничения CHECK, которые проверяют содержимое документов JSON, хранящихся в строковом столбце, чтобы обеспечить правильное форматирование текста JSON, хранящегося в таблицах, оптимизированных для памяти.
В следующем примере создается таблица Product
с JSON-столбцом Tags
. Столбец Tags
имеет ограничение CHECK, которое использует функцию ISJSON
для проверки в столбце текста JSON.
DROP TABLE IF EXISTS xtp.Product;
GO
CREATE TABLE xtp.Product (
ProductID INT PRIMARY KEY NONCLUSTERED,
Name NVARCHAR(400) NOT NULL,
Price FLOAT,
Tags NVARCHAR(400)
CONSTRAINT [Tags should be formatted as JSON] CHECK (ISJSON(Tags) = 1),
Data NVARCHAR(4000)
)
WITH (MEMORY_OPTIMIZED = ON);
GO
Вы можете также добавить скомпилированное в собственном коде ограничение CHECK в существующую таблицу, содержащую столбцы JSON.
ALTER TABLE xtp.Product
ADD CONSTRAINT [Data should be JSON]
CHECK (ISJSON(Data)=1);
Предоставление значений JSON с помощью вычисляемых столбцов
Вычисляемые столбцы позволяют вам предоставлять значения из текста JSON и получать доступ к этим значениям без необходимости повторно получать значения из текста JSON и повторно анализировать структуру JSON. Значения, предоставляемые таким образом, строго типизированы и физически сохраняются в вычисляемых столбцах. Доступ к значениям JSON с помощью материализованных вычисляемых столбцов выполняется быстрее, чем прямой доступ к значениям в документе JSON.
В примере ниже показано, как предоставить следующие два значения из столбца JSON Data
:
- Страна или регион, где производится продукт.
- себестоимость производства товара.
В этом примере вычисляемые столбцы MadeIn
и Cost
обновляются каждый раз, когда изменяется документ JSON, сохраненный в столбце Data
.
DROP TABLE IF EXISTS xtp.Product;
GO
CREATE TABLE xtp.Product (
ProductID INT PRIMARY KEY NONCLUSTERED,
Name NVARCHAR(400) NOT NULL,
Price FLOAT,
Data NVARCHAR(4000),
MadeIn AS CAST(JSON_VALUE(Data, '$.MadeIn') AS NVARCHAR(50)) PERSISTED,
Cost AS CAST(JSON_VALUE(Data, '$.ManufacturingCost') AS FLOAT) PERSISTED
)
WITH (MEMORY_OPTIMIZED = ON);
GO
Индексирование значений в столбцах JSON
Значения в столбцах JSON можно индексировать с помощью индексов, оптимизированных для памяти. Индексируемые значения JSON должны быть строго типизированными и предоставленными с помощью вычисляемых столбцов, как описано в предыдущем примере.
Значения в столбцах JSON можно индексировать с помощью двух стандартных индексов — некластеризованного и хэш-индекса.
- Некластеризованные индексы оптимизируют запросы, которые выбирают диапазоны строк по какому-либо значению JSON или сортируют результаты по значениям JSON.
- Хэш-индексы оптимизируют запросы, которые выбирают одну или несколько записей, указывая точное значение для поиска.
В следующем примере создается таблица, которая предоставляет значения JSON с помощью двух вычисляемых столбцов. В примере создается некластеризованный индекс в одном значении JSON и хэш-индекс — в другом.
DROP TABLE IF EXISTS xtp.Product;
GO
CREATE TABLE xtp.Product (
ProductID INT PRIMARY KEY NONCLUSTERED,
Name NVARCHAR(400) NOT NULL,
Price FLOAT,
Data NVARCHAR(4000),
MadeIn AS CAST(JSON_VALUE(Data, '$.MadeIn') AS NVARCHAR(50)) PERSISTED,
Cost AS CAST(JSON_VALUE(Data, '$.ManufacturingCost') AS FLOAT) PERSISTED,
INDEX [idx_Product_MadeIn] NONCLUSTERED (MadeIn)
)
WITH (MEMORY_OPTIMIZED = ON);
GO
ALTER TABLE Product ADD INDEX [idx_Product_Cost] NONCLUSTERED HASH (Cost)
WITH (BUCKET_COUNT = 20000);
Компиляция запросов JSON в собственном коде
Если процедуры, функции и триггеры содержат запросы, которые используют встроенные функции JSON, компиляция в машинный код повышает производительность этих запросов и снижает количество циклов ЦП, необходимых для их выполнения.
В следующем примере показана скомпилированная в собственном коде процедура, использующая несколько функций JSON: JSON_VALUE
, OPENJSON
и JSON_MODIFY
.
CREATE PROCEDURE xtp.ProductList (@ProductIds NVARCHAR(100))
WITH SCHEMABINDING, NATIVE_COMPILATION
AS BEGIN
ATOMIC WITH (TRANSACTION ISOLATION LEVEL = snapshot, LANGUAGE = N'English')
SELECT ProductID,
Name,
Price,
Data,
Tags,
JSON_VALUE(data, '$.MadeIn') AS MadeIn
FROM xtp.Product
INNER JOIN OPENJSON(@ProductIds)
ON ProductID = value
END;
GO
CREATE PROCEDURE xtp.UpdateProductData (
@ProductId INT,
@Property NVARCHAR(100),
@Value NVARCHAR(100)
)
WITH SCHEMABINDING, NATIVE_COMPILATION
AS BEGIN
ATOMIC WITH (TRANSACTION ISOLATION LEVEL = snapshot, LANGUAGE = N'English')
UPDATE xtp.Product
SET Data = JSON_MODIFY(Data, @Property, @Value)
WHERE ProductID = @ProductId;
END
GO
Следующие шаги
Наглядные инструкции по встроенной поддержке JSON в SQL Server и базе данных SQL Azure см. в следующих видео.
- JSON as a bridge between NoSQL and relational worlds (JSON как мост между NoSQL и реляционными решениями)