Sdílet prostřednictvím


Optimalizace zpracování JSON pomocí OLTP v paměti

Platí pro: SQL Server 2017 (14.x) a novější verze Azure SQL DatabaseAzure SQL Managed InstanceSQL databáze v Microsoft Fabric

SQL Server a Azure SQL Database umožňují pracovat s textem formátovaným jako JSON. Pokud chcete zvýšit výkon dotazů, které zpracovávají data JSON, můžete dokumenty JSON ukládat do tabulek optimalizovaných pro paměť pomocí standardních řetězců sloupců (nvarchar typu). Ukládání dat JSON v tabulkách optimalizovaných pro paměť zvyšuje výkon dotazů pomocí přístupu k datům v paměti bez uzamčení.

Ukládání JSON v tabulkách optimalizovaných pro paměť

Následující příklad ukazuje tabulku Product optimalizovanou pro paměť se dvěma sloupci JSON, Tags a 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

Optimalizace zpracování JSON s využitím dalších funkcí v paměti

Funkce JSON můžete plně integrovat s existujícími technologiemi OLTP v paměti. Můžete například provést následující akce:

Ověření sloupců JSON

Můžete přidat nativně zkompilovaná omezení CHECK, která ověřují obsah dokumentů JSON uložených ve sloupci řetězce, abyste zajistili správné formátování textu JSON uloženého v tabulkách optimalizovaných pro paměť.

Následující příklad vytvoří tabulku Product se sloupcem JSON Tags. Sloupec Tags má omezení CHECK, které používá funkci ISJSON k ověření textu JSON ve sloupci.

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

Můžete také přidat nativně zkompilované omezení CHECK do existující tabulky, která obsahuje sloupce JSON.

ALTER TABLE xtp.Product
    ADD CONSTRAINT [Data should be JSON]
        CHECK (ISJSON(Data)=1);

Zveřejnění hodnot JSON pomocí počítaných sloupců

Počítané sloupce umožňují zveřejnit hodnoty z textu JSON a přistupovat k těmto hodnotám bez opětovného načtení hodnoty z textu JSON a bez opětovné analýzy struktury JSON. Hodnoty vystavené tímto způsobem jsou silně typované a fyzicky se uchovávají ve vypočítaných sloupcích. Přístup k hodnotám JSON pomocí trvalých počítaných sloupců je rychlejší než přímý přístup k hodnotám v dokumentu JSON.

Následující příklad ukazuje, jak z Data sloupce JSON zveřejnit následující dvě hodnoty:

  • Země/oblast, kde se produkt vyrábí.
  • Výrobní náklady na produkt.

V tomto příkladu se vypočítané sloupce MadeIn a Cost aktualizují při každé změně dokumentu JSON uloženého ve sloupci 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

Hodnoty indexu ve sloupcích JSON

Hodnoty ve sloupcích JSON můžete indexovat pomocí indexů optimalizovaných pro paměť. Hodnoty JSON, které jsou indexované, musí být vystavené a silně zadané pomocí vypočítaných sloupců, jak je popsáno v předchozím příkladu.

Hodnoty ve sloupcích JSON je možné indexovat pomocí standardních indexů NONCLUSTERED i HASH.

  • Neklastrované indexy optimalizují dotazy, které vybírají rozsahy řádků podle určité hodnoty JSON nebo seřazují výsledky podle hodnot JSON.
  • Indexy HASH optimalizují dotazy, které vyberou jeden řádek nebo několik řádků, zadáním přesné hodnoty, kterou chcete najít.

Následující příklad vytvoří tabulku, která zveřejňuje hodnoty JSON pomocí dvou počítaných sloupců. Příklad vytvoří index NONCLUSTERED pro jednu hodnotu JSON a index HASH na druhé.

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

Nativní kompilace dotazů JSON

Pokud vaše procedury, funkce a triggery obsahují dotazy, které používají integrované funkce JSON, nativní kompilace zvyšuje výkon těchto dotazů a snižuje cykly procesoru potřebné ke spuštění.

Následující příklad ukazuje nativně zkompilovaný postup, který používá několik funkcí JSON: JSON_VALUE, OPENJSONa 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

Vizuální úvod k integrované podpoře JSON najdete v následujících videích: