提高MySQL查询性能

时间:2017-07-10 06:40:42

标签: mysql performance

在PHP文件中查询(https://bugzilla.xamarin.com/show_bug.cgi?id=29167#c0

SELECT tmdb_movies.movie_title,tmdb_movies.tmdb_id
,GROUP_CONCAT(DISTINCT videos.videos_key) as videos_key
,GROUP_CONCAT(DISTINCT videos.videos_name) as videos_name
,GROUP_CONCAT(DISTINCT genres.genres_name) AS genres_name

FROM tmdb_movies

LEFT JOIN videos ON videos.videos_tmdb_id=tmdb_movies.tmdb_id
JOIN genres USING (tmdb_id)

GROUP BY tmdb_movies.movie_title,tmdb_movies.tmdb_id

HAVING find_in_set('$category1', genres_name) $andor find_in_set('$category2', genres_name) 

ORDER BY $sortby $order LIMIT 10 OFFSET $start

在此查询中:$category1$category2是变量,如(动作,犯罪,恐怖,喜剧等)

$andor是一个变量。如果变量AND$category1都有值,则它的值为$category2

如果只有$category1有值,则$andor变量值为OR

<小时/> 这10个查询需要大约4-6秒才能显示。我的预期速度小于0.1秒。我在MySQL表中有大约80k行和35列。

我的索引

create index idxm on tmdb_movies(tmdb_id);
create index idxv on videos(videos_tmdb_id, videos_name, videos_key);
create index idxv on genres(tmdb_id, genres_name);

tmdb_movies表格:

tmdb_id      movie_title
1            Logan
2            Iron Man
3            Superman

genres表格

tmdb_id                 genres_name
1                         Crime
1                         Comedy
1                         Drama
2                         Action
2                         Horror
2                         Documentary
3                         Music

videos表格

videos_tmdb_id          videos_name
1                       Official Trailer
1                       Trailer 2 
2                       Trailer 1
2                       Trailer 2 HD
3                       Superman Trailer 1
3                       Superman Trailer 2

如果您需要更多信息,请告诉我

编辑:解释查询Screeshot

SQL Fiddle

3 个答案:

答案 0 :(得分:2)

请尝试使用以下查询:

SELECT tmdb_movies.movie_title,tmdb_movies.tmdb_id
,GROUP_CONCAT(DISTINCT videos.videos_key) as videos_key
,GROUP_CONCAT(DISTINCT videos.videos_name) as videos_name
,GROUP_CONCAT(DISTINCT genres.genres_name) AS genres_name

FROM tmdb_movies

LEFT JOIN videos ON videos.videos_tmdb_id=tmdb_movies.tmdb_id
JOIN genres USING (tmdb_id)

WHERE 1=1
AND EXISTS( SELECT 1 FROM genres g WHERE g.tmdb_id = genres.tmdb_id AND g.genres_name = '$category1' )

GROUP BY tmdb_movies.movie_title,tmdb_movies.tmdb_id

ORDER BY $sortby $order LIMIT 10 OFFSET $start

请注意,我在1=1子句中包含了条件WHERE。这是,因此您可以轻松追加AND whatever。这样,您可以更轻松地在代码中构建if条件,以便附加$category2或不附加DISTINCT。像你一样检查一个空字符串是没有意义的,应该避免。

编辑:

要避免GROUP_CONCAT中的SELECT tmdb_movies.movie_title,tmdb_movies.tmdb_id , (SELECT GROUP_CONCAT(videos_key) FROM videos v WHERE v.videos_tmdb_id = tmdb_movies.tmdb_id) , (SELECT GROUP_CONCAT(videos_name) FROM videos v WHERE v.videos_tmdb_id = tmdb_movies.tmdb_id) ,GROUP_CONCAT(DISTINCT genres.genres_name) AS genres_name FROM tmdb_movies JOIN genres USING (tmdb_id) WHERE 1=1 AND EXISTS( SELECT 1 FROM genres g WHERE g.tmdb_id = genres.tmdb_id AND g.genres_name = '$category1' ) GROUP BY tmdb_movies.movie_title,tmdb_movies.tmdb_id ORDER BY $sortby $order LIMIT 10 OFFSET $start ,您必须将这些内容写为子查询,以避免连接倍增。我认为,我并没有为这些类型做到这一点,因为我认为它很适合你的索引。
无论如何,我还要说,我怀疑你会因此得到任何改善。

Fragment

答案 1 :(得分:1)

我会尝试使用VARCHAR更改(如果可能)TEXT数据类型,使用VARCHAR的有效最大长度。 TEXT可能会对索引性能产生不良影响。 分析执行计划的意义不大,因为你在rextester上记录的记录很少,所以请试试你的数据库并告诉我。

例如:

CREATE TABLE genres (
  tmdb_id INTEGER NOT NULL,
  genres_name VARCHAR(100) NOT NULL
);

CREATE TABLE videos (
  videos_tmdb_id INTEGER NOT NULL,
  videos_name VARCHAR(800) NOT NULL,
  videos_key VARCHAR(100) NOT NULL
);

然后创建你建议的索引,但我会尝试将类型的索引更改为:

create index idxv on genres(genres_name, tmdb_id);

答案 2 :(得分:0)

我会首先尝试获取这些类型,然后将其余部分加入到该结果中:

SELECT
tmdb_movies.movie_title,
tmdb_movies.tmdb_id,
GROUP_CONCAT(DISTINCT videos.videos_key) as videos_key,
GROUP_CONCAT(DISTINCT videos.videos_name) as videos_name,
GROUP_CONCAT(DISTINCT genres.genres_name) AS genres_name
FROM
(
SELECT
distinct(tmdb_id) as tmdb_id
FROM
genres
WHERE 
genres_name = '$category1' $andor genres_name = '$category2'
) x
LEFT JOIN tmdb_movies ON tmdb_movies.tmdb_id=x.tmdb_id
LEFT JOIN videos ON videos.videos_tmdb_id=x.tmdb_id
LEFT JOIN genres ON genres.tmdb_id=x.tmdb_id
GROUP BY tmdb_movies.movie_title,x.tmdb_id
ORDER BY $sortby $order LIMIT 10 OFFSET $start