sql - MySQL查询有时还可以,其他时候需要5分钟!

标签 sql mysql indexing

我有一张用于计算 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 秒。

我们非常欢迎任何帮助。 谢谢! 哈南

下面是建议查询的解释:

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

显示创建表分数

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 秒!

最佳答案

确保您有以下索引:

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

这些查询与第一个查询相同,但如果您的条件没有选择性,则更有用。

这两篇文章解释了查询的工作原理:

关于sql - MySQL查询有时还可以,其他时候需要5分钟!,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3864229/

相关文章:

R:具有重复时间索引条目的时间序列

mysql - 更改 mysql 表中的主键列时出错

php - 使用准备好的语句在一个查询中修改多个表

mysql - 无法删除数据,MySQL

MySQL 映射表插入约束不起作用

java - 无法从 lucene 索引读取字段内容

sql-server-2008 - 在 SQL Server 数据库中删除索引

sql - TDD 构造器 Golang

mysql - SQL SELECT 来自多个表或 JOIN

MySQL 在关系数据库的同一列中存在多个 where