Я много читал и гуглял по этому вопросу, и я не могу найти удовлетворительного ответа, поэтому буду признателен за любую помощь.Большинство ответов, которые я нахожу, близки к моей ситуации, но не обращаются к ней (и попытка следовать решениям не принесла мне пользы).
См. Правку № 2 ниже для лучшего примера
[Это был оригинальный вопрос, но он не очень хорошо отражает то, что я спрашиваю.]
Скажем, у меня есть 2 таблицы, каждая с 4 столбцами:
- ключ (int, автоинкремент)
- c1 (дата)
- c2 (varchar длины 3)
- c3 (также varchar длины3)
И я хочу выполнить следующий запрос:
SELECT t.c1, t.c2, COUNT(*)
FROM test1 t
LEFT JOIN test2 t2 ON t2.key = t.key
GROUP BY t.c1, t.c2
Оба поля key
проиндексированы как первичные ключи.Я хочу получить количество строк, возвращаемых в каждой группе c1, c2.
Когда я объясняю этот запрос, я получаю "использование временного; использование сортировки файлов".Фактическая таблица, для которой я выполняю этот запрос, содержит более 500 000 строк, так что это означает, что этот запрос занимает много времени.
Итак, мой вопрос (при условии, что я не делал ничего плохого в запросе): есть лиспособ индексировать эту таблицу, чтобы исключить временное использование / сортировку файлов?
Заранее спасибо за любую помощь.
Редактировать
Вот таблицаопределение (в этом примере обе таблицы идентичны - на самом деле это не так, но я не уверен, что это имеет значение на данном этапе):
CREATE TABLE `test1` (
`key` int(11) NOT NULL auto_increment,
`c1` date NOT NULL,
`c2` varchar(3) NOT NULL,
`c3` varchar(3) NOT NULL,
PRIMARY KEY (`key`),
UNIQUE KEY `c1` (`c1`,`c2`),
UNIQUE KEY `c2_2` (`c2`,`c1`),
KEY `c2` (`c2`,`c3`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
Полный оператор EXPLAIN:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 tracking.t.key 1 Using index
Это только для моих примеров таблиц.В моих реальных таблицах строки для t говорят 500 000+ (каждая строка в таблице, хотя это может быть связано с чем-то другим).
Edit # 2
Вот более конкретный пример, чтобы лучше объяснить мою ситуацию.
Допустим, у меня есть данные о бейсбольных матчах Малой лиги.У меня есть две таблицы.Один хранит данные об играх:
CREATE TABLE `ex_games` (
`game_id` int(11) NOT NULL auto_increment,
`home_team` int(11) NOT NULL,
`date` date NOT NULL,
PRIMARY KEY (`game_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
Другой хранит данные о летучих мышах в каждой игре:
CREATE TABLE `ex_atbats` (
`ab_id` int(11) NOT NULL auto_increment,
`game` int(11) NOT NULL,
`team` int(11) NOT NULL,
`player` int(11) NOT NULL,
`result` tinyint(1) NOT NULL,
PRIMARY KEY (`hit_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
Итак, у меня два вопроса.Давайте начнем с простой версии: я хочу вернуть список игр с подсчетом количества бит в каждой игре.Поэтому я думаю, что сделал бы что-то вроде этого:
SELECT date, home_team, COUNT(h.ab_id) FROM `ex_atbats` h
LEFT JOIN ex_games g ON g.game_id = h.game
GROUP BY g.game_id
Этот запрос использует файловую сортировку / временный.Есть ли лучший способ структурировать это или индексировать таблицы, чтобы избавиться от этого?
Затем, более сложная часть: скажем, теперь я хочу не только включить подсчет количества в битах, но ивключить подсчет количества битов, которым предшествовала бита с одинаковым результатом той же командой.Я предполагаю, что это будет что-то вроде:
SELECT g.date, g.home_team, COUNT(ab.ab_id), COUNT(ab2.ab_id) FROM `ex_atbats` ab
LEFT JOIN ex_games g ON g.game_id = ab.game
LEFT JOIN ex_atbats ab2 ON ab2.ab_id = ab.ab_id - 1 AND ab2.result = ab.result
GROUP BY g.game_id
Это правильный способ структурировать этот запрос?При этом также используется сортировка файлов / временная.
Так каков оптимальный способ выполнения этих задач?
Еще раз спасибо.