2013-12-19 6 views
0

Я пытаюсь соединить два запроса от 2-х различных таблиц и объединить их в один выберите, но это занимает слишком много времени:Выбор два таблиц занимает слишком много времени

SELECT 
    p.pid, p.cid, p.date,p.headline,p.content,p.description, 
    r.reg_id,r.cid,r.year,r.headline,r.description,r.url,r.extra 
FROM printers p, readers r 
WHERE 
    (p.headline LIKE '%val%' OR p.content LIKE '%val%' OR p.description LIKE '%val%' OR r.headline LIKE '%val%' OR r.description LIKE '%val%') 
    AND (p.cid != 37 OR p.cid != 38 OR p.cid != 63 OR p.cid != 64) 
    AND (p.status = 'online' OR p.status = 'active' OR r.status = 'online' OR r.status = 'active') 
    AND r.headline_en = '' 

Это занимает так много времени, PhpMyAdmin (я использую его чтобы попробовать этот запрос) прокомментировал, что произошла ошибка в C: \ Windows \ Temp \ *. myi. И если я использую mysql-клиент, он будет комментировать это, я должен увеличить пределы памяти. Таблица printers имеет < 2000 строк, а таблица readers имеет менее 1000 строк, что не является большой базой данных ... Я предпочитаю оптимизацию, поскольку у меня нет доступа к mysql config на моем хосте.

Пожалуйста, помогите мне, мой запрос неправильный или мне нужно изменить my.cnf ??

Редактировать: если информация отсутствует. Этот запрос предназначен для функции «Поиск» на сайте, поэтому нет ограничений, и они представляют собой две разные таблицы без столбца общего доступа.

+2

Я не вижу никаких условий соединения. Как в вашем запросе подключены таблицы «принтеры» и «читатели»? – zerkms

+0

Декартовые соединения (то есть выбор из двух или более таблиц без установки условий соединения) часто вызывают очень большие ряды. Либо определите условия 'join', либо используйте' limit' для извлечения набора строк в кусках. – Barranka

ответ

2

Вы ищете две таблицы, не связывая их каким-либо образом. Это создает

  • для каждой совпадающей строки в принтерах, все соответствующие строки для читателей
  • для каждой соответствующей строки в читателях все соответствующие строки в принтерах

Поэтому часть запроса, относящийся к принтерам запускаются для каждый соответствующий считыватель и наоборот. Это ставит этот порядок в размере 2000000 полных сканирований таблицы.

Чтобы это исправить,

  • либо связать таблицы (с помощью пункта JOIN)
  • или разбить запрос в два, возможно, воссоединить их с UNION

EDIT

Это случайные мысли в ответ на комментарии:

  • Использования LIKE '%val%' делает использование индекса невозможного
  • Первым WHERE условие является селективным на оба р такого г. Это мое (возможно, ошибочное) понимание, что это исключает использование одного из них в качестве таблицы вождения, действительно создавая сканирование таблицы перекрестных выборок. Конечно, 2000000 является максимальным наихудшим случаем (все совпадения)
  • Все, что я забыл?
+0

"для каждой соответствующей строки в принтерах, все соответствующие строки для читателей" --- это не совсем правильно. Помимо этого - +1 – zerkms

+1

PS: исправить №3: условие соединения может быть указано даже для текущего неявного соединения, почему бы и нет. Принимая во внимание, что «либо связывать таблицы (через предложение JOIN)» само по себе без 'ON', все равно приведет к декартовому продукту – zerkms

+1

Не совсем 2000000 сканированных таблиц, всего 2000000 строк для фильтрации. –

0

Ok первый прочь я optermised ваш запрос

SELECT p.pid, 
     p.cid, 
     p.date, 
     p.headline, 
     p.content, 
     p.description, 
     r.reg_id, 
     r.cid, 
     r.year, 
     r.headline, 
     r.description, 
     r.url, 
     r.extra 
FROM printers p, 
     readers r 
WHERE (
     CONCAT(
      p.headline, 
      p.content, 
      p.description, 
      r.headline, 
      r.description 
     ) 
     LIKE '%val%') 
     AND p.cid NOT IN (37,38,63,64) 
     AND (p.status IN ('online','active') 
      OR r.status IN ('online','active') 
     AND r.headline_en = '' 

также вы кладете индексы на любом из столбцов, те, которые вы ищете против вас должен попытаться индекс

Edit.также вам нужно сделать соединение с вашими данными, иначе вы получите огромное количество комбинаций, поэтому приведенное выше оптимизировано только на бит после «WHERE»

+0

Извините, он все еще занимает слишком много времени. Спасибо, в любом случае. Я попытаюсь оптимизировать бит «где». – SianiparD

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