There is no LEFT join visible to anyone except someone who is in love with LEFT joins without knowing what one is.
Your query is misformed. You proper query ought to be: select * from base b join derived d using (id) order by id; There is no b.id nor d.id in the output row. It is a figment of your imagination. The output row contains an "id". Of course the problem arises because of all the other people who also like to write broken SQL and expect it it work. Why do you expect that your brokenness should win out over someone else's brokenness? --- The fact that there's a Highway to Hell but only a Stairway to Heaven says a lot about anticipated traffic volume. >-----Original Message----- >From: sqlite-users [mailto:sqlite-users- >boun...@mailinglists.sqlite.org] On Behalf Of Torsten Landschoff >Sent: Tuesday, 15 May, 2018 16:13 >To: sqlite-users@mailinglists.sqlite.org >Subject: [sqlite] Weird query plan when sorting by a joined column > >Hello, > >I am running into an issue while trying to make our code more >efficient >when talking to Oracle - what is much faster when going to the fat >RDBMS >is curiously slow on sqlite. > >Basically when doing a join like > > select * from base b join derived d using (id) order by d.id > >the query plan is abysmal slower than when using > > select * from base b join derived d using (id) order by b.id > >I would have expected that b.id is basically an alias for d.id as >this >is a simple left join. Unfortunately it is not simple to change this >in >our query as it is created using the SQLAlchemy ORM. > > >In case anybody would be so kind and take a look at this I included a >small SQL Script to reproduce. Results here are: > >---------- >> $ /opt/sqlite3/bin/sqlite3 -version >> 3.23.2 2018-05-09 02:23:29 >f139f6f07df094a0a62e0a55ae7e91dc68006d55c9db7b244a945cc8216f55ff >> $ /opt/sqlite3/bin/sqlite3 < weird_plan.sql >> >> This results in a blazingly fast execution: >> >> addr opcode p1 p2 p3 p4 p5 comment >> ---- ------------- ---- ---- ---- ------------- -- --------- >---- >> 0 Init 0 19 0 00 Start at >19 >> 1 Noop 2 4 0 00 >> 2 Integer 100 1 0 00 r[1]=100; >LIMIT counter >> 3 Integer 0 2 0 00 r[2]=0 >> 4 MustBeInt 2 0 0 00 OFFSET >counter >> 5 OffsetLimit 1 3 2 00 if r[1]>0 >then r[3]=r[1]+max(0,r[2]) else r[3]=(-1); LIMIT+OFFSET >> 6 OpenRead 1 4 0 0 00 root=4 >iDb=0; derived >> 7 OpenRead 0 2 0 2 00 root=2 >iDb=0; base >> 8 SeekLT 1 18 4 00 key=r[4]; >pk >> 9 Rowid 1 5 0 00 >r[5]=rowid >> 10 SeekRowid 0 17 5 00 >intkey=r[5]; pk >> 11 Ge 4 17 5 54 if >r[5]>=r[4] goto 17 >> 12 IfPos 2 17 1 00 if >r[2]>0 then r[2]-=1, goto 17; OFFSET >> 13 Copy 5 7 0 00 >r[7]=r[5] >> 14 Column 0 1 8 00 >r[8]=base.modification_time >> 15 ResultRow 7 2 0 00 >output=r[7..8] >> 16 DecrJumpZero 1 18 0 00 if (-- >r[1])==0 goto 18 >> 17 Prev 1 9 0 00 >> 18 Halt 0 0 0 00 >> 19 Transaction 0 0 4 0 01 >usesStmtJournal=0 >> 20 Integer 5463052 4 0 00 >r[4]=5463052 >> 21 Goto 0 1 0 00 >> >> This takes seconds with real data: >> >> addr opcode p1 p2 p3 p4 p5 comment >> ---- ------------- ---- ---- ---- ------------- -- --------- >---- >> 0 Init 0 30 0 00 Start at >30 >> 1 OpenEphemeral 2 4 0 k(1,-B) 00 nColumn=4 >> 2 Integer 100 1 0 00 r[1]=100; >LIMIT counter >> 3 Integer 0 2 0 00 r[2]=0 >> 4 MustBeInt 2 0 0 00 OFFSET >counter >> 5 OffsetLimit 1 3 2 00 if r[1]>0 >then r[3]=r[1]+max(0,r[2]) else r[3]=(-1); LIMIT+OFFSET >> 6 OpenRead 1 4 0 0 00 root=4 >iDb=0; derived >> 7 OpenRead 0 2 0 2 00 root=2 >iDb=0; base >> 8 Rewind 1 23 0 00 >> 9 Integer 5463052 4 0 00 >r[4]=5463052 >> 10 Rowid 1 5 0 00 >r[5]=rowid >> 11 Ge 4 23 5 53 if >r[5]>=r[4] goto 23 >> 12 SeekRowid 0 22 5 00 >intkey=r[5]; pk >> 13 Ge 7 22 5 54 if >r[5]>=r[7] goto 22 >> 14 Column 0 1 10 00 >r[10]=base.modification_time >> 15 Copy 5 8 0 00 >r[8]=r[5] >> 16 Sequence 2 9 0 00 >r[9]=cursor[2].ctr++ >> 17 MakeRecord 8 3 12 00 >r[12]=mkrec(r[8..10]) >> 18 IdxInsert 2 12 8 3 00 >key=r[12] >> 19 IfNotZero 3 22 0 00 if >r[3]!=0 then r[3]--, goto 22 >> 20 Last 2 0 0 00 >> 21 Delete 2 0 0 00 >> 22 Next 1 10 0 00 >> 23 Sort 2 29 0 00 >> 24 IfPos 2 28 1 00 if >r[2]>0 then r[2]-=1, goto 28; OFFSET >> 25 Column 2 2 11 00 >r[11]=base_modification_time >> 26 Column 2 0 10 00 >r[10]=base_id >> 27 ResultRow 10 2 0 00 >output=r[10..11] >> 28 Next 2 24 0 00 >> 29 Halt 0 0 0 00 >> 30 Transaction 0 0 4 0 01 >usesStmtJournal=0 >> 31 Integer 5463052 7 0 00 >r[7]=5463052 >> 32 Goto 0 1 0 00 >---------- > > >TIA for your support! > >Greetings, Torsten > >-- >$---+----1----+----2----+----3----+----4----+----5----+----6----+ > >SCALE GmbH >Niederlassung Dresden >Torsten Landschoff >Pohlandstraße 19 >01309 Dresden > >Tel: +49-351-312002-10 >Fax: +49-351-312002-29 > >SCALE GmbH >Registergericht und Sitz: Ingolstadt, HRB 6384 >Geschäftsführer: Dr.-Ing. Heiner Müllerschön, Dipl.-Math. Ulrich >Franz >_______________________________________________ >sqlite-users mailing list >sqlite-users@mailinglists.sqlite.org >http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users