MySQL Query иногда хорошо, в другое время занимает 5 минут! - PullRequest
2 голосов
/ 05 октября 2010

У меня есть таблица, которую я использую для рекордов игры для 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 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 секунд!

Ответы [ 3 ]

4 голосов
/ 05 октября 2010

Убедитесь, что у вас есть следующие индексы:

scores (game_id, game_size, game_level, date, id)
scores (game_id, game_size, game_level, name, place, score_string, id)

(любой из них может быть эффективным в зависимости от распределения данных).

Также может быть полезно добавить следующиеindex:

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

Этот запрос идентичен первому, но более полезен, если ваши условия не являются выборочными.

Эти две статьи объясняют, как работает запрос:

2 голосов
/ 05 октября 2010

Минимальный : Все поля в предложении where должны иметь один индекс (не объединенный).

Максимальный : Минимальный + имя, место, а также счетная строка.

Очень сложно сказать без дополнительной информации о количестве строк, распределении значений по проиндексированным полям и т. Д.

Имейте в виду: попытайтесь проиндексировать наиболее селективное поле или поле с равномерным распределением первым.

Поработайте над своей оценкой!

0 голосов
/ 05 октября 2010

Это большой труд для выполнения SQL-запроса.Найдите минимальное значение в одном столбце, сопоставьте другие столбцы и получите диапазон в другом, не говоря уже о сортировке.

Если у вас нет индексации, это займет много времени, как только вы получите многозаписей в таблице.Конечно, добавление слишком большого количества индексов сделает вставку длительной, поэтому вы не хотите переусердствовать.

Если вы выполните запрос и сразу же перезапустите его, mysql, скорее всего, будет кэшировать информацию, делая второй (и все последующие запросы) молниеносно.Я думаю, именно поэтому вы видите длинные запросы, а затем они ускоряются.Вам нужно использовать длительное время, чтобы узнать, насколько новые индексы помогут.Если вам нужно указать mysql, чтобы он избавился от кеша, вы можете использовать «очистить таблицы» (но будьте готовы к тому, что ваш запрос займет много времени).

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...