索引是用于'外部'和'内部'的嵌套选择中的子句吗?

Dmi*_*kin 2 sql postgresql indexing select

面临在选择条件的地方使用列别名的需要.找到可行的解决方案在这里.

假设我们有一对一的关系(用户到角色),我们希望获得如下结果:

SELECT u.name AS u_name, r.name AS r_name
FROM users AS u
  INNER JOIN roles AS r
    ON u.role_id = r.role_id
WHERE u.name = 'John'
Run Code Online (Sandbox Code Playgroud)

我们有相应的idex user.name(仅举例).

如果运行此查询EXPLAIN,则显示选择期间使用的所有索引(包括名称索引).

现在,因为我们想在WHERE子句中使用别名,基于提出的解决方案,我们可以重写查询:

SELECT * FROM (
  SELECT u.name AS u_name, r.name AS r_name
  FROM users AS u
    INNER JOIN roles AS r
      ON u.role_id = r.role_id
) AS temp
WHERE u_name = 'John'
Run Code Online (Sandbox Code Playgroud)

如您所见,WHERE嵌套选择中没有子句.运行此查询EXPLAIN会得到相同的结果(只是承认,我不是分析'解释'结果的专家,但仍然):

  • 相同的索引
  • 相同的成本
  • 类似的执行时间

我对此结果感到有点困惑:确信至少不会使用用户名索引.

Q1: postgres是否以这种方式使用索引?

Q2:是否存在性能问题?

wil*_*ser 5

子查询不是必需的,因此可以展开/折叠.

以下查询将生成一个平面计划(并且索引不相关)


\i tmp.sql

CREATE TABLE t
        (a integer not null primary key
        );

insert into t(a)
select v from generate_series(1,10000) v
        ;

ANALYZE t;

EXPLAIN
SELECT * from (
        select d AS e from (
                select c as d from (
                        select b AS c from (
                                select a AS b from t
                                        ) s
                                ) r
                        ) q
                ) p
where e =95
        ;
Run Code Online (Sandbox Code Playgroud)

结果计划:


DROP SCHEMA
CREATE SCHEMA
SET
CREATE TABLE
INSERT 0 10000
ANALYZE
                             QUERY PLAN                              
---------------------------------------------------------------------
 Index Only Scan using t_pkey on t  (cost=0.17..2.38 rows=1 width=4)
   Index Cond: (a = 95)
(2 rows)
Run Code Online (Sandbox Code Playgroud)

在OP的片段中,最里面的查询(表表达式)是一个双表连接,但机制是相同的:所有外层都可以剥离(并重命名结果列)

是的:连接将受益于连接字段的索引,最终也可以使用索引.