分析PostgreSQL执行计划

分析PostgreSQL执行计划,postgresql,query-performance,Postgresql,Query Performance,我试图了解PostgreSQL如何使用索引以及它们的执行计划 我执行了下面的查询 EXPLAIN(VERBOSE,ANALYZE) SELECT SUM("Orders"."order_subtotal_net_after_discount") AS "Total sum of Order Subtotal Net After Discount" FROM "ol"."orders_test" AS "Orders" LEFT OUTER JOIN "ol"."ga_transactions"

我试图了解PostgreSQL如何使用索引以及它们的执行计划

我执行了下面的查询

EXPLAIN(VERBOSE,ANALYZE)
SELECT SUM("Orders"."order_subtotal_net_after_discount") AS "Total sum of Order Subtotal Net After Discount"
FROM "ol"."orders_test" AS "Orders"
LEFT OUTER JOIN "ol"."ga_transactions" AS "Ga Transactions" ON "Ga Transactions"."transaction_id" = "Orders"."order_number"
WHERE ( to_char(created_at_order,'YYYY-MM-DD')=to_char(now(),'YYYY-MM-DD')
       AND "Orders"."order_state_2"<>'canceled'
      AND "Orders"."order_state_2" <> 'pending_payment'
      AND "Orders"."order_state_1" <> 'canceled'
      AND "Orders"."order_state_1" <> 'pending_payment'    
      AND "Orders"."order_state_1" <> 'closed'
      AND "Orders"."order_state_2" <> 'closed'
       )

不需要在索引中包含所有列。索引用于快速查找几行。并不是什么灵丹妙药能让一切突然变得更快。如果在索引中包含所有表列,则扫描索引所需的时间与执行Seq扫描所需的时间相同

您肯定要按顺序创建索引

create index on orders_test (created_at_order);
但是,您的表达式
to_char(按'YYYY-MM-DD'顺序创建)
将不会使用该索引。最好的办法是改变你的状况:

where created_at_order >= current_date and created_at_order < current_date + 1
为日期值编制索引还有一个优点,即索引较小。日期只需要4个字节,而字符串2019-10-15需要10个字节的存储空间

然后,以下内容将使用该索引:

where created_at_order::date = current_date
如果对状态列的附加限制进一步减少了行,则可以使用筛选索引:

create index on orders_test ( (created_at_order::date) )
WHERE order_state_2 <>'canceled'
  AND order_state_2  <> 'pending_payment'
  AND order_state_1  <> 'canceled'
  AND order_state_1  <> 'pending_payment'    
  AND order_state_1  <> 'closed'
  AND order_state_2  <> 'closed';
在订单上创建索引\u测试((在订单::日期创建))
其中订单状态为“已取消”
订单状态为“待付款”
订单状态为“已取消”
订单状态为“待付款”
订单状态为“关闭”
和命令状态2“关闭”;
这将使索引更小,并更快地在索引中查找行。但是,该索引将不再用于不包含这些条件的查询

如果您没有一直使用所有这些条件,则可以将它们减少为您一直使用的条件


如果这些附加条件没有真正减少行数,因为“created today”上的条件已经非常严格,那么您可以忽略它们。

否不需要在索引中包含所有列。索引用于快速查找几行。并不是什么灵丹妙药能让一切突然变得更快。如果在索引中包含所有表列,则扫描索引所需的时间与执行Seq扫描所需的时间相同

您肯定要按顺序创建索引

create index on orders_test (created_at_order);
但是,您的表达式
to_char(按'YYYY-MM-DD'顺序创建)
将不会使用该索引。最好的办法是改变你的状况:

where created_at_order >= current_date and created_at_order < current_date + 1
为日期值编制索引还有一个优点,即索引较小。日期只需要4个字节,而字符串2019-10-15需要10个字节的存储空间

然后,以下内容将使用该索引:

where created_at_order::date = current_date
如果对状态列的附加限制进一步减少了行,则可以使用筛选索引:

create index on orders_test ( (created_at_order::date) )
WHERE order_state_2 <>'canceled'
  AND order_state_2  <> 'pending_payment'
  AND order_state_1  <> 'canceled'
  AND order_state_1  <> 'pending_payment'    
  AND order_state_1  <> 'closed'
  AND order_state_2  <> 'closed';
在订单上创建索引\u测试((在订单::日期创建))
其中订单状态为“已取消”
订单状态为“待付款”
订单状态为“已取消”
订单状态为“待付款”
订单状态为“关闭”
和命令状态2“关闭”;
这将使索引更小,并更快地在索引中查找行。但是,该索引将不再用于不包含这些条件的查询

如果您没有一直使用所有这些条件,则可以将它们减少为您一直使用的条件


如果这些附加条件并没有真正减少行数,因为“created today”(今天创建)上的条件已经非常严格,那么您可以忽略它们。

您使用
created\u at\u order
作为时间戳创建了索引,但在
中使用了函数转换和比较字符串。
我建议您将
WHERE
小条款编辑为如下内容:

WHERE created_at_order BETWEEN now() AND TIMESTAMP 'today'

您使用按顺序创建的
作为时间戳创建索引,但在
中使用函数转换和比较字符串。
我建议您将
WHERE
小条款编辑为如下内容:

WHERE created_at_order BETWEEN now() AND TIMESTAMP 'today'

你总是使用那些'order_state…``条件吗?@a_horse_和'u no_name是的,在大多数查询中,这个条件都会存在。什么数据类型是按顺序创建的?
?数据类型是“timestamp without timezone”,但大多数情况下是使用转换为\u CHAR()函数获取所需的日期格式。您是否总是使用那些'order\u state…``条件?@a\u horse\u和\u no\u name是的,在大多数查询中,此条件都会存在。按顺序创建的数据类型是什么?
?数据类型是“没有时区的时间戳”,但大多数情况下将其转换为\u CHAR()函数获取所需的日期格式。非常感谢您的简要解释,我将按照您提到的更改查询并创建索引。因此,INCLUDE列不必添加任何内容作为INCLUDE列?
INCLUDE
并不是必需的。您可能需要在两列上创建索引,例如
(按订单创建,订单编号)
(按订单创建::日期,订单编号)
,因为加入时使用了
订单编号
。非常感谢您的简要解释,我将更改查询并创建您提到的索引。因此,INCLUDE列不必添加任何内容作为INCLUDE列?
INCLUDE
并不是必需的。您可能希望在两列上创建索引,例如
(按订单创建,订单编号)
(按订单创建::日期,订单编号)
,因为
订单编号
用于联接。