如何提高 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_idtranslations_tmdb_idvideos_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 BYDISTINCT 部分。

第二个:

  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 上尝试复合索引。应该有帮助。

  1. 为什么GROUP_CONCAT(DISTINCT ...)?没有重复。
  2. 您只select获取一部电影的数据。但是您的派生表读取并汇总了所有电影。一个伟大的优化器会仔细检查这个并且只聚合那部电影的记录。如果这是甲骨文,我会期待这一点。但是 MySQL?我不会依赖这个。因此,在您的子查询中添加一个 where 子句。
  3. 您不应该 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);