Мой запрос Sql очень медленный (60 секунд). У кого-нибудь есть идеи по улучшению? - PullRequest
0 голосов
/ 20 мая 2011

Мой запрос медленный.Я ищу между 3 таблицами.Se_movies = 80000 записей, se_movie_contenttags = 1,6 млн записей, se_movie_descriptiontags -200000 записей

два упрощенных запроса.

ИЛИ - МЕДЛЕННЫЙ

SELECT SQL_NO_CACHE  count(movie_id)
FROM se_movies LEFT JOIN se_users ON se_movies.movie_user_id=se_users.user_id
LEFT  JOIN 
( 
  SELECT did , cid , ifnull(cid,did) as uid FROM ( SELECT tag_object_id AS did FROM se_movie_descriptiontags WHERE tag_name IN ('dog') ) AS dtag
  LEFT  JOIN (SELECT tag_object_id AS cid FROM se_movie_contenttags WHERE tag_name IN ('dog') ) AS ctag
  ON dtag.did=ctag.cid
UNION 
  SELECT did , cid , ifnull(cid,did) as uid  FROM ( SELECT tag_object_id AS did FROM se_movie_descriptiontags WHERE tag_name IN ('dog') ) AS dtag
  RIGHT  JOIN (SELECT tag_object_id AS cid FROM se_movie_contenttags WHERE tag_name IN ('dog') ) AS ctag
  ON dtag.did=ctag.cid
)
AS tagobjects ON se_movies.movie_id=tagobjects.uid
WHERE  ( se_movies.movie_title LIKE '%dog%') **OR**  (  (cid IS NOT NULL or  did IS NOT NULL) and uid IS NOT NULL )

И - Быстрый

SELECT SQL_NO_CACHE  count(movie_id)
FROM se_movies LEFT JOIN se_users ON se_movies.movie_user_id=se_users.user_id
LEFT  JOIN 
( 
  SELECT did , cid , ifnull(cid,did) as uid FROM ( SELECT tag_object_id AS did FROM se_movie_descriptiontags WHERE tag_name IN ('dog') ) AS dtag
  LEFT  JOIN (SELECT tag_object_id AS cid FROM se_movie_contenttags WHERE tag_name IN ('dog') ) AS ctag
  ON dtag.did=ctag.cid
UNION 
  SELECT did , cid , ifnull(cid,did) as uid  FROM ( SELECT tag_object_id AS did FROM se_movie_descriptiontags WHERE tag_name IN ('dog') ) AS dtag
  RIGHT  JOIN (SELECT tag_object_id AS cid FROM se_movie_contenttags WHERE tag_name IN ('dog') ) AS ctag
  ON dtag.did=ctag.cid
)
AS tagobjects ON se_movies.movie_id=tagobjects.uid
WHERE   ( se_movies.movie_title LIKE '%dog%') **AND**  (  (cid IS NOT NULL or  did IS NOT NULL) and uid IS NOT NULL )

каждый в отдельности

( se_movies.movie_title LIKE '%dog%') - around 300
 (cid IS NOT NULL or  did IS NOT NULL) and uid IS NOT NULL - return 595

но это быстро, если кто-либо из них возвращает около 50 или меньше.

В основном, если какое-либо ключевое слово имеет более 500 в каждом теге и заголовке таблицы фильма ... это занимает 60сек

в противном случае 2,3 сек.

есть ли лучший способ?

я знаю, что вы можете сделать UNION между этими двумя ... и AND для других вещей ...

Поиск - заголовок ИЛИ (contenttag или desctag)

Проблема в слишком большом количестве вариантов запроса ...

Является ли проблемой выполнение ИЛИ, если данные находятся в двух разных таблицах?В любом случае, чтобы ускорить их?.

Спасибо.

Система - mysql apache2 php5 ubuntu - amazon aws.

Объясните введите описание ссылки здесь

решено с помощью

SELECT SQL_NO_CACHE count (movie_id) FROM se_movies ВЛЕВО ПРИСОЕДИНЯТЬСЯ se_users ВКЛ se_movies.movie_user_id = se_users.user_id ВНУТРЕННЕЕ ОБЪЕДИНЕНИЕ tag_object_id('dog') UNION SELECT tag_object_id КАК movieid ОТ se_movie_descriptiontags WHERE tag_name IN ('dog') UNION SELECT s1.movie_id AS movieid ИЗ se_movies как s1 ГДЕ s1.movie_title НРАВИТСЯ '% dog%' UNION SELECT s2.movie FROMas s2 WHERE s2.movie_desc НРАВИТСЯ '% dog%') КАК тегобъекты ON se_movies.movie_id = tagobjects.movieid

.5sec

1 Ответ

0 голосов
/ 20 мая 2011

Если se_movie_descriptiontags и se_movie_contenttags содержат пары (movie_id, tag), и вы хотите включить все фильмы, которые имеют определенные теги, я бы заменил tagobjects встроенный просмотр на:

SELECT `tag_object_id` AS `uid` FROM `se_movie_descriptiontags`
WHERE `tag_name` IN ('dog')
UNION
SELECT `tag_object_id` FROM `se_movie_contenttags`
WHERE `tag_name` IN ('dog')

Этот запрос вернет идентификаторы фильмов с тегом «собака» в одной или обеих таблицах se_movie_descriptiontags и se_movie_contenttags.И тогда вы можете избавиться от OR ((cid IS NOT NULL OR did IS NOT NULL) AND uid IS NOT NULL) в основном запросе.

Окончательный полный запрос будет выглядеть так:

SELECT SQL_NO_CACHE count(movie_id)
FROM
    se_movies LEFT JOIN
    se_users ON se_movies.movie_user_id=se_users.user_id INNER JOIN 
    ( 
        SELECT `tag_object_id` AS `uid` FROM `se_movie_descriptiontags`
        WHERE `tag_name` IN ('dog')
        UNION
        SELECT `tag_object_id` FROM `se_movie_contenttags`
        WHERE `tag_name` IN ('dog')
    ) AS tagobjects ON se_movies.movie_id=tagobjects.uid
WHERE (se_movies.movie_title LIKE '%dog%')

Кроме того, обратите внимание, что только (se_movies.movie_title LIKE '%dog%') является убийцей производительности,потому что он не может быть оптимизирован с помощью индекса по столбцу movie_title, и, безусловно, вызовет сканирование таблицы.Это в основном связано с тем, что условие начинается с символа подстановки.Для этого типа сценария я бы предложил изучить возможности полнотекстового поиска MySQL.

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