在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
答案 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