Of course, the correlated version returns all books, not just the ones that 
have at least one author, were read at least once, and have at least one genre. 
 

---
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 Keith Medcalf
>Sent: Friday, 15 March, 2019 14:44
>To: SQLite mailing list
>Subject: Re: [sqlite] Query planner: Scanning subqueries vs using
>automatic covering index
>
>
>The current tip of trunk produced the same results demonstrated by
>Niklas in his original post for his original testcase for me.
>
>I would have written the query as a simple query with correlated
>subqueries to get the concatenated data as it is a "more natural"
>declaration of what is wanted (in my opinion anyway), rather than re-
>writing into joins.
>
>  select BookID,
>         Title,
>         (
>           SELECT group_concat(ltrim("First Name" || ' ' || "Last
>Name"),',')
>             FROM AuthorBooks JOIN Authors USING (AuthorID)
>            WHERE BookID == Books.BookID
>         ) as "Author(s)",
>         (
>           SELECT group_concat("Date read",', ')
>             FROM DatesRead
>            WHERE BookID == Books.BookID
>         ) as "Date(s)",
>         (
>           SELECT group_concat(Genre,', ')
>             FROM BookGenres JOIN Genres USING (GenreID)
>            WHERE BookID == Books.BookID
>         ) AS "Genre(s)"
>    FROM Books
>ORDER BY BookID;
>
>---
>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 niklas
>>Sent: Friday, 15 March, 2019 01:36
>>To: sqlite-users@mailinglists.sqlite.org
>>Subject: [sqlite] Query planner: Scanning subqueries vs using
>>automatic covering index
>>
>>I recently noticed some very slow queries for my sqlite book
>>database.
>>Turns out that it happened due to the query planner decided to scan
>>sub-queries instead of using an automatic covering index to search
>>them.
>>
>>The database contains about 3000 entries and with two subqueries it
>>took a noticable time to run, with three subqueries I had to give up
>>and
>>abort to save the CPU from overheating.
>>
>>Using indexes only take milliseconds in all cases.
>>
>>Dropping analyze (sqlite_stat1) information from the database made
>>the problem go away, i.e. made sqlite use index instead of scanning.
>>As did adding a few more columns to the ORDER BY part.
>>
>>These sql statements should be enough to demonstrate the problem.
>>I am using sqlite 3.25.1
>>
>>**********
>>create.txt
>>**********
>>
>>BEGIN;
>>
>>CREATE TABLE "Authors" (
>>    "AuthorID" INTEGER PRIMARY KEY,
>>    "Last Name" TEXT NOT NULL,
>>    "First Name" TEXT NOT NULL);
>>
>>CREATE TABLE "Books" (
>>    "BookID" INTEGER PRIMARY KEY,
>>    "Title" TEXT NOT NULL);
>>
>>CREATE TABLE "Genres"(
>>    "GenreID" INTEGER PRIMARY KEY,
>>    "Genre" TEXT UNIQUE NOT NULL);
>>
>>CREATE TABLE "DatesRead"(
>>    "BookID" INTEGER,
>>    "Date Read" TEXT,
>>    PRIMARY KEY("BookID", "Date Read"),
>>    FOREIGN KEY(BookID) REFERENCES Books(BookID)) WITHOUT ROWID;
>>
>>CREATE TABLE "AuthorBooks"(
>>    "BookID" INTEGER,
>>    "AuthorID" INTEGER,
>>    PRIMARY KEY("BookID", "AuthorID" ),
>>    FOREIGN KEY(BookID) REFERENCES Books(BookID),
>>    FOREIGN KEY(AuthorID) REFERENCES Authors(AuthorID)) WITHOUT
>>ROWID;
>>
>>CREATE TABLE "BookGenres"(
>>    "BookID" INTEGER,
>>    "GenreID" INTEGER,
>>    PRIMARY KEY("BookID", "GenreID" ),
>>    FOREIGN KEY(BookID) REFERENCES Books(BookID),
>>    FOREIGN KEY(GenreID) REFERENCES Genres(GenreID)) WITHOUT ROWID;
>>
>>ANALYZE;
>>INSERT INTO sqlite_stat1 VALUES('BookGenres','BookGenres','3190 2
>>1');
>>INSERT INTO sqlite_stat1 VALUES('DatesRead','DatesRead','3047 2 1');
>>INSERT INTO sqlite_stat1 VALUES('AuthorBooks','AuthorBooks','3549 2
>>1');
>>INSERT INTO sqlite_stat1 VALUES('Authors',NULL,'1329');
>>INSERT INTO sqlite_stat1 VALUES('Books',NULL,'2978');
>>INSERT INTO sqlite_stat1
>>VALUES('Genres','sqlite_autoindex_Genres_1','112
>>1');
>>
>>COMMIT;
>>
>>************
>>queries.txt
>>************
>>
>>select "--------------------";
>>select "order by bookid only";
>>select "--------------------";
>>
>>EXPLAIN QUERY PLAN
>>SELECT BookID,Title,"Author(s)","Date(s)","Genre(s)"
>>FROM Books
>>JOIN (SELECT BookID, group_concat(ltrim("First Name"||' '||"Last
>>Name"),',
>>') AS 'Author(s)' FROM Books JOIN AuthorBooks USING(BookID) JOIN
>>Authors
>>USING(AuthorID) GROUP BY BookID) USING(BookID)
>>JOIN (SELECT BookID, group_concat("Date read",', ') AS 'Date(s)'
>FROM
>>Books
>>JOIN DatesRead USING(BookID) GROUP BY BookID) USING(BookID)
>>JOIN (SELECT BookID, group_concat(Genre,', ') AS 'Genre(s)' FROM
>>Books JOIN
>>BookGenres USING(BookID) JOIN Genres USING(GenreID) GROUP BY BookID)
>>USING(BookID)
>>ORDER BY BookID;
>>
>>select "-------------------------------------------";
>>select "order by bookid and some other fields too";
>>select "------------------------------------------";
>>
>>EXPLAIN QUERY PLAN
>>SELECT BookID,Title,"Author(s)","Date(s)","Genre(s)"
>>FROM Books
>>JOIN (SELECT BookID, group_concat(ltrim("First Name"||' '||"Last
>>Name"),',
>>') AS 'Author(s)' FROM Books JOIN AuthorBooks USING(BookID) JOIN
>>Authors
>>USING(AuthorID) GROUP BY BookID) USING(BookID)
>>JOIN (SELECT BookID, group_concat("Date read",', ') AS 'Date(s)'
>FROM
>>Books
>>JOIN DatesRead USING(BookID) GROUP BY BookID) USING(BookID)
>>JOIN (SELECT BookID, group_concat(Genre,', ') AS 'Genre(s)' FROM
>>Books JOIN
>>BookGenres USING(BookID) JOIN Genres USING(GenreID) GROUP BY BookID)
>>USING(BookID)
>>ORDER BY BookID, Title, "Author(s)", "Date(s)";
>>
>>
>>************
>>Test run:
>>************
>>
>>del test.db
>>type create.txt | sqlite3 test.db
>>type queries.txt | sqlite3 test.db
>>
>>
>>************
>>Output:
>>************
>>
>>--------------------
>>order by bookid only
>>--------------------
>>QUERY PLAN
>>|--MATERIALIZE 1
>>|  |--SCAN TABLE Books
>>|  |--SEARCH TABLE AuthorBooks USING PRIMARY KEY (BookID=?)
>>|  `--SEARCH TABLE Authors USING INTEGER PRIMARY KEY (rowid=?)
>>|--MATERIALIZE 2
>>|  |--SCAN TABLE Books
>>|  `--SEARCH TABLE DatesRead USING PRIMARY KEY (BookID=?)
>>|--MATERIALIZE 3
>>|  |--SCAN TABLE Books
>>|  |--SEARCH TABLE BookGenres USING PRIMARY KEY (BookID=?)
>>|  `--SEARCH TABLE Genres USING INTEGER PRIMARY KEY (rowid=?)
>>|--SCAN SUBQUERY 1
>>|--SCAN SUBQUERY 2
>>|--SCAN SUBQUERY 3
>>|--SEARCH TABLE Books USING INTEGER PRIMARY KEY (rowid=?)
>>`--USE TEMP B-TREE FOR ORDER BY
>>-------------------------------------------
>>order by bookid and some other fields too
>>------------------------------------------
>>QUERY PLAN
>>|--MATERIALIZE 1
>>|  |--SCAN TABLE Books
>>|  |--SEARCH TABLE AuthorBooks USING PRIMARY KEY (BookID=?)
>>|  `--SEARCH TABLE Authors USING INTEGER PRIMARY KEY (rowid=?)
>>|--MATERIALIZE 2
>>|  |--SCAN TABLE Books
>>|  `--SEARCH TABLE DatesRead USING PRIMARY KEY (BookID=?)
>>|--MATERIALIZE 3
>>|  |--SCAN TABLE Books
>>|  |--SEARCH TABLE BookGenres USING PRIMARY KEY (BookID=?)
>>|  `--SEARCH TABLE Genres USING INTEGER PRIMARY KEY (rowid=?)
>>|--SCAN SUBQUERY 1
>>|--SEARCH TABLE Books USING INTEGER PRIMARY KEY (rowid=?)
>>|--SEARCH SUBQUERY 2 USING AUTOMATIC COVERING INDEX (BookID=?)
>>|--SEARCH SUBQUERY 3 USING AUTOMATIC COVERING INDEX (BookID=?)
>>`--USE TEMP B-TREE FOR ORDER BY
>>
>>
>>As can be seen the first query (when analyze information is in
>place)
>>will use three nested scans as opposed to the second query with more
>>order by columns that instead uses indexes to search.
>>
>>Now, might this be a weakness in the query planner, or is there some
>>precautions I could/should always take to avoid the scanning?
>>
>>
>>
>>
>>
>>
>>--
>>Sent from: http://sqlite.1065341.n5.nabble.com/
>>_______________________________________________
>>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



_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to