2013-07-18 2 views
1

У меня есть две таблицыПочему SQL-запрос медленнее другого, если в соответствии с EXPLAIN QUERY PLAN это должно быть наоборот?

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

с индексом

CREATE UNIQUE INDEX idxCategory ON Categories (Category, Id) 

Если я бегу

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

это говорит

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 
     ) 

) 

Но если я использую присоединяется

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 

Я получаю

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 
     ) 

) 

Затем, используя объединений должно быть быстрее. Но когда я запускаю как коды с phpliteadmin,

  • 1-й занимает 0 секунд
  • 2-й занимает 0.3281 секунд

Почему ??

ответ

6

Я бы указал, что два запроса не эквивалентны.

Ваш первый запрос эффективно выполняет INNER JOIN, а второй - LEFT JOIN. Я бы сказал, что это причина разницы в скорости. Ваш LEFT JOIN будет требовать, чтобы все записи из категорий были включены в вывод, что ваш первый запрос не требует.

Попробуйте изменить ЛЕВЫЙ ПРИСОЕДИНЕНИЕ НА ВНУТРЕННУЮ СОЕДИНЕНИЕ, а затем сравните скорость.

0

Распространенное заблуждение с планами объяснений заключается в том, что они дают реалистичное ожидание производительности запроса. Однако они предоставляют вам хорошую оценку того, что, по мнению базы данных, потребуется для выполнения запроса. Это основано на многих факторах, таких как индексы таблиц, статистические данные о таблицах, участвующих в запросе, степень параллелизма и общие ресурсы, выделенные для системы.

0

Для второго запроса SQLite создает временный индекс на столбце Id (это то, что означает AUTOMATIC). Вы должны создать этот индекс явно.

Смежные вопросы