2

我有一个具有以下架构的 postgres 表

     Table "public.myTable"
  Column               |           Type           | Modifiers 
-----------             +--------------------------+-----------
 serial_number         | character varying(255)   | 
 name                  | character varying(255)   | 
 Designation           | character varying(255)   | 
 place                 | character varying(255)   | 
 timeOfJoining         | timestamp with time zone | 
 timeOfLeaving               | timestamp with time zone | 

Indexes:
    "name_Designation_place" btree (name, Designation, place)
    "Designation_place_name" btree (Designation, place, name)
    "Designation_name_place" btree (Designation, name, place)
    "timeOfJoining_timeOfLeaving" btree (timeOfJoining, timeOfLeaving)
    "timeOfJoining_timeOfLeaving" btree (timeOfJoining, timeOfLeaving)

现在,当我运行表单查询时:

explain analyze select place from myTable where Designation='Manager' and timeOfJoining>'1930-10-10';

我得到以下计划:

Index Scan using Designation_place_name on myTable  (cost=0.00..67701.36 rows=22043 width=27) (actual time=0.061..3.796 rows=3376 loops=1)
   Index Cond: ((relation)::text = 'Manager'::text)
   Filter: (timeOfJoining > '1930-10-10 00:00:00+05:53:20'::timestamp with time zone)
 Total runtime: 4.082 ms
(4 rows)

现在我无法理解查询计划是如何执行的。查询计划是否首先从 myTable 上的索引 Designation_place_name 检索序列号,然后转到 myTable 并获取行,然后在 timeOfJoining 上执行过滤

或者

查询计划是否同时获取索引 timeOfJoining_timeOfLeaving 和 Designation_place_name 然后执行连接,并且在此连接时完成过滤?

4

2 回答 2

1

查询计划是否同时获取索引 timeOfJoining_timeOfLeaving 和 Designation_place_name 然后执行连接,并且在此连接时完成过滤?

由于timeOfJoining_timeOfLeaving计划中未提及该索引,因此未使用该索引。就是这么简单。

Does the query plan first retrieve the serial_number from the index Designation_place_name on myTable and then goes to myTable and fetches the rows and then performs the filtering on timeOfJoining?

Mostly: Yes. But not the serial_number is used but an internal type of link. Besides of that minor point this is what the plan tells you.

于 2013-06-23T12:10:59.057 回答
1

This plan:

Index Scan using Designation_place_name on myTable  (cost=0.00..67701.36 rows=22043 width=27) (actual time=0.061..3.796 rows=3376 loops=1)
   Index Cond: ((relation)::text = 'Manager'::text)
   Filter: (timeOfJoining > '1930-10-10 00:00:00+05:53:20'::timestamp with time zone)
 Total runtime: 4.082 ms
(4 rows)

Basically means:

  1. Using the Designation_place_name index
  2. Find rows that fit the index condition relation = 'Manager'
  3. Keep only rows that match the timeOfJoining criteria

During step 2, disk pages are accessed "randomly", rather than sequentially, which is to say the index contains the address of matching rows on disk, and Postgres visits these addresses in the order indicated by the index. (This can be costly, btw. Sometimes, the planner will decide its cheaper to just read the entire table (seq scan) or batch fetch all rows on a page while ignoring the order indicated by the index (bitmap index scan).)

Note: there are no (table) joins in that query. Had there been one, you'd have seen extra indentation levels. Read them from most indented to least indented.

于 2013-06-23T12:12:24.697 回答