如何提高具有 OPENJSON 来过滤 JSON 数组属性的 T-SQL 查询的性能

Ner*_*ero 4 sql-server performance json

我有一个包含 JSON 数组列 ( nvarchar(max)) 的表,有数百万行,预计将来会有数十亿行。

表结构是这样的:

[SnapshotId] - PK,
[BuildingId],
......................
[MeterData],
Run Code Online (Sandbox Code Playgroud)

MeterData 包含这样的 Json 数组:

[{
    "MeterReadingId": 0,
    "BuildingMeterId": 1,
    "Value": 1.0,   
}, {
    "MeterReadingId": 0,
    "BuildingMeterId": 2,
    "Value": 1.625, 
}]
Run Code Online (Sandbox Code Playgroud)

我需要按“HourlySnapshot”表过滤,其中“BuildingMeterId = 255”是例如,写了下面的查询

SELECT * 
FROM [HourlySnapshot] h 
CROSS APPLY OPENJSON(h.MeterData) 
    WITH (BuildingMeterId int '$.BuildingMeterId') AS MeterDataJson
WHERE MeterDataJson.BuildingMeterId = 255
Run Code Online (Sandbox Code Playgroud)

工作正常,但由于解析 JSON,性能很差。我读到您可以通过创建索引来克服性能问题。我创建了一个如下所示的聚集索引

CREATE CLUSTERED INDEX CL_MeterDataModel 
    ON [HourlySnapshot] (MeterDataModel)
Run Code Online (Sandbox Code Playgroud)

但是在速度方面看不到任何改进。我做错了吗?什么是提高速度的最佳方法。

谢谢

尼禄无英雄

Joh*_*ven 5

计算列和索引的组合可能会有所帮助。

ALTER TABLE [HourlySnapshot]
ADD [BuildingMeterId] AS JSON_VALUE([MeterData], '$.BuildingMeterId');

CREATE NONCLUSTERED INDEX IX_ParsedBuildingMeterId ON [HourlySnapshot] (BuildingMeterId)
Run Code Online (Sandbox Code Playgroud)

这实际上会导致 SQL Server 在插入/更新时解析和索引值。读取时可以使用索引,不做全表扫描。