Skip to main content

CREATE INDEX

使用 CREATE INDEX 命令在表或物化视图上创建索引。

关于索引

什么是索引?

数据库中的索引旨在提高数据库管理系统(DBMS)从表或物化视图中定位和检索所需数据的速度。通常在表中的一个或多个列上创建索引,可以极大地提高查询的性能,特别是对于大数据量或频繁访问的表。索引通常在非主键列上创建,以加快对这些列进行点查询的速度。

使用索引的好处

总体而言,使用索引可以显著提高系统的性能和效率。

何时使用索引

索引对于优化从大数据集中检索少量记录的查询性能特别有用。在 RisingWave 中,索引能加快批处理查询的速度。

句法

CREATE INDEX index_name ON object_name ( index_column [ ASC | DESC ], [, ...] )
[ INCLUDE ( include_column [, ...] ) ]
[ DISTRIBUTED BY ( distributed_column [, ...] ) ];

参数

参数或子句描述
index_name要创建的索引的名称。
object_name在其中创建索引的表或物化视图的名称。
index_column创建索引的列的名称。
DESC降序排列返回的数据。
INCLUDE 子句指定要包含在索引中作为非键列的列。
  • 索引查询可以返回非键列的值,而无需访问索引表,从而提高性能。
  • 如果省略 INCLUDE 子句,表或物化视图的所有列都将被索引。建议在 RisingWave 中这样做。
  • 如果只想包含 index_column,请使用 CREATE INDEX ON object_name(index_column) INCLUDE(index_column);
  • 更多信息,请参阅 如何决定包含哪些列
DISTRIBUTED BY 子句指定索引分布键。
  • 作为分布式数据库,RisingWave 将数据分布在多个节点上。创建索引时,分布键用于确定数据应如何在这些节点上分布。
  • 如果省略 DISTRIBUTED BY 子句,则第一个索引列将用作默认分布键。
  • distributed_column 必须是 index_column 的前缀。
  • 更多信息,请参阅 如何确定索引分布键

示例

让我们创建两个表,customersorders

CREATE TABLE customers (
c_custkey INTEGER,
c_name VARCHAR,
c_address VARCHAR,
c_nationkey INTEGER,
c_phone VARCHAR,
c_acctbal NUMERIC,
c_mktsegment VARCHAR,
c_comment VARCHAR,
PRIMARY KEY (c_custkey)
);

CREATE TABLE orders (
o_orderkey BIGINT,
o_custkey INTEGER,
o_orderstatus VARCHAR,
o_totalprice NUMERIC,
o_orderdate DATE,
o_orderpriority VARCHAR,
o_clerk VARCHAR,
o_shippriority INTEGER,
o_comment VARCHAR,
PRIMARY KEY (o_orderkey)
);

如果想加快通过电话号码获取客户记录的查询速度,可以在 customers 表中的 c_phone 列上构建索引。

CREATE INDEX idx_c_phone on customers(c_phone);

SELECT * FROM customers where c_phone = '123456789';

SELECT * FROM customers where c_phone in ('123456789', '987654321');

如果想加快通过客户键获取客户所有订单的查询速度,可以在 orders 表中的 o_custkey 列上构建索引。

CREATE INDEX idx_o_custkey ON orders(o_custkey);

SELECT * FROM customers JOIN orders ON c_custkey = o_custkey
WHERE c_phone = '123456789';

如何决定包含哪些列?

默认情况下,如果省略 INCLUDE 子句,RisingWave 会创建一个包含表或物化视图所有列的索引。这与标准的 PostgreSQL 有所不同。为什么呢?RisingWave 作为云原生流数据库,与 PostgreSQL 有几大不同之处,包括使用对象存储来实现更具成本效益的存储,以及希望让索引创建对于不熟悉数据库系统的用户来说尽可能简单。通过包含所有列,RisingWave 可确保索引涵盖查询涉及的所有列,从而无需进行主表查询。而在云环境中,由于网络通信的原因,主表查询可能会更慢。但是,RisingWave 仍为希望使用 INCLUDE 子句的用户提供了仅包含特定列的选项。

例如:

如果查询仅访问特定列,可以创建一个仅包含这些列的索引。RisingWave 优化器将自动为查询选择适当的索引。

-- 创建仅包含必要列的索引
CREATE INDEX idx_c_phone1 ON customers(c_phone) INCLUDE (c_name, c_address);

-- RisingWave 将自动使用索引 idx_c_phone1 进行以下查询,因为它仅访问了索引列。
SELECT c_name, c_address FROM customers WHERE c_phone = '123456789';
tip

您可以使用 EXPLAIN 命令查看执行计划。

如何确定索引分布键?

如果省略 distributed_column 子句,RisingWave 默认使用第一个索引列作为 DISTRIBUTED BY。RisingWave 将数据分布到多个节点上,并使用 distributed_column 基于索引确定如何分布数据。如果您的查询打算使用索引,但只提供了 index_column 的前缀,那么 RisingWave 可能无法确定从哪个节点访问索引数据。要解决这个问题,可以自行指定 distributed_column,确保这些列是 index_column 的前缀。

例如:

-- 创建具有指定分布列的索引
CREATE INDEX idx_c_phone2 ON customers(c_name, c_nationkey) DISTRIBUTED BY (c_name);

SELECT * FROM customers WHERE c_name = 'Alice';

表达式上的索引

RisingWave 支持在表达式上创建索引。通常,表达式上的索引用于改进常用表达式的查询性能。要在表达式上创建索引,请使用以下句法:

CREATE INDEX index_name ON object_name (expression(column_name));

例如,如果您经常执行以下查询:

SELECT * FROM people WHERE (first_name || ' ' || last_name) = 'John Smith';

那么您可能希望创建以下索引以改进此类查询的性能:

CREATE INDEX people_names ON people ((first_name || ' ' || last_name));

另请参阅

DROP INDEX — 移除在表或物化视图上构建的索引。