For your JOIN case, I would expect the following "conversation" (simplified and based on the original cost based QP, the NGQP may be doing something else)
xBestIndex( table A, no constraints) -> Full table scan FTS(A), cost = CARD(A), count=CARD(A) xBestIndex( table A, OID) -> primary key lookup PK(A), cost = LOG(CARD(A)), count=1, unique flag set xBestIndex( table B, no constraints) -> FTS B xBestIndex( table B, Owner) -> partial table scan PTS(B, Owner); since this seems to be unsupported, this is also FTS(B) Now it considers the possible query plans Lookup in table A, followed by a full table scan of table B: LOG(CARD(A)) * CARD(B) (because there is no index on B.Owner) Full table scan of table B, followed by lookup in table A: CARD(B) * LOG(CARD(A)) Since the cost estimate is the same, it is free to choose either plan, apparently the second one. In both cases, a full table scan of table B is performed. Why does this cause a problem in the second query plan? Note: you can use the keyword "cross" to force the desired order. Does your query work then? What is the difference in the way that table B is handled? -----Ursprüngliche Nachricht----- Von: sqlite-users [mailto:sqlite-users-boun...@mailinglists.sqlite.org] Im Auftrag von David Fletcher Gesendet: Sonntag, 29. Juli 2018 18:42 An: sqlite-users@mailinglists.sqlite.org Betreff: [EXTERNAL] [sqlite] virtual tables, xBestIndex/xFilter question First, thanks in advance for any help offered. I'm pretty comfortable using sqlite but just now starting to develop with virtual tables. I'm running into troubles and I'm pretty sure it's because my mental model of sqlite is wimpy. I'm trying to build a tool that interfaces to C++ objects in memory that are basically arranged as a tree (or graph or mesh). For example, let's suppose I have a class called A and objects of this class can own any number of B objects. Every A and B object has an ObjectID. Each object also has an owner. In C/C++ I would do this sort of thing: A* pA = GetOjectGivenID(12345); B* pB; BIterator iter(pA); while ((pB = iter.Next()) != 0) { assert(pB->pOwner == pA); } That's simple enough. I'm trying to achieve the same effect using virtual tables, each of which follow this basic pattern: create table A(OID integer primary key, Owner integer, Attr1 integer, Attr text, ...) without rowid; That is, the first column of every table is OID, the object ID. For most of the tables, there's also a column called Owner and maybe other columns that act as foreign keys, too. (I haven't actually gone to the trouble to denote the columns are foreign keys just yet.) Everything works when I have just a single table with SQL like this: select * from A where A.OID == 12345; The statement will walk through all of the rows. Behind the scenes, a C++ iterator is doing all of the work. I'm struggling with joins. This statement doesn't work in my application: select * from A join B on A.OID == B.Owner where A.OID == 12345; The xBestIndex function is called a couple of times if this is the first time the table has been defined. (xBestIndex is called fewer times if the table has been seen before. I'm guessing sqlite is caching some info.) When the xFilter function is called, it's being handed the virtual table for B, not A. Because there's no object ID to act as the iterator's source, the xFilter function ends in failure. I'm struggling to find aConstraintUsage settings that will cause A, the left-hand table in my mental model, to be presented before B. I'm setting the estimated number of rows correctly, I think. I think the argvIndex values are being set correctly, too, I think. At least sqlite isn't complaining about malformed expressions. But, something is missing. I spent some time looking at other examples but most of them seem to use other tables within sqlite to hold the data vs. objects in memory. I did stumble across https://osquery.io/ yesterday, which looks interesting and useful. It's also somewhat complex and I haven't delved into its xBestIndex/xFilter implementations just yet. I think I'd benefit from looking at any application that uses C/C++ objects in memory plus iterators to traverse objects in a tree/graph/mesh/etc. Can anyone point out projects like this? I think I'd also benefit with documentation that shows more of what's happening behind the scenes with xBestIndex/xFilter. Can anyone point me to documentation that is more detailed? I've looked at the sqlite docs, Jay Kreibich's book& Mike Owens book and "Query Anything" documentation. Thanks, David _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users ___________________________________________ Gunter Hick | Software Engineer | Scientific Games International GmbH | Klitschgasse 2-4, A-1130 Vienna | FN 157284 a, HG Wien, DVR: 0430013 | (O) +43 1 80100 - 0 May be privileged. May be confidential. Please delete if not the addressee. _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users