如何提高 SQL 的抓取速度?
How to improve fetching speed from SQL?
我不是 MySQL 索引方面的专家,但我看了很多教程,我的页面仍然需要 7 秒才能加载,使用 PHP.
我在 MySQL table 中有大约 50k 行和 30 列。
如何提高 MySQL 获取数据的速度?我可以在下面的查询中改进什么吗?
SELECT tmdb_movies.movie_title,tmdb_movies.budget,tmdb_movies.original_language,tmdb_movies.original_title
,translations.translations_english_name
,videos.videos_name,videos.videos_key
FROM tmdb_movies
LEFT JOIN
(
SELECT
translations_tmdb_id
,GROUP_CONCAT(DISTINCT translations.translations_english_name SEPARATOR ', ') AS translations_english_name
FROM translations
GROUP BY translations_tmdb_id
) translations ON translations.translations_tmdb_id = tmdb_movies.tmdb_id
LEFT JOIN
(
SELECT
videos_tmdb_id
,GROUP_CONCAT(DISTINCT videos.videos_name) as videos_name
,GROUP_CONCAT(DISTINCT videos.videos_key) as videos_key
FROM videos
GROUP BY videos_tmdb_id
) videos ON videos.videos_tmdb_id = tmdb_movies.tmdb_id
Where tmdb_movies.tmdb_id= '$tmdb_id'
这里,我用tmdb_id
连接所有的table。 tmdb_id
、translations_tmdb_id
和 videos_tmdb_id
在 MySQL 中编入索引。
这是我的 MySQL table 结构的示例:
tmdb_movies
table:
tmdb_id movie_title
1 Logan
2 Iron Man
3 Superman
translations
table
translations_tmdb_id translations_english_name
1 English
1 Hindi
1 French
2 English
2 Spanish
2 Hindi
videos
table
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
您的主要 SELECT
语句可能没问题;您正在过滤自动递增的主键。
这两个子查询可能存在提高性能的机会。
第一个:
SELECT
translations_tmdb_id,
GROUP_CONCAT( DISTINCT translations.translations_english_name
SEPARATOR ', ') AS translations_english_name
FROM translations
GROUP BY translations_tmdb_id
translations_tmdb_id, translations_english_name
上的 compound index (sometimes called a composite index or multi-column index) 有可能对这个子查询有很大帮助。为什么?它可以帮助查询的 GROUP BY
和 DISTINCT
部分。
第二个:
SELECT
videos_tmdb_id
,GROUP_CONCAT(DISTINCT videos.videos_name) as videos_name
,GROUP_CONCAT(DISTINCT videos.videos_key) as videos_key
FROM videos
GROUP BY videos_tmdb_id
同样的原则适用,但是两个不同的 DISTINCT
子句会稍微减慢速度。在 videos_tmdb_id, videos_name, videos_key
上尝试复合索引。应该有帮助。
- 为什么
GROUP_CONCAT(DISTINCT ...)
?没有重复。
- 您只select获取一部电影的数据。但是您的派生表读取并汇总了所有电影。一个伟大的优化器会仔细检查这个并且只聚合那部电影的记录。如果这是甲骨文,我会期待这一点。但是 MySQL?我不会依赖这个。因此,在您的子查询中添加一个 where 子句。
- 您不应该 select 没有 order by 子句的视频名称和密钥。对它们进行排序,使它们具有相同的顺序,即名字与第一个键匹配等。
这是您重写的查询:
SELECT
m.movie_title,
m.budget,
m.original_language,
m.original_title,
t.translations_english_names,
v.videos_names,
v.videos_keys
FROM tmdb_movies m
CROSS JOIN
(
SELECT
GROUP_CONCAT(translations_english_name SEPARATOR ', ') AS translations_english_names
FROM translations
WHERE translations_tmdb_id = @tmdb_id
) t
CROSS JOIN
(
SELECT
GROUP_CONCAT(videos_name ORDER BY videos_name) as videos_names,
GROUP_CONCAT(videos_key ORDER BY videos_name) as videos_keys
FROM videos
WHERE videos_tmdb_id = @tmdb_id
) v
WHERE m.tmdb_id = @tmdb_id;
这些是您应该使用的索引:
create index idxm on tmdb_movies(tmdb_id); -- if tmdb_id is PK, you have this already
create index idxt on translations(translations_tmdb_id, translations_english_name);
create index idxv on videos(videos_tmdb_id, videos_name, videos_key);
我不是 MySQL 索引方面的专家,但我看了很多教程,我的页面仍然需要 7 秒才能加载,使用 PHP.
我在 MySQL table 中有大约 50k 行和 30 列。
如何提高 MySQL 获取数据的速度?我可以在下面的查询中改进什么吗?
SELECT tmdb_movies.movie_title,tmdb_movies.budget,tmdb_movies.original_language,tmdb_movies.original_title
,translations.translations_english_name
,videos.videos_name,videos.videos_key
FROM tmdb_movies
LEFT JOIN
(
SELECT
translations_tmdb_id
,GROUP_CONCAT(DISTINCT translations.translations_english_name SEPARATOR ', ') AS translations_english_name
FROM translations
GROUP BY translations_tmdb_id
) translations ON translations.translations_tmdb_id = tmdb_movies.tmdb_id
LEFT JOIN
(
SELECT
videos_tmdb_id
,GROUP_CONCAT(DISTINCT videos.videos_name) as videos_name
,GROUP_CONCAT(DISTINCT videos.videos_key) as videos_key
FROM videos
GROUP BY videos_tmdb_id
) videos ON videos.videos_tmdb_id = tmdb_movies.tmdb_id
Where tmdb_movies.tmdb_id= '$tmdb_id'
这里,我用tmdb_id
连接所有的table。 tmdb_id
、translations_tmdb_id
和 videos_tmdb_id
在 MySQL 中编入索引。
这是我的 MySQL table 结构的示例:
tmdb_movies
table:
tmdb_id movie_title
1 Logan
2 Iron Man
3 Superman
translations
table
translations_tmdb_id translations_english_name
1 English
1 Hindi
1 French
2 English
2 Spanish
2 Hindi
videos
table
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
您的主要 SELECT
语句可能没问题;您正在过滤自动递增的主键。
这两个子查询可能存在提高性能的机会。
第一个:
SELECT
translations_tmdb_id,
GROUP_CONCAT( DISTINCT translations.translations_english_name
SEPARATOR ', ') AS translations_english_name
FROM translations
GROUP BY translations_tmdb_id
translations_tmdb_id, translations_english_name
上的 compound index (sometimes called a composite index or multi-column index) 有可能对这个子查询有很大帮助。为什么?它可以帮助查询的 GROUP BY
和 DISTINCT
部分。
第二个:
SELECT
videos_tmdb_id
,GROUP_CONCAT(DISTINCT videos.videos_name) as videos_name
,GROUP_CONCAT(DISTINCT videos.videos_key) as videos_key
FROM videos
GROUP BY videos_tmdb_id
同样的原则适用,但是两个不同的 DISTINCT
子句会稍微减慢速度。在 videos_tmdb_id, videos_name, videos_key
上尝试复合索引。应该有帮助。
- 为什么
GROUP_CONCAT(DISTINCT ...)
?没有重复。 - 您只select获取一部电影的数据。但是您的派生表读取并汇总了所有电影。一个伟大的优化器会仔细检查这个并且只聚合那部电影的记录。如果这是甲骨文,我会期待这一点。但是 MySQL?我不会依赖这个。因此,在您的子查询中添加一个 where 子句。
- 您不应该 select 没有 order by 子句的视频名称和密钥。对它们进行排序,使它们具有相同的顺序,即名字与第一个键匹配等。
这是您重写的查询:
SELECT
m.movie_title,
m.budget,
m.original_language,
m.original_title,
t.translations_english_names,
v.videos_names,
v.videos_keys
FROM tmdb_movies m
CROSS JOIN
(
SELECT
GROUP_CONCAT(translations_english_name SEPARATOR ', ') AS translations_english_names
FROM translations
WHERE translations_tmdb_id = @tmdb_id
) t
CROSS JOIN
(
SELECT
GROUP_CONCAT(videos_name ORDER BY videos_name) as videos_names,
GROUP_CONCAT(videos_key ORDER BY videos_name) as videos_keys
FROM videos
WHERE videos_tmdb_id = @tmdb_id
) v
WHERE m.tmdb_id = @tmdb_id;
这些是您应该使用的索引:
create index idxm on tmdb_movies(tmdb_id); -- if tmdb_id is PK, you have this already
create index idxt on translations(translations_tmdb_id, translations_english_name);
create index idxv on videos(videos_tmdb_id, videos_name, videos_key);