创建 JSON 索引(Transact-SQL)

适用于: SQL Server 2025 (17.x) 预览版

在 SQL Server 2025 (17.x) 预览版中的指定表和列上创建 JSON 索引。

JSON 索引:

  • 可以在表中有数据之前创建。
  • 可以通过指定限定的数据库名称在另一个数据库中的表上创建。
  • 要求表具有聚簇主键。
  • 不能在索引视图上指定。

注释

创建 JSON 索引目前为预览版,仅在 SQL Server 2025(17.x) 预览版中可用。

Transact-SQL 语法约定

语法

CREATE JSON INDEX name ON table_name (json_column_name)
  [ FOR ( sql_json_path [ , ...n ] ) ]
  [ WITH ( <json_index_option> [ , ...n ] ) ]
  [ ON { filegroup_name | "default" } ]
[ ; ]

<object> ::=
    { database_name.schema_name.table_name | schema_name.table_name | table_name }

<sql_json_path> ::=
    { character_string_literal }

<json_index_option> ::=
{
    FILLFACTOR = fillfactor
  | DROP_EXISTING = { ON | OFF }
  | ONLINE = OFF
  | ALLOW_ROW_LOCKS = { ON | OFF }
  | ALLOW_PAGE_LOCKS = { ON | OFF }
  | MAXDOP = max_degree_of_parallelism
  | DATA_COMPRESSION = { NONE | ROW | PAGE }
}

论据

索引名称

索引的名称。 索引名称在表中必须唯一,但不必在数据库中是唯一的。 索引名称必须遵循 标识符规则。

  • ON <对象> ( json_column_name

    指定要在其中创建索引的对象(数据库、架构或表),以及 json 列的名称。

  • json_column_name

    包含零个或多个指定 SQL/JSON 路径的 json 数据类型 table_name 列的名称。

  • sql_json_path

    需要从 json_column_name中提取和编制索引的 SQL/JSON 路径。 sql_json_path 的默认值是 $

    • 以递归方式从指定路径开始为所有键/值编制索引。
    • JSON 文档路径中最多支持 128 个级别。
    • 不允许重叠。

    例如, $.a$.a.b 引发错误,因为路径 $.a 以递归方式包括所有路径,并且用户意图尚不清楚。

ON filegroup_name

为指定文件组创建指定索引。 如果未指定任何位置且未对表进行分区,索引将使用与基础表相同的文件组。 文件组必须已存在。

在“默认”上

在默认文件组上创建指定的索引。

在此上下文中,术语默认值不是关键字。 它是默认文件组的标识符,必须按 In 或 in ON "default"ON [default]. 如果 "default" 已指定,则 QUOTED_IDENTIFIER 选项必须为 ON 当前会话。 这是默认设置。 有关详细信息,请参阅 SET QUOTED_IDENTIFIER

<object>:: =

需要索引的对象可以是完全限定或非完全限定的。

  • database_name

    数据库的名称。

  • schema_name

    表所属的架构的名称。

  • table_name

    要编制索引的表的名称。

FILLFACTOR = fillfactor

指定一个百分比,指示在数据库引擎创建或重新生成索引的过程中,应将每个索引页面的叶级填充到什么程度。 fillfactor 必须是一个从 1100 的整数值。 默认值为 0。 如果 fillfactor1000,则数据库引擎会创建索引,其中叶页被填满至容量。

注释

填充因子值 0100 在各个方面都是相同的。

FILLFACTOR 设置仅在创建或重新生成索引时应用。 数据库引擎并不会在页中动态保持指定的可用空间百分比。 若要查看填充因子设置,请使用 sys.indexes 目录视图。

创建一个FILLFACTOR小于100的聚集索引会影响数据占用的存储空间量,因为数据库引擎在创建聚集索引时会重新分发数据。

有关详细信息,请参阅 为索引指定填充因子

DROP_EXISTING = { ON |OFF }

指定删除并重新生成已存在的命名空间索引。 默认值为 OFF

  • 删除现有索引并重新生成。 指定的索引名称必须与当前现有索引相同;但是,可以修改索引定义。 例如,可以指定不同的列、排序顺序、分区方案或索引选项。

  • OFF

    如果指定的索引名称已存在,则会显示错误。

无法使用 DROP_EXISTING 更改索引类型。

ONLINE = OFF

指定基础表和关联的索引在索引作期间不能用于查询和数据修改。 在此版本的 SQL Server 中,JSON 索引不支持联机索引生成。 如果此选项设置为 ON JSON 索引,则会引发错误。 省略选项 ONLINE 或设置为 ONLINEOFF.

离线索引操作在创建、重建或删除 JSON 索引时,会获取表上的架构修改(Sch-M)锁。 这样可以防止所有用户在操作期间访问基础表。

在 SQL Server 中,并不是每个版本都支持联机索引操作。

有关 Windows 上 SQL Server 各版本支持的功能列表,请参阅:

ALLOW_ROW_LOCKS = { ON |OFF }

指定是否允许使用行锁。 默认值为 ON

  • 在访问索引时允许使用行锁。 数据库引擎确定何时使用行锁。

  • OFF

    不使用行锁。

ALLOW_PAGE_LOCKS = { ON |OFF }

指定是否允许页锁。 默认值为 ON

  • 开启

    在访问索引时允许使用页锁。 数据库引擎确定何时使用页锁。

  • OFF

    不使用页锁。

MAXDOP = max_degree_of_parallelism

覆盖 max degree of parallelism 配置选项在索引操作期间。 用于 MAXDOP 限制并行计划执行中使用的处理器数。 最大值为 64 个处理器。

重要

MAXDOP尽管此选项在语法上受支持,CREATE SPATIAL INDEX但目前始终只使用单个处理器。

max_degree_of_parallelism 可以是以下值之一。

价值 DESCRIPTION
1 取消生成并行计划。
>1 基于当前系统工作负荷,将并行索引操作中使用的最大处理器数限制为指定数量或更少。
0(默认值) 根据当前系统工作负荷使用实际的处理器数量或更少数量的处理器。

有关详细信息,请参阅 “配置并行索引作”。

并行索引操作并不适用于 SQL Server 的所有版本。

有关 Windows 上 SQL Server 各版本支持的功能列表,请参阅:

DATA_COMPRESSION = { NONE |ROW |PAGE }

确定索引使用的数据压缩级别。

  • 没有

    索引未对数据使用压缩

  • 索引对数据使用的行压缩

  • 索引对数据使用的页面压缩

注解

每个选项只能为每个 CREATE JSON INDEX 语句指定一次。 指定重复任意一个选项将会引发错误。

[ ON { filegroup_name |“default” } ]

如果为 JSON 索引指定文件组,则无论表的分区方案如何,索引都会放置在该文件组上。

有关创建索引的详细信息,请参阅 CREATE INDEX 中的“备注”部分。

JSON 索引支持的谓词

如果 JSON 列上存在一个 JSON 索引,则可以优化在表中 JSON 列中包含的 JSON 文档上的搜索操作。 JSON 索引用于各种基于 JSON 函数表达式的查询。

以下示例使用AdventureWorks2022数据库中的Sales.SalesOrderHeader表以及名为Infojson列。 将 Info 列创建为 json 类型。 还会在具有默认设置的 Info 列上创建 JSON 索引。 下面的代码示例演示了 CREATE JSON INDEX 该语句:

CREATE JSON INDEX sales_info_idx ON Sales.SalesOrderHeader(Info);

对于示例搜索表达式,请使用以下 JSON 文档作为数据:

销售订单号 信息
437 {"Customer":{"Name":"Kelsey Raje","ID":16517,"Type":"IN"},"Order":{"ID":43710,"Number":"SO43710","CreationDate":"2011-06-02T00:00:00","TotalDue":3953.9884}}
643 {"Customer":{"Name":"Aaron Campbell","ID":16167,"Type":"IN"},"Order":{"ID":64304,"Number":"SO64304","CreationDate":"2014-01-16T00:00:00","TotalDue":36.0230, "IsProcessed": true}}

JSON_PATH_EXISTS 函数

使用 JSON_PATH_EXISTS 函数测试 JSON 文档中是否存在指定的 SQL/JSON 路径。

该查询演示了如何通过使用 JSON 索引来优化 JSON_PATH_EXISTS 列:

SELECT COUNT(*)
FROM Sales.SalesOrderHeader
WHERE JSON_PATH_EXISTS(Info, '$.Order.IsProcessed') = 1;

谓词和以下运算符支持 JSON_PATH_EXISTS JSON 索引:

  • 比较运算符 (=
  • IS [NOT] NULL 谓词 (当前不支持)

JSON_VALUE函数

使用 JSON_VALUE 提取 JSON 文档中指定 SQL/JSON 路径中的 JSON 文本/标量值。 以下查询演示了如何使用 JSON 索引来优化 json 列中的 JSON_VALUE 表达式。

  • 在对象属性中搜索 JSON 字符串的相等性:

    SELECT COUNT(*)
    FROM Sales.SalesOrderHeader
    WHERE JSON_VALUE(Info, '$.Customer.Type') = 'IN';
    
  • 转换值为 int 数据类型后,执行对象属性中的 JSON 数字的相等性搜索:

    SELECT *
    FROM Sales.SalesOrderHeader
    WHERE JSON_VALUE(Info, '$.Customer.ID' RETURNING INT) = 16167;
    
  • 将值转换为 int 数据类型后,范围搜索对象属性中的 JSON 编号:

    SELECT *
    FROM Sales.SalesOrderHeader
    WHERE JSON_VALUE(Info, '$.Customer.ID' RETURNING INT) IN (16167, 16517);
    
  • 将值转换为 十进制 数据类型后,范围搜索对象属性中的 JSON 编号:

    SELECT *
    FROM Sales.SalesOrderHeader
    WHERE JSON_VALUE(Info, '$.Order.TotalDue RETURNING decimal(20, 4)) BETWEEN 1000 and 2000;
    

JSON 索引由 JSON_VALUE 谓词支持,以及以下运算符:

  • 比较运算符 (=
  • LIKE 谓词(当前不支持)
  • IS [NOT] NULL 谓词(当前不支持)

JSON_CONTAINS函数

JSON_CONTAINS函数支持在 JSON 文档中轻松搜索 JSON 值,如果 JSON 列上存在,则可以使用 JSON 索引。 此函数可用于测试 JSON 文档中指定的 SQL/JSON 路径中是否包含 JSON 标量值、对象或数组。 指定为 SQL 标量类型的搜索值根据现有的 SQL/JSON 类型转换进行转换。 这些规则在行为部分中定义。

要求

包含 JSON 列的表上必需有一个聚类键。 如果群集键不存在,则会引发错误。 聚类键限制为 31 列,索引键的最大大小应小于 128 字节。

权限

用户必须具有 ALTER 对表的权限,或者是 sysadmin 固定服务器角色的成员,或者 db_ddladmindb_owner 固定数据库角色的成员。

局限性

JSON 索引语句存在以下限制:

  • 只能在表中的 json 列上创建一个 JSON 索引。
  • 在表中最多可以创建 249 个 JSON 索引。 不支持在特定 JSON 列上创建多个 JSON 索引。
  • 无法在计算的 json 列上创建 JSON 索引。
  • 无法在视图、表值变量或内存优化表的 json 列上创建 JSON 索引。
  • JSON 索引只能以脱机方式创建或更改。
  • JSON 路径不能在索引定义中重叠。 例如, $a$a.b 重叠,不允许在 CREATE JSON INDEX 语句中。
  • 修改路径需要重新创建 JSON 索引。
  • 索引提示不支持 JSON 索引。
  • 不支持数据压缩选项。

例子

答: 在 JSON 列上创建 JSON 索引

以下示例创建一个名为包含 docs 类型列的表content。 然后,该示例在content列上创建 JSON 索引json_content_index。 该示例针对 JSON 文档的整个 JSON 文档或 JSON 文档中的所有 SQL/JSON 路径创建 json 索引。

DROP TABLE IF EXISTS docs;

CREATE TABLE docs (content JSON, id INT PRIMARY KEY);
CREATE JSON INDEX json_content_index ON docs(content);

答: 在具有特定路径的 JSON 列上创建 JSON 索引

以下示例创建一个名为包含 docs 类型列的表content。 然后,该示例在列content上创建 JSON 索引json_content_index。 此示例在 JSON 文档中的特定 SQL/JSON 路径上创建 json 索引。
该示例还将索引 FILLFACTOR 设置为 80

DROP TABLE IF EXISTS docs;

CREATE TABLE docs (content JSON, id INT PRIMARY KEY);

CREATE JSON INDEX json_content_index
    ON docs(content) FOR ('$.a', '$.b')
    WITH (FILLFACTOR = 80);