Why a SQL query is slower than another if according to EXPLAIN QUERY PLAN it should be the opposite?

StackOverflow https://stackoverflow.com/questions/17735867

Вопрос

I have two tables

CREATE TABLE Categories (
   Category INTEGER,
   Id INTEGER,
   FOREIGN KEY (Category) REFERENCES CategoriesInfo(Category)
)
CREATE TABLE 'CategoriesInfo' (
   'Category' INTEGER PRIMARY KEY NOT NULL,
   'Name' TEXT
)

with index

CREATE UNIQUE INDEX idxCategory ON Categories (Category, Id)

If I run

EXPLAIN QUERY PLAN
SELECT CategoriesInfo.Category, Name
FROM Categories, CategoriesInfo
Where Categories.Category=CategoriesInfo.Category AND Id=:id
ORDER BY Name

it says

Array
(
    [0] => Array
        (
            [selectid] => 0
            [order] => 0
            [from] => 1
            [detail] => SCAN TABLE CategoriesInfo (~1475 rows)
        )

    [1] => Array
        (
            [selectid] => 0
            [order] => 1
            [from] => 0
            [detail] => SEARCH TABLE Categories USING COVERING INDEX idxCategory (Category=? AND Id=?) (~1 rows)
        )

    [2] => Array
        (
            [selectid] => 0
            [order] => 0
            [from] => 0
            [detail] => USE TEMP B-TREE FOR ORDER BY
        )

)

But if I use joins

EXPLAIN QUERY PLAN
SELECT CategoriesInfo.Category, CategoriesInfo.Name
FROM Categories
LEFT JOIN CategoriesInfo ON (Categories.Category=CategoriesInfo.Category)
WHERE Categories.Id=:id
ORDER BY Name

I get

Array
(
    [0] => Array
        (
            [selectid] => 0
            [order] => 0
            [from] => 0
            [detail] => SEARCH TABLE Categories USING AUTOMATIC COVERING INDEX (Id=?) (~6 rows)
        )

    [1] => Array
        (
            [selectid] => 0
            [order] => 1
            [from] => 1
            [detail] => SEARCH TABLE CategoriesInfo USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
        )

    [2] => Array
        (
            [selectid] => 0
            [order] => 0
            [from] => 0
            [detail] => USE TEMP B-TREE FOR ORDER BY
        )

)

Then, using joins should be faster. But when I run both codes with phpliteadmin,

  • The 1st takes 0 seconds
  • The 2nd takes 0.3281 seconds

Why??

Это было полезно?

Решение

I would point out the two queries aren't equivalent.

Your first query effectively performs an INNER JOIN, while your second one is a LEFT JOIN. I would wager this is the cause of the speed difference. Your LEFT JOIN is going to require that all records from Categories are included in the output, something your first query does not require.

Try changing the LEFT JOIN to INNER JOIN and then compare the speed.

Другие советы

A common misconception with explain plans is that they are giving a realistic expectation of the performance of a query. What they do, however, is provide you with a good estimate of what the database thinks it will take to run the query. This is based on many factors such as table indices, statistics on the tables involved in the query, degree of parallelism, and overall resources allocated for the system.

For the second query, SQLite creates a temporary index on the Id column (this is what AUTOMATIC means). You should create this index explicitly.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top