Добавление предложения WHERE делает запрос действительно медленным - PullRequest
0 голосов
/ 19 ноября 2010

Рассмотрим следующие два запроса:

select a.*, c.*
from account a
join customer c on a.customer_id = c.id
join import i on a.import_id = i.id
join import_bundle ib on i.import_bundle_id = ib.id

и

select a.*, c.*
from account a
join customer c on a.customer_id = c.id
join import i on a.import_id = i.id
join import_bundle ib on i.import_bundle_id = ib.id
where ib.id = 8

Первый запрос быстрый, а второй супер медленный.Есть идеи почему?Я предполагаю, что мне нужен индекс или что-то, но я не понимаю, как работают индексы.Я использую MySQL.

Вот что произойдет, если я сделаю EXPLAIN для второго запроса:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra   
 1  SIMPLE  ib  const   PRIMARY     PRIMARY     8   const   1   Using index
 1  SIMPLE  c   ALL     PRIMARY         144858  
 1  SIMPLE  a   ref     fk_account_customer_id,fk_account_import_id     fk_account_customer_id  8   mcif.c.id   2   
 1  SIMPLE  i   eq_ref  PRIMARY,import_bundle_id    PRIMARY     8   mcif.a.import_id    1   Using where

Хотя я не знаю, как это интерпретировать.

Редактировать: вот что я в итоге использовал:

select a.*,
       c.*
  from account a
  join customer c on a.customer_id = c.id
  join (select id,
               import_bundle_id
          from import
         where import_bundle_id = 8) i on a.import_id = i.id
  join import_bundle ib on i.import_bundle_id = ib.id

Добавление индекса на import_bundle.id ничего не сделало.

Ответы [ 5 ]

1 голос
/ 20 ноября 2010
  • Что касается производительности, в вашем запросе вам действительно нужны. * И c. *?

  • Таким образом, использование индекса недостаточно улучшается. Я не знаком с MySQL, но не могли бы вы попробовать объединиться с подобным подзапросом?

    select a.*, c.*
    from account a
    join customer c on a.customer_id = c.id
    join 
    (    
        SELECT id, import_bundle_id FROM import WHERE id = 8
    ) as i on a.import_id = i.id
    join import_bundle ib on i.import_bundle_id = ib.id
    where ib.id = 8
  • Вероятно, лучшим индексом являются: индекс для import.import_bundle_id и другой индекс для import_bundle.id.
1 голос
/ 19 ноября 2010

Последний запрос вынуждает MySQL находить записи в наборе результатов с ib.id = 8.

Если вы добавите индекс к import_bundle.id, MySQL сможет быстро найтисоответствующая запись, вместо того, чтобы проверять их все.

Индекс базы данных подобен индексу в учебнике, вместо того, чтобы просматривать каждую страницу, вы переходите к индексу сзади, находите номер страницы (s) для того, что вы ищете, и идите прямо туда.

1 голос
/ 19 ноября 2010

Используйте EXPLAIN http://dev.mysql.com/doc/refman/5.0/en/explain.html, чтобы понять, что индекс может улучшить ваш поиск.

Вот как работает индекс http://www.tizag.com/mysqlTutorial/mysql-index.php

0 голосов
/ 19 ноября 2010

Другие ответы указывают вам в правильном направлении, насколько указатель на ib.id. Однако ib.id выглядит как первичный ключ (PK). Это установлено как PK в вашей базе данных? Если это так, он должен автоматически получить индекс в силу того, что он является PK. Если он не установлен как PK, и это действительно столбец, который должен быть, у вас будет больше проблем с вашей базой данных, чем просто производительность.

Короче говоря, если ib.id должен быть первичным ключом, сделайте его одним, и ваша производительность должна улучшиться, потому что он будет автоматически проиндексирован (и вам не нужно будет беспокоиться об отдельном добавлении к нему любых индексов).

0 голосов
/ 19 ноября 2010

Я не знаком с mysql конкретно, но индекс ib.id почти наверняка будет полезен. Любые поля, которые вы используете в предложении JOIN или WHERE, обычно должны быть проиндексированы. Кроме того, вы можете попробовать выполнить фильтрацию по i.import_bundle_id вместо ib.id и посмотреть, поможет ли это.

Индексы в целом служат для ускорения поиска информации. Вместо того, чтобы просматривать каждый элемент, разбросанный по всей вашей базе данных, чтобы найти нужную, они могут использовать хеш-таблицу или подобный метод, чтобы сузить область поиска, возможно, сузив ее до нужной записи , Википедия объясняет это гораздо лучше, чем я. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...