以下是设置:
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))"
}
]
}
]
}
}
不幸的是,我无法提供数据来重现查询计划结果。