为什么在查询中小于(<)比大于(>)具有更好的性能?

时间:2020-09-01 02:20:07

标签: postgresql

在以下查询中,您将看到使用<运算符的查询仅花费0.007s,而使用>运算符的查询花费0.474s。那是巨大的区别。会发生什么事?

postgresql> SHOW server_version;
+------------------+
| server_version   |
|------------------|
| 9.4.17           |
+------------------+
SHOW
Time: 0.006s

postgresql> \d msg
+------------------+-----------------------------+-------------------------------------------------------------+
| Column           | Type                        | Modifiers                                                   |
|------------------+-----------------------------+-------------------------------------------------------------|
| id               | bigint                      |  not null default nextval('msg_id_seq'::regclass) |
| content          | text                        |  default ''::text                                           |
... ...
| created_at       | timestamp without time zone |  default timezone('UTC'::text, now())                       |
+------------------+-----------------------------+-------------------------------------------------------------+
Indexes:
    "msg_pkey" PRIMARY KEY, btree (id)
    "ix_msg_created_at" btree (created_at)

Time: 0.013s

postgresql> SELECT id FROM msg WHERE created_at < '2020-08-27' ORDER BY id desc LIMIT 1;
+--------+
| id     |
|--------|
| 973604 |
+--------+
SELECT 1
Time: 0.007s

postgresql> SELECT id FROM msg WHERE created_at > '2020-08-27' ORDER BY id LIMIT 1;
+--------+
| id     |
|--------|
| 973605 |
+--------+
SELECT 1
Time: 0.474s

postgresql> SELECT count(*) FROM msg WHERE created_at < '2020-08-27';
+---------+
| count   |
|---------|
| 967498  |
+---------+
SELECT 1
Time: 0.509s

postgresql> SELECT count(*) FROM msg WHERE created_at > '2020-08-27';
+---------+
| count   |
|---------|
| 1089    |
+---------+
SELECT 1
Time: 0.007s

postgresql> EXPLAIN ANALYZE SELECT id FROM msg WHERE created_at < '2020-08-27' ORDER BY id desc LIMIT 1;
+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| QUERY PLAN                                                                                                                                                 |
|------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Limit  (cost=0.43..0.53 rows=1 width=8) (actual time=0.770..0.770 rows=1 loops=1)                                                                          |
|   ->  Index Scan Backward using msg_pkey on msg  (cost=0.43..114629.92 rows=1092141 width=8) (actual time=0.770..0.770 rows=1 loops=1) |
|         Filter: (created_at < '2020-08-27 00:00:00'::timestamp without time zone)                                                                          |
|         Rows Removed by Filter: 1103                                                                                                                       |
| Planning time: 0.110 ms                                                                                                                                    |
| Execution time: 0.782 ms                                                                                                                                   |
+------------------------------------------------------------------------------------------------------------------------------------------------------------+
EXPLAIN
Time: 0.008s

postgresql> EXPLAIN ANALYZE SELECT id FROM msg WHERE created_at > '2020-08-27' ORDER BY id LIMIT 1;
+----------------------------------------------------------------------------------------------------------------------------------------------------+
| QUERY PLAN                                                                                                                                         |
|----------------------------------------------------------------------------------------------------------------------------------------------------|
| Limit  (cost=0.43..44.58 rows=1 width=8) (actual time=481.168..481.169 rows=1 loops=1)                                                             |
|   ->  Index Scan using msg_pkey on msg  (cost=0.43..114629.92 rows=2596 width=8) (actual time=481.166..481.166 rows=1 loops=1) |
|         Filter: (created_at > '2020-08-27 00:00:00'::timestamp without time zone)                                                                  |
|         Rows Removed by Filter: 967498                                                                                                             |
| Planning time: 0.124 ms                                                                                                                            |
| Execution time: 481.184 ms                                                                                                                         |
+----------------------------------------------------------------------------------------------------------------------------------------------------+
EXPLAIN
Time: 0.489s

更新以添加行数(2020-09-01):

  • 2020年8月27日之后创建的行数为1089。
  • 2020年8月27日之前创建的行数为967498。

更新以添加查询计划(2020-09-01)。

  • 似乎两个查询都使用索引msg_pkey而不是ix_msg_created_atRows Removed by Filter的差异可以解释性能差异。

1 个答案:

答案 0 :(得分:2)

EXPLAIN的输出所示,似乎两个查询都扫描索引msg_pkey而不是ix_msg_created_at。如图Rows Removed by Filter所示,使用>运算符的查询扫描967498行,而使用<运算符的查询仅扫描1103行。这应该可以解释巨大的性能差异。

感谢所有帮助和建议。