Postgres在横向连接中不使用GiST索引

时间:2015-03-04 14:03:36

标签: postgresql postgis

以下是设置:

CREATE EXTENSION postgis;
DROP TABLE IF EXISTS A;
DROP TABLE IF EXISTS B;

CREATE TABLE A(shape Geometry, id INT);
CREATE TABLE B(shape Geometry, id INT, kind INT);
CREATE INDEX ON A USING GIST (shape);
CREATE INDEX ON B USING GIST (shape);

我正在运行以下命令:

ANALYZE A;
ANALYZE B;

EXPLAIN
  SELECT * FROM (SELECT A.id as aid, (SELECT B.id FROM B WHERE
     ST_Contains(B.shape, A.shape)
     AND B.kind != 1 LIMIT 1) as bid FROM A) AS TMP;

给了我

      {
    "Plan": {
      "Node Type": "Seq Scan",
      "Relation Name": "A",
      "Startup Cost": 0.00,
      "Total Cost": 2606592.33,
      "Plan Rows": 549745,
      "Plan Width": 1646,
      "Plans": [
        {
          "Node Type": "Limit",
          "Parent Relationship": "SubPlan",
          "Subplan Name": "SubPlan 1",
          "Startup Cost": 0.00,
          "Total Cost": 4.68,
          "Plan Rows": 1,
          "Plan Width": 8,
          "Plans": [
            {
              "Node Type": "Seq Scan",
              "Parent Relationship": "Outer",
              "Relation Name": "B",
              "Startup Cost": 0.00,
              "Total Cost": 4.68,
              "Plan Rows": 1,
              "Plan Width": 8,
              "Filter": "((shape && A.shape) AND _st_contains(shape, A.shape))"
            }
          ]
        }
      ]
    }
  }

请注意,横向连接内部有顺序扫描,但显然有一个索引可用。但是在设置

之后

set enable_seqscan=false;

正在使用索引。这实际上会显着影响运行时,并且似乎postgres应该自动地计算这样的事情。

 {
    "Plan": {
      "Node Type": "Seq Scan",
      "Relation Name": "A",
      "Startup Cost": 10000000000.00,
      "Total Cost": 10004716493.85,
      "Plan Rows": 549450,
      "Plan Width": 1677,
      "Plans": [
        {
          "Node Type": "Limit",
          "Parent Relationship": "SubPlan",
          "Subplan Name": "SubPlan 1",
          "Startup Cost": 0.00,
          "Total Cost": 8.52,
          "Plan Rows": 1,
          "Plan Width": 8,
          "Plans": [
            {
              "Node Type": "Index Scan",
              "Parent Relationship": "Outer",
              "Scan Direction": "NoMovement",
              "Index Name": "B_shape_idx",
              "Relation Name": "B",
              "Startup Cost": 0.00,
              "Total Cost": 8.52,
              "Plan Rows": 1,
              "Plan Width": 8,
              "Index Cond": "(shape && A.shape)",
              "Filter": "_st_contains(shape, A.shape)"
            }
          ]
        }
      ]
     }
    }

有没有办法告诉postgres以较少的hacky方式使用索引?可能通过重写查询?根据我的理解,不建议在制作中使用set enable_...

当你实际运行上面的命令时,它会给出

{
    "Plan": {
      "Node Type": "Seq Scan",
      "Relation Name": "a",
      "Alias": "a",
      "Startup Cost": 0.00,
      "Total Cost": 10372.75,
      "Plan Rows": 1230,
      "Plan Width": 36,
      "Plans": [
        {
          "Node Type": "Limit",
          "Parent Relationship": "SubPlan",
          "Subplan Name": "SubPlan 1",
          "Startup Cost": 0.14,
          "Total Cost": 8.41,
          "Plan Rows": 1,
          "Plan Width": 4,
          "Plans": [
            {
              "Node Type": "Index Scan",
              "Parent Relationship": "Outer",
              "Scan Direction": "NoMovement",
              "Index Name": "b_shape_idx",
              "Relation Name": "b",
              "Alias": "b",
              "Startup Cost": 0.14,
              "Total Cost": 8.41,
              "Plan Rows": 1,
              "Plan Width": 4,
              "Index Cond": "(shape && a.shape)",
              "Filter": "((kind <> 1) AND _st_contains(shape, a.shape))"
            }
          ]
        }
      ]
    }
  }

不幸的是,我无法提供数据来重现查询计划结果。

0 个答案:

没有答案