我有一张桌子用于高分iPhone游戏。 截至目前,查询已被禁用,因此游戏玩家无法看到分数: - (
表格包含以下字段:
Type Collation Attributes Null Default Extra Action
id int(11) No auto_increment
date date No
timestamp timestamp No CURRENT_TIMESTAMP
game_id tinyint(4) No
game_size tinyint(4) No
game_level tinyint(4) No
score float No
score_string char(11) utf8_general_ci No
name varchar(50) utf8_general_ci No
place varchar(50) utf8_general_ci No
device varchar(128) utf8_general_ci Yes NULL
我为game_id和game_size添加了一个双字段索引 这可能是问题,但我无法弄清楚为什么搜索需要5分钟......
这是占用所有时间的查询。 其他更简单的查询也需要很长时间。
SELECT SQL_CALC_FOUND_ROWS name, MIN(score_string) AS Expr1, place FROM
scores WHERE game_id="1" AND game_size = "5" AND game_level = "1"
AND date> "2005-04-14" GROUP BY name, place ORDER BY
MIN(score_string) Limit 0, 100;
当我在phpMyAdmin中测试时,它返回1秒,然后返回几秒0.0015秒,然后再返回1秒。
任何帮助都会受到欢迎。 谢谢! Hanaan
以下是针对建议查询的EXPLAIN:
EXPLAIN SELECT name, score_string, place
FROM scores s
WHERE game_id =1
AND game_size =15
AND game_level =1
AND id = (
SELECT id
FROM scores si
WHERE si.game_id =1
AND si.game_size =15
AND si.game_level =1
AND si.name = s.name
AND si.place = s.place
AND si.date > '2005-04-14'
ORDER BY si.game_id, si.game_size, si.game_level, si.name, si.place, si.score_string, si.id
LIMIT 1
)
ORDER BY game_id, game_size, game_level, score_string, id
LIMIT 100
d select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY s ref game_id,indx1,game_id_2 game_id_2 3 const,const,const 14034 Using where
2 DEPENDENT SUBQUERY si ref game_id,indx1,game_id_2 game_id 307 const,const,const,tmi_hcg.s.name,tmi_hcg.s.place 13 Using where
SHOW CREATE TABLE得分
CREATE TABLE `scores` (
`id` int(11) NOT NULL auto_increment,
`date` date NOT NULL,
`timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
`game_id` tinyint(4) NOT NULL,
`game_size` tinyint(4) NOT NULL,
`game_level` tinyint(4) NOT NULL,
`score` float NOT NULL,
`score_string` char(11) NOT NULL,
`name` varchar(50) NOT NULL,
`place` varchar(50) NOT NULL,
`device` varchar(128) default NULL,
PRIMARY KEY (`id`),
KEY `game_id` (`game_id`,`game_size`,`game_level`,`name`,`place`,`score_string`,`id`),
KEY `indx1` (`game_id`,`game_size`,`game_level`,`date`,`id`),
KEY `game_id_2` (`game_id`,`game_size`,`game_level`,`score_string`,`id`)
) ENGINE=MyISAM AUTO_INCREMENT=81564 DEFAULT CHARSET=utf8
似乎数据越接近今天,响应时间越长:
SELECT name, score_string, place
FROM scores s
WHERE game_id =1
AND game_size =15
AND game_level =1
AND id = (
SELECT id
FROM scores si
WHERE si.game_id =1
AND si.game_size =15
AND si.game_level =1
AND si.name = s.name
AND si.place = s.place
AND si.date > "2010-10-01"
ORDER BY si.game_id, si.game_size, si.game_level, si.name, si.place, si.score_string, si.id
LIMIT 1 )
ORDER BY game_id, game_size, game_level, score_string, id
LIMIT 100
这花费了惊人的49秒!
答案 0 :(得分:4)
确保您拥有以下索引:
scores (game_id, game_size, game_level, date, id)
scores (game_id, game_size, game_level, name, place, score_string, id)
(取决于数据分布,它们中的任何一个都可以有效)。
此外,添加以下索引可能很有用:
scores (game_id, game_size, game_level, score_string, id)
并将查询重写为:
SELECT name, score_string, place
FROM scores s
WHERE game_id = 1
AND game_size = 5
AND game_level = 1
AND id =
(
SELECT id
FROM scores si
WHERE si.game_id = 1
AND si.game_size = 5
AND si.game_level = 1
AND si.name = s.name
AND si.place = s.place
AND si.date > '2005-04-14'
ORDER BY
si.game_id, si.game_size, si.game_level, si.name, si.place, si.score_string, si.id
LIMIT 1
)
ORDER BY
game_id, game_size, game_level, score_string, id
LIMIT 100
这些查询与第一个查询相同,但如果您的条件不具有选择性,则更有用。
这两篇文章解释了查询的工作原理:
答案 1 :(得分:2)
最小:where子句中的所有字段都应该有一个索引(未合并)。
最大:最小+名称,地点,score_string。
如果没有关于行数,索引字段值的分布等的更多信息,很难说清楚。
请记住:尝试将最具选择性的字段或首先使用均匀分布的字段编入索引。
确定你的录取率!
答案 2 :(得分:0)
这对SQL查询来说有很多工作要做。找到一列中的最小值,匹配其他列并获得另一列中的范围,更不用说排序了。
如果您没有任何索引,一旦您在表中获得大量记录,这将花费大量时间。当然,放入太多的索引会使插入需要很长时间,所以你不想过度使用它。
如果你运行一个查询,并立即重新运行它,mysql可能会缓存信息,使第二个(和所有后续查询)闪电般快速。我认为这就是为什么你看到长时间的查询,然后他们加快。您需要使用很长时间来访问新索引将有多大帮助。如果你需要告诉mysql摆脱它的缓存,你可以使用“刷新表”(但为你的查询做好准备需要很长时间)。
希望有所帮助。