在 WHERE 子句中使用的所有列上创建索引是一个好习惯吗

Sac*_*tre 2 postgresql indexing query-optimization cpu-usage timescaledb

该表存储时间序列数据并包含大约 15 列。我想优化SELECT在 3 列上有过滤器的查询

SELECT * FROM TABLE_1
WHERE COL_1 = ? 
  AND COL_2 = ? 
  AND COL_3 = ?
Run Code Online (Sandbox Code Playgroud)

COL_1在和上创建了 2 个索引COL_2,但在 上没有创建COL_3。当 RPS(每秒请求数)约为 1K 时,数据库 CPU 峰值达到100% 。

数据库配置是

  1. 8 个 CPU
  2. 16 GB 内存
  3. 250 GB 存储空间

由于没有索引,查询处理是否更多COL_3?在子句中使用的每个列上创建索引是一个好习惯吗WHERE

O. *_*nes 10

在 WHERE 子句中使用的所有列上创建索引是一个好习惯吗?

在 WHERE 子句中提到的所有列上创建单列索引并不是一个好习惯。这些索引对您的查询没有太大帮助,并且在您执行 INSERT 和 UPDATE 操作时它们会花费时间和 IO。

创建与大容量查询的 WHERE 子句相匹配的多列索引是一种很好的做法。

您的查询样本

SELECT * FROM TABLE_1
WHERE COL_1 = ? 
  AND COL_2 = ? 
  AND COL_3 = ?
Run Code Online (Sandbox Code Playgroud)

将受益于 的 BTREE 索引(COL_1, COL_2, COL_3)。postgresql 可以随机访问表中与 WHERE 子句匹配的第一行的索引,然后通过扫描索引检索行。

如果您的查询是

SELECT * FROM TABLE_1
WHERE COL_1 = ? 
  AND COL_TIME >= ? 
  AND COL_3 = ?
Run Code Online (Sandbox Code Playgroud)

你想要一个关于 的索引(COL_1, COL_3, COL_TIME)。同样,postgresql 可以随机访问第一个符合条件的行的索引,然后顺序扫描索引,直到到达最后一个符合条件的行。将相等匹配列首先放入索引中,然后是范围匹配 ( COL_TIME >= ?) 列。

设计您的索引以匹配

  1. 您的数据库对主键和其他约束的要求。
  2. 您的大量查询。

仅仅在许多列上放置单列索引是一个严重的错误。有时问我怎么知道这一点。;-)

当您第一次开始使用索引时,它可能看起来很神秘。Marcus Winand 的书https://use-the-index-luke.com/是开始学习的好地方。