将ORDER BY添加到SQL查询会爆炸运行时

时间:2018-04-03 18:06:14

标签: sql postgresql performance sql-execution-plan postgresql-performance

当我添加ORDER BY时,我的查询执行时间会爆炸,我似乎无法得到它背后的推理。我认为在索引字段上订购应该很简单。

所以两个查询看起来像这样:

这个需要30-50秒:

EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS, FORMAT JSON)
SELECT * FROM "content_entry"
INNER JOIN "marketplace_review" ON ("content_entry"."id" = "marketplace_review"."entry_ptr_id")
INNER JOIN "marketplace_product" ON ("marketplace_review"."product_id" = "marketplace_product"."id")
WHERE ("content_entry"."type" = 3 AND "marketplace_product"."brand_id" = 750)
ORDER BY "content_entry"."timestamp" DESC
LIMIT 3

这个不到一秒钟

EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS, FORMAT JSON)
SELECT * FROM "content_entry"
INNER JOIN "marketplace_review" ON ("content_entry"."id" = "marketplace_review"."entry_ptr_id")
INNER JOIN "marketplace_product" ON ("marketplace_review"."product_id" = "marketplace_product"."id")
WHERE ("content_entry"."type" = 3 AND "marketplace_product"."brand_id" = 750)
LIMIT 3

订单的输出:

[
  {
    "Plan": {
      "Node Type": "Limit",
      "Parallel Aware": false,
      "Startup Cost": 1.43,
      "Total Cost": 98242.01,
      "Plan Rows": 3,
      "Plan Width": 385,
      "Actual Startup Time": 2668.251,
      "Actual Total Time": 45068.099,
      "Actual Rows": 3,
      "Actual Loops": 1,
      "Output": [""],
      "Shared Hit Blocks": 60929421,
      "Shared Read Blocks": 0,
      "Shared Dirtied Blocks": 0,
      "Shared Written Blocks": 0,
      "Local Hit Blocks": 0,
      "Local Read Blocks": 0,
      "Local Dirtied Blocks": 0,
      "Local Written Blocks": 0,
      "Temp Read Blocks": 0,
      "Temp Written Blocks": 0,
      "Plans": [
        {
          "Node Type": "Nested Loop",
          "Parent Relationship": "Outer",
          "Parallel Aware": false,
          "Join Type": "Inner",
          "Startup Cost": 1.43,
          "Total Cost": 29046467.49,
          "Plan Rows": 887,
          "Plan Width": 385,
          "Actual Startup Time": 2668.250,
          "Actual Total Time": 45068.095,
          "Actual Rows": 3,
          "Actual Loops": 1,
          "Output": [""],
          "Shared Hit Blocks": 60929421,
          "Shared Read Blocks": 0,
          "Shared Dirtied Blocks": 0,
          "Shared Written Blocks": 0,
          "Local Hit Blocks": 0,
          "Local Read Blocks": 0,
          "Local Dirtied Blocks": 0,
          "Local Written Blocks": 0,
          "Temp Read Blocks": 0,
          "Temp Written Blocks": 0,
          "Plans": [
            {
              "Node Type": "Nested Loop",
              "Parent Relationship": "Outer",
              "Parallel Aware": false,
              "Join Type": "Inner",
              "Startup Cost": 1.00,
              "Total Cost": 18561128.82,
              "Plan Rows": 17657640,
              "Plan Width": 389,
              "Actual Startup Time": 0.036,
              "Actual Total Time": 23010.813,
              "Actual Rows": 5636983,
              "Actual Loops": 1,
              "Output": [""],
              "Shared Hit Blocks": 29168382,
              "Shared Read Blocks": 0,
              "Shared Dirtied Blocks": 0,
              "Shared Written Blocks": 0,
              "Local Hit Blocks": 0,
              "Local Read Blocks": 0,
              "Local Dirtied Blocks": 0,
              "Local Written Blocks": 0,
              "Temp Read Blocks": 0,
              "Temp Written Blocks": 0,
              "Plans": [
                {
                  "Node Type": "Index Scan",
                  "Parent Relationship": "Outer",
                  "Parallel Aware": false,
                  "Scan Direction": "Backward",
                  "Index Name": "content_entry_d7e6d55b",
                  "Relation Name": "content_entry",
                  "Schema": "public",
                  "Alias": "content_entry",
                  "Startup Cost": 0.56,
                  "Total Cost": 5903549.69,
                  "Plan Rows": 24176239,
                  "Plan Width": 385,
                  "Actual Startup Time": 0.031,
                  "Actual Total Time": 5038.896,
                  "Actual Rows": 5636983,
                  "Actual Loops": 1,
                  "Output": [""],
                  "Filter": "(content_entry.type = 3)",
                  "Rows Removed by Filter": 1872638,
                  "Shared Hit Blocks": 6559529,
                  "Shared Read Blocks": 0,
                  "Shared Dirtied Blocks": 0,
                  "Shared Written Blocks": 0,
                  "Local Hit Blocks": 0,
                  "Local Read Blocks": 0,
                  "Local Dirtied Blocks": 0,
                  "Local Written Blocks": 0,
                  "Temp Read Blocks": 0,
                  "Temp Written Blocks": 0
                },
                {
                  "Node Type": "Index Scan",
                  "Parent Relationship": "Inner",
                  "Parallel Aware": false,
                  "Scan Direction": "Forward",
                  "Index Name": "marketplace_review_pkey",
                  "Relation Name": "marketplace_review",
                  "Schema": "public",
                  "Alias": "marketplace_review",
                  "Startup Cost": 0.44,
                  "Total Cost": 0.51,
                  "Plan Rows": 1,
                  "Plan Width": 8,
                  "Actual Startup Time": 0.002,
                  "Actual Total Time": 0.002,
                  "Actual Rows": 1,
                  "Actual Loops": 5636983,
                  "Output": [""],
                  "Index Cond": "(marketplace_review.entry_ptr_id = content_entry.id)",
                  "Rows Removed by Index Recheck": 0,
                  "Shared Hit Blocks": 22608853,
                  "Shared Read Blocks": 0,
                  "Shared Dirtied Blocks": 0,
                  "Shared Written Blocks": 0,
                  "Local Hit Blocks": 0,
                  "Local Read Blocks": 0,
                  "Local Dirtied Blocks": 0,
                  "Local Written Blocks": 0,
                  "Temp Read Blocks": 0,
                  "Temp Written Blocks": 0
                }
              ]
            },
            {
              "Node Type": "Index Scan",
              "Parent Relationship": "Inner",
              "Parallel Aware": false,
              "Scan Direction": "Forward",
              "Index Name": "marketplace_product_pkey",
              "Relation Name": "marketplace_product",
              "Schema": "public",
              "Alias": "marketplace_product",
              "Startup Cost": 0.43,
              "Total Cost": 0.58,
              "Plan Rows": 1,
              "Plan Width": 4,
              "Actual Startup Time": 0.003,
              "Actual Total Time": 0.003,
              "Actual Rows": 0,
              "Actual Loops": 5636983,
              "Output": ["marketplace_product.id"],
              "Index Cond": "(marketplace_product.id = marketplace_review.product_id)",
              "Rows Removed by Index Recheck": 0,
              "Filter": "(marketplace_product.brand_id = 750)",
              "Rows Removed by Filter": 1,
              "Shared Hit Blocks": 31761039,
              "Shared Read Blocks": 0,
              "Shared Dirtied Blocks": 0,
              "Shared Written Blocks": 0,
              "Local Hit Blocks": 0,
              "Local Read Blocks": 0,
              "Local Dirtied Blocks": 0,
              "Local Written Blocks": 0,
              "Temp Read Blocks": 0,
              "Temp Written Blocks": 0
            }
          ]
        }
      ]
    },
    "Planning Time": 1.493,
    "Triggers": [
    ],
    "Execution Time": 45068.146
  }
]

没有订单的那个输出:

[
  {
    "Plan": {
      "Node Type": "Limit",
      "Parallel Aware": false,
      "Startup Cost": 24.64,
      "Total Cost": 1780.29,
      "Plan Rows": 3,
      "Plan Width": 1412,
      "Actual Startup Time": 0.039,
      "Actual Total Time": 0.060,
      "Actual Rows": 3,
      "Actual Loops": 1,
      "Output": [""],
      "Shared Hit Blocks": 25,
      "Shared Read Blocks": 0,
      "Shared Dirtied Blocks": 0,
      "Shared Written Blocks": 0,
      "Local Hit Blocks": 0,
      "Local Read Blocks": 0,
      "Local Dirtied Blocks": 0,
      "Local Written Blocks": 0,
      "Temp Read Blocks": 0,
      "Temp Written Blocks": 0,
      "Plans": [
        {
          "Node Type": "Nested Loop",
          "Parent Relationship": "Outer",
          "Parallel Aware": false,
          "Join Type": "Inner",
          "Startup Cost": 24.64,
          "Total Cost": 527304.93,
          "Plan Rows": 901,
          "Plan Width": 1412,
          "Actual Startup Time": 0.038,
          "Actual Total Time": 0.059,
          "Actual Rows": 3,
          "Actual Loops": 1,
          "Output": [""],
          "Shared Hit Blocks": 25,
          "Shared Read Blocks": 0,
          "Shared Dirtied Blocks": 0,
          "Shared Written Blocks": 0,
          "Local Hit Blocks": 0,
          "Local Read Blocks": 0,
          "Local Dirtied Blocks": 0,
          "Local Written Blocks": 0,
          "Temp Read Blocks": 0,
          "Temp Written Blocks": 0,
          "Plans": [
            {
              "Node Type": "Nested Loop",
              "Parent Relationship": "Outer",
              "Parallel Aware": false,
              "Join Type": "Inner",
              "Startup Cost": 24.08,
              "Total Cost": 526285.64,
              "Plan Rows": 1249,
              "Plan Width": 1027,
              "Actual Startup Time": 0.028,
              "Actual Total Time": 0.033,
              "Actual Rows": 3,
              "Actual Loops": 1,
              "Output": [""],
              "Shared Hit Blocks": 10,
              "Shared Read Blocks": 0,
              "Shared Dirtied Blocks": 0,
              "Shared Written Blocks": 0,
              "Local Hit Blocks": 0,
              "Local Read Blocks": 0,
              "Local Dirtied Blocks": 0,
              "Local Written Blocks": 0,
              "Temp Read Blocks": 0,
              "Temp Written Blocks": 0,
              "Plans": [
                {
                  "Node Type": "Index Scan",
                  "Parent Relationship": "Outer",
                  "Parallel Aware": false,
                  "Scan Direction": "Forward",
                  "Index Name": "marketplace_product_521b20f5",
                  "Relation Name": "marketplace_product",
                  "Schema": "public",
                  "Alias": "marketplace_product",
                  "Startup Cost": 0.43,
                  "Total Cost": 761.18,
                  "Plan Rows": 189,
                  "Plan Width": 986,
                  "Actual Startup Time": 0.010,
                  "Actual Total Time": 0.010,
                  "Actual Rows": 1,
                  "Actual Loops": 1,
                  "Output": [""],
                  "Index Cond": "(marketplace_product.brand_id = 750)",
                  "Rows Removed by Index Recheck": 0,
                  "Shared Hit Blocks": 4,
                  "Shared Read Blocks": 0,
                  "Shared Dirtied Blocks": 0,
                  "Shared Written Blocks": 0,
                  "Local Hit Blocks": 0,
                  "Local Read Blocks": 0,
                  "Local Dirtied Blocks": 0,
                  "Local Written Blocks": 0,
                  "Temp Read Blocks": 0,
                  "Temp Written Blocks": 0
                },
                {
                  "Node Type": "Bitmap Heap Scan",
                  "Parent Relationship": "Inner",
                  "Parallel Aware": false,
                  "Relation Name": "marketplace_review",
                  "Schema": "public",
                  "Alias": "marketplace_review",
                  "Startup Cost": 23.65,
                  "Total Cost": 2771.16,
                  "Plan Rows": 939,
                  "Plan Width": 41,
                  "Actual Startup Time": 0.013,
                  "Actual Total Time": 0.017,
                  "Actual Rows": 3,
                  "Actual Loops": 1,
                  "Output": [""],
                  "Recheck Cond": "(marketplace_review.product_id = marketplace_product.id)",
                  "Rows Removed by Index Recheck": 0,
                  "Exact Heap Blocks": 3,
                  "Lossy Heap Blocks": 0,
                  "Shared Hit Blocks": 6,
                  "Shared Read Blocks": 0,
                  "Shared Dirtied Blocks": 0,
                  "Shared Written Blocks": 0,
                  "Local Hit Blocks": 0,
                  "Local Read Blocks": 0,
                  "Local Dirtied Blocks": 0,
                  "Local Written Blocks": 0,
                  "Temp Read Blocks": 0,
                  "Temp Written Blocks": 0,
                  "Plans": [
                    {
                      "Node Type": "Bitmap Index Scan",
                      "Parent Relationship": "Outer",
                      "Parallel Aware": false,
                      "Index Name": "marketplace_review_product_id_4e8c6bab491b1730_idx",
                      "Startup Cost": 0.00,
                      "Total Cost": 23.42,
                      "Plan Rows": 939,
                      "Plan Width": 0,
                      "Actual Startup Time": 0.009,
                      "Actual Total Time": 0.009,
                      "Actual Rows": 13,
                      "Actual Loops": 1,
                      "Index Cond": "(marketplace_review.product_id = marketplace_product.id)",
                      "Shared Hit Blocks": 3,
                      "Shared Read Blocks": 0,
                      "Shared Dirtied Blocks": 0,
                      "Shared Written Blocks": 0,
                      "Local Hit Blocks": 0,
                      "Local Read Blocks": 0,
                      "Local Dirtied Blocks": 0,
                      "Local Written Blocks": 0,
                      "Temp Read Blocks": 0,
                      "Temp Written Blocks": 0
                    }
                  ]
                }
              ]
            },
            {
              "Node Type": "Index Scan",
              "Parent Relationship": "Inner",
              "Parallel Aware": false,
              "Scan Direction": "Forward",
              "Index Name": "content_entry_pkey",
              "Relation Name": "content_entry",
              "Schema": "public",
              "Alias": "content_entry",
              "Startup Cost": 0.56,
              "Total Cost": 0.81,
              "Plan Rows": 1,
              "Plan Width": 385,
              "Actual Startup Time": 0.006,
              "Actual Total Time": 0.006,
              "Actual Rows": 1,
              "Actual Loops": 3,
              "Output": [""],
              "Index Cond": "(content_entry.id = marketplace_review.entry_ptr_id)",
              "Rows Removed by Index Recheck": 0,
              "Filter": "(content_entry.type = 3)",
              "Rows Removed by Filter": 0,
              "Shared Hit Blocks": 15,
              "Shared Read Blocks": 0,
              "Shared Dirtied Blocks": 0,
              "Shared Written Blocks": 0,
              "Local Hit Blocks": 0,
              "Local Read Blocks": 0,
              "Local Dirtied Blocks": 0,
              "Local Written Blocks": 0,
              "Temp Read Blocks": 0,
              "Temp Written Blocks": 0
            }
          ]
        }
      ]
    },
    "Planning Time": 0.771,
    "Triggers": [
    ],
    "Execution Time": 0.182
  }
]

只是没有连接的排序再次低于1秒,这是正常的,因为有序字段被索引,所以我不明白为什么连接会破坏那么多的排序。

1 个答案:

答案 0 :(得分:3)

您的查询减少了噪音:

org.eclipse.ui.workbench.texteditor.hyperlinkDetectorTargets

使用SELECT * FROM content_entry ce JOIN marketplace_review mr ON mr.entry_ptr_id = ce.id JOIN marketplace_product mp ON mp.id = mr.product_id WHERE ce.type = 3 AND mp.brand_id = 750 ORDER BY ce.timestamp DESC -- adding this makes it slow LIMIT 3 而不是LIMIT 3的查询可以自由返回符合条件的任意三行。这是你的第一个快速查询。

添加ORDER BY后,Postgres必须考虑所有符合条件的行,对它们进行排序并根据您的ORDER BY表达式识别“first”3。如果明显更多的行符合ORDER BY中的三个,那么这实际上要贵得多。查询可能必须访问数百万行而不是仅仅手持。这是你的第二个慢查询。

第一个查询获得更快更多行符合条件似乎反直觉,而第二个查询变得更慢。但是,如果你考虑一下,这是有道理的。

如果您的索引完全符合LIMIT 3条件并且不包含太多不合格的行,则可以显着提高第二个查询的性能 - 而且Postgres也不会期望太多不符合条件的行基于当前统计和成本设置的行。

估计4个谓词(2x WHERE,2x JOIN)的组合选择性并不容易。增加关键列的统计目标可能帮助。

ORDER BY的(缺失)输出结合可用资源和实际资源设置应该提供线索,其中估计偏离实际计数,其中成本或资源设置可能不合适以及不同索引可能有帮助的地方。

在黑暗中拍摄:

如果您还没有,EXPLAIN (ANALYZE, BUFFERS)上的多列索引将有助于两个查询。或者,如果您总是查询content_entry(type, timestamp DESC)(并且这不是大多数行的类型),则部分索引会更有效:

type = 3

相关:

确保列CREATE INDEX foo ON content_entry (timestamp DESC) WHERE entry = 3; 已定义content_entry.timestamp,或考虑NOT NULL。相关:

你真的需要从3个表(ORDER BY ce.timestamp DESC NULL LAST)返回所有列吗?