WHERE子句在主键字段上的行为

时间:2017-06-30 05:31:08

标签: sql postgresql

select * from table where username="johndoe"

在Postgres中,如果用户名不是主键,我知道它会遍历所有记录。

但是如果它是主键字段,上述SQL语句将遍历整个表,或者在用户名匹配后立即终止。换句话说,“where”在主键列上运行时是否有不同的行为?

1 个答案:

答案 0 :(得分:0)

当这些列用作过滤谓词时,主键(以及所有索引的列)利用索引,例如WHEREJOIN...ON子句。

作为一个真实世界的例子,我的应用程序有一个名为Log_Games的表,它是一个包含数百万行,ID作为主键的表,以及许多其他非索引列,例如为ParsedAt。比较以下内容:

INDEXED QUERY

EXPLAIN ANALYZE
SELECT *
FROM "Log_Games"
WHERE "ID" = 792046

索引查询计划

Index Scan using "Log_Games_pkey" on "Log_Games"  (cost=0.43..8.45 rows=1 width=4190) (actual time=0.024..0.024 rows=1 loops=1)
  Index Cond: ("ID" = 792046)
Planning time: 1.059 ms
Execution time: 0.066 ms

非索引查询

EXPLAIN ANALYZE
SELECT *
FROM "Log_Games"
WHERE "ParsedAt" = '2015-05-07 07:31:24+00'

非指数查询计划

Seq Scan on "Log_Games"  (cost=0.00..141377.34 rows=18 width=4190) (actual time=0.013..793.094 rows=1 loops=1)
  Filter: ("ParsedAt" = '2015-05-07 07:31:24+00'::timestamp with time zone)
  Rows Removed by Filter: 1924676
Planning time: 0.794 ms
Execution time: 793.135 ms

带有indexed子句的查询使用索引Log_Games_pkey,从而导致查询以0.066ms的速度执行。带有非索引子句的查询将恢复为顺序扫描,这意味着它从表的开始到结束,以查看哪些列匹配,这是一个导致执行时间耗尽到793.135ms的操作。

网上有很多好的资源可以帮助您阅读执行计划并决定何时需要支持索引。一个好的起点是PostgreSQL文档: https://www.postgresql.org/docs/9.6/static/using-explain.html