games_releases
是一个结合了游戏信息的表格。像游戏标题,游戏发行商或开发者这样的信息对于许多不同的游戏是相同的,因此它们被保存在不同的表格中,这些表格后来连接在一起。
以下示例仅加入games_titles
表以便于理解(但实际上还有一些表按照相同的原则加入)。
games_releases
表:
id int(11) <- unique
title_id int(11) <- index
developer_id int(11)
... more game relevant data
games_releases
的一些典型行看起来像:
id title_id developer_id ... ...
--------------------------------------------
1 17 265
2 23 41
3 31 3
4 42 15
5 17 123
games_titles
表:
id int(11) <- unique
title varchar(128)
created int(11)
games_titles
的一些典型行看起来像:
id title created
----------------------------------------
17 Pac-Man [some unix timestamp]
23 Defender [some unix timestamp]
31 Scramble [some unix timestamp]
42 Q*bert [some unix timestamp]
99 Phoenix [some unix timestamp]
现在:假设用户希望按字母顺序查看所有游戏(一次24个),然后执行此查询......
SELECT
id AS release_id, t.`title` AS title
FROM
games_releases
LEFT JOIN games_titles t ON t.`id`=`games_releases`.`title_id`
ORDER BY title
LIMIT 24
这将被退回
release_id title
-----------------------------
2 Defender
1 Pac-Man
5 Pac-Man
4 Q*Bert
3 Scramble
所以基本上结果表的特征是字符串而不是ID。
挑战:此查询将需要0.2秒才能运行,这是慢速的方式(games_releases
列出了大约80.000项,但想象数据库增长到1.000.000项。)
以下是解释告诉我的内容(games_releases有索引title_id):
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE games_releases NULL index NULL title_id 4 NULL 76669 Using index; Using temporary; Using filesort
1 SIMPLE t NULL eq_ref PRIMARY PRIMARY 4 phoenix.games_releases.title_id 1
有机会对此进行优化吗?
编辑:问题已得到解答。问题是错误的“LEFT JOIN”而不是“JOIN”。但是:我如何通过增长OFFSET来征服更长的执行时间?
虽然已经阅读了关于它的负载,但我很难理解在进行多个JOIN时如何有效地设置索引。
拥有games_titles的“标题”索引似乎没有任何效果。
答案 0 :(得分:0)
供将来参考:有关查询效果的问题通常必须显示查询中涉及的每个表的SHOW CREATE TABLE tablename
的输出。表结构对性能产生影响。
从您的查询中看,您希望按照字母顺序显示games_titles
表格中的前24个标题,其中games_releases
表格中存在任何匹配项。我不明白你LEFT JOIN
的逻辑。如果games_releases
中的标题有多行,您是否希望重复标题?对于games_releases
中games_titles
行无法匹配的行,您想要做什么?
我认为你可以得到你想要的结果如下:
SELECT DISTINCT t.id, t.title
FROM games_titles t
JOIN games_releases r ON t.id = r.title_id
ORDER BY t.title
LIMIT 24
这会从titles表中提供与releases表中的任何内容匹配的不同行。这可能是其性能的最佳选择。不过,我想知道,在您的应用程序中,按字母顺序排列前24个标题的重要性,以及为什么这对于放入视图很重要。
SELECT lots, of, stuff .... ORDER BY something LIMIT number
是一个臭名昭着的性能反模式。为什么? MySQL必须对大量数据进行排序,只丢弃少量数据。视图定义的局限性使您难以在视图中更有效地执行某些操作。
您没有告诉我们games_titles.id
是否被编入索引。它需要编入索引。如果它是主键,则将其编入索引。