Производительность MySQL с GROUP BY и JOIN - PullRequest
3 голосов
/ 01 июля 2011

Проведя много времени с вариантами этого вопроса, я задаюсь вопросом, может ли кто-нибудь помочь мне оптимизировать этот запрос или индексы.

У меня есть три временные таблицы ref1, ref2, ref3, все они определены ниже: ref1 и ref2 имеют около 6000 строк, а ref3 - только 3 строки:

CREATE TEMPORARY TABLE ref1 (
  id INT NOT NULL AUTO_INCREMENT,
  val INT,
  PRIMARY KEY (id)
)
ENGINE = MEMORY;

Медленный запрос к таблице примерно так: около 1М строк:

CREATE TABLE t1 (
  d DATETIME NOT NULL,
  id1 INT NOT NULL,
  id2 INT NOT NULL,
  id3 INT NOT NULL,
  x INT NULL,
  PRIMARY KEY (id1, d, id2, id3)
)
ENGINE = INNODB;

Запрос в вопросе:

SELECT id1, SUM(x)
  FROM t1
  INNER JOIN ref1 ON ref1.id = t1.id1
  INNER JOIN ref2 ON ref2.id = t1.id2
  INNER JOIN ref3 ON ref3.id = t1.id3
  WHERE d BETWEEN '2011-03-01' AND '2011-04-01'
  GROUP BY id1;

Временные таблицы используются для фильтрации результирующего набора только по элементам, которые ищет пользователь.

EXPLAIN

+----+-------------+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref              | rows | Extra                           |
+----+-------------+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
|  1 | SIMPLE      | ref1  | ALL    | PRIMARY       | NULL    | NULL    | NULL             | 6000 | Using temporary; Using filesort |
|  1 | SIMPLE      | t1    | ref    | PRIMARY       | PRIMARY | 4       | med31new.ref1.id |   38 | Using where                     |
|  1 | SIMPLE      | ref3  | ALL    | PRIMARY       | NULL    | NULL    | NULL             |    3 | Using where; Using join buffer  |
|  1 | SIMPLE      | ref2  | eq_ref | PRIMARY       | PRIMARY | 4       | med31new.t1.id2  |    1 |                                 |
+----+-------------+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+

(в другой системе с ~ 5M строками EXPLAIN покажет t1 первым в списке, с "Использованием где; Использование индекса; Использование временным; Использование сортировки файлов")

Есть ли что-то очевидное, чего мне не хватает, что помешало бы использовать временную таблицу?

Ответы [ 3 ]

2 голосов
/ 01 июля 2011

Первая файловая сортировка не означает, что файл записан на диске для выполнения сортировки, это имя алгоритма быстрой сортировки в mySQL, проверьте что делает с помощью filesort-mean-in-mysql .

Таким образом, проблемное ключевое слово в вашем объяснении - Using temporary, а не Using filesort. Для этого вы можете поиграть с tmp_table_size & max_heap_table_size (поместите одинаковые значения в оба), чтобы обеспечить больше работы в памяти и избежать создания временной таблицы, отметьте эту ссылку на тему с замечаниями об ошибках документации .

Тогда вы можете попробовать другую политику индексации и посмотреть результаты, но не пытайтесь избежать сортировки файлов.

Последнее, не связанное, вы делаете SUM(x), но x может принимать значения NULL, SUM(COALESCE(x) , 0) может быть лучше, если вы не хотите, чтобы какое-либо значение NULL в Группе делало вашу сумму NULL.

0 голосов
/ 20 июля 2011

Разве это не:

SELECT id1, SUM(x)
  FROM t1
  INNER JOIN ref1 ON ref1.id = t1.id1
  INNER JOIN ref2 ON ref2.id = t1.id2
  INNER JOIN ref3 ON ref3.id = t1.id3
  WHERE d BETWEEN '2011-03-01' AND '2011-04-01'
  GROUP BY id1;

точно соответствует:

select id1, SUM(x)
  FROM t1
  WHERE d BETWEEN '2011-03-01' AND '2011-04-01'
  group by id1;

Для чего используются дополнительные таблицы? Я думаю, что временная таблица, упомянутая в другом ответе, ссылается на то, что MySQL создает временную таблицу во время выполнения запроса. Если вы надеетесь создать подзапрос (или таблицу), который минимизирует количество операций, требуемых в соединении, это может ускорить запрос, но я не вижу выбранных объединенных данных.

0 голосов
/ 01 июля 2011

Добавьте индекс ТОЛЬКО ДАТА. Поскольку это критерий первой таблицы, а остальные - просто объединения, она будет оптимизирована в первую очередь с учетом ДАТЫ ... объединения вторичны.

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