<div dir="ltr">Hello,<div><br></div><div>I have a query plan optimization question. It is formatted nicely on </div><div><br></div><div><a href="http://stackoverflow.com/questions/28856452/postgres-not-using-gist-index-in-lateral-join">http://stackoverflow.com/questions/28856452/postgres-not-using-gist-index-in-lateral-join</a><br></div><div><br></div><div>But here is a copy for the archive:</div><br>Here is the setup:<div><br><div>CREATE EXTENSION postgis;</div><div>DROP TABLE IF EXISTS A;</div><div>DROP TABLE IF EXISTS B; </div><div>CREATE TABLE A(shape Geometry, id INT); </div><div>CREATE TABLE B(shape Geometry, id INT, kind INT); </div><div>CREATE INDEX ON A USING GIST (shape); </div><div>CREATE INDEX ON B USING GIST (shape);<br><br>I am running the following commands:</div><div><br><div>ANALYZE A; </div><div>ANALYZE B;</div><div><br></div><div>-- for each row in A, select exactly one row in B (if there is one)</div><div>-- such that B contains <span style="font-size:13.1999998092651px">geometry of A</span></div><div>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;<br><br>which gives me {
 "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))"
 }
 ]
 }
 ]
 }
 }<br><br><br>Note that there is a sequential scan inside the lateral join, however there is clearly an index available. However after setting<br><br>set enable_seqscan=false;<br><br>the index is being used. This actually affects runtime significantly (around 3 times faster) and seems that postgres should figure things like that automatically. {
 "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)"
 }
 ]
 }
 ]
 }
 }<br><br>Is there any way to tell postgres to use index in a less hacky way? Possibly by rewriting the query? From what I understand the use of set enable_... is not recommended in production.<br><br>When you actually run the commands above it will give</div><div><br></div><div>{
 "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))"
 }
 ]
 }
 ]
 }
 }<br><br>Unfortunately I cannot provide data to reproduce the query plan results.</div></div></div><div><br></div><div>Thanks,</div><div>Igor</div></div>