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 子句 | 指定要包含在索引中作为非键列的列。
|
DISTRIBUTED BY 子句 | 指定索引分布键。
|
示例
让我们创建两个表,customers
和 orders
。
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';
您可以使用 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
— 移除在表或物化视图上构建的索引。