SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 11.12.2011 03:01:42

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Cовпадающий explain, но разное выполнение.

Приветствую, Коллеги.

Поделитесь плиз соображениями по сабжу.

Есть две похожих таблицы, которые отличаются только тем, что у первой индекс только на одно поле, а у второй - накрывающий, на оба поля в таблице.

CREATE TABLE `exp1_1440_t` (
  `t` int(11) NOT NULL AUTO_INCREMENT,
  `d` bigint(20) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  KEY `t` (`t`)
) ENGINE=MyISAM AUTO_INCREMENT=1441 DEFAULT CHARSET=utf8;

CREATE TABLE `exp1_1440_td` (
  `t` int(11) NOT NULL AUTO_INCREMENT,
  `d` bigint(20) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  KEY `td` (`t`,`d`)
) ENGINE=MyISAM AUTO_INCREMENT=1441 DEFAULT CHARSET=utf8;


В каждой таблице по 1440 записей, дамп приложен.

Цель - запросом, который вписывается в реляционную модель БД выбрать максимальный перепад.

Рассматриваются два варианта, возвращающих один и тот же результат, и построенные схожим образом.

На таблице exp1_1440_t c одиночным индексом на поле t:

SELECT MAX((SELECT d FROM exp1_1440_t t2 WHERE t2.t>t1.t ORDER BY t2.t LIMIT 1) - t1.d) FROM exp1_1440_t t1;
и
SELECT MAX(t1.d-(SELECT d FROM exp1_1440_t t2 WHERE t2.t<t1.t ORDER BY t2.t DESC LIMIT 1)) FROM exp1_1440_t t1;

Выполняются они примерно одно и то же время - 1.16 сек.

explain'ы совпадают.

Код:

mysql> explain SELECT MAX((SELECT d FROM exp1_1440_t t2 WHERE t2.t>t1.t ORDER BY t2.t LIMIT 1) - t1.d) FROM exp1_1440_t t1;
+----+--------------------+-------+-------+---------------+------+---------+------+------+-------------+
| id | select_type        | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+--------------------+-------+-------+---------------+------+---------+------+------+-------------+
|  1 | PRIMARY            | t1    | ALL   | NULL          | NULL | NULL    | NULL | 1440 |             |
|  2 | DEPENDENT SUBQUERY | t2    | index | t             | t    | 4       | NULL |    1 | Using where |
+----+--------------------+-------+-------+---------------+------+---------+------+------+-------------+
2 rows in set (0.00 sec)

mysql> explain SELECT MAX(t1.d-(SELECT d FROM exp1_1440_t t2 WHERE t2.t<t1.t ORDER BY t2.t DESC LIMIT 1)) FROM exp1_1440_t t1;
+----+--------------------+-------+-------+---------------+------+---------+------+------+-------------+
| id | select_type        | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+--------------------+-------+-------+---------------+------+---------+------+------+-------------+
|  1 | PRIMARY            | t1    | ALL   | NULL          | NULL | NULL    | NULL | 1440 |             |
|  2 | DEPENDENT SUBQUERY | t2    | index | t             | t    | 4       | NULL |    1 | Using where |
+----+--------------------+-------+-------+---------------+------+---------+------+------+-------------+
2 rows in set (0.00 sec)

Все вроде логично.

Но если использовать накрывающий индекс td(t,d), то становится непонятней.
explain'ы опять же совпадают:

Код:

mysql> explain SELECT MAX((SELECT d FROM exp1_1440_td t2 WHERE t2.t>t1.t ORDER BY t2.t LIMIT 1) - t1.d) FROM exp1_1440_td t1;
+----+--------------------+-------+-------+---------------+------+---------+------+------+--------------------------+
| id | select_type        | table | type  | possible_keys | key  | key_len | ref  | rows | Extra                    |
+----+--------------------+-------+-------+---------------+------+---------+------+------+--------------------------+
|  1 | PRIMARY            | t1    | index | NULL          | td   | 13      | NULL | 1440 | Using index              |
|  2 | DEPENDENT SUBQUERY | t2    | index | td            | td   | 13      | NULL |    1 | Using where; Using index |
+----+--------------------+-------+-------+---------------+------+---------+------+------+--------------------------+
2 rows in set (0.00 sec)

mysql> explain SELECT MAX(t1.d-(SELECT d FROM exp1_1440_td t2 WHERE t2.t<t1.t ORDER BY t2.t DESC LIMIT 1)) FROM exp1_1440_td t1;
+----+--------------------+-------+-------+---------------+------+---------+------+------+--------------------------+
| id | select_type        | table | type  | possible_keys | key  | key_len | ref  | rows | Extra                    |
+----+--------------------+-------+-------+---------------+------+---------+------+------+--------------------------+
|  1 | PRIMARY            | t1    | index | NULL          | td   | 13      | NULL | 1440 | Using index              |
|  2 | DEPENDENT SUBQUERY | t2    | index | td            | td   | 13      | NULL |    1 | Using where; Using index |
+----+--------------------+-------+-------+---------------+------+---------+------+------+--------------------------+
2 rows in set (0.00 sec)

А вот время выполнения сильно отличается

Код:

mysql> SELECT MAX((SELECT d FROM exp1_1440_td t2 WHERE t2.t>t1.t ORDER BY t2.t LIMIT 1) - t1.d) FROM exp1_1440_td t1;
+-----------------------------------------------------------------------------------+
| MAX((SELECT d FROM exp1_1440_td t2 WHERE t2.t>t1.t ORDER BY t2.t LIMIT 1) - t1.d) |
+-----------------------------------------------------------------------------------+
|                                                                                99 |
+-----------------------------------------------------------------------------------+
1 row in set (0.41 sec)

mysql> SELECT MAX(t1.d-(SELECT d FROM exp1_1440_td t2 WHERE t2.t<t1.t ORDER BY t2.t DESC LIMIT 1)) FROM exp1_1440_td t1;
+--------------------------------------------------------------------------------------+
| MAX(t1.d-(SELECT d FROM exp1_1440_td t2 WHERE t2.t<t1.t ORDER BY t2.t DESC LIMIT 1)) |
+--------------------------------------------------------------------------------------+
|                                                                                   99 |
+--------------------------------------------------------------------------------------+
1 row in set (2.78 sec)

Собственно, в этом и вопрос - в чем разница в выполнении этих запросов?, почему такая существенная разница в скорости?


Прикрепленные файлы:
Attachment Icon d.sql, Размер: 43,338 байт, Скачано: 951

Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#2 11.12.2011 18:56:39

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Cовпадающий explain, но разное выполнение.

Прикольно smile

Различие на этапе Sending data в подзапросах. Ощущение, что это overhead
из-за того, что приходится разворачивать индекс в памяти (бегать задом напе-
ред). Возможно, какой-то плохо оптимизированный кусок кода в этом месте.

Неактивен

 

#3 11.12.2011 19:02:56

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Cовпадающий explain, но разное выполнение.

Класс! А мораль отсюда можно какую-то вывести?


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#4 11.12.2011 19:58:56

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Cовпадающий explain, но разное выполнение.

Мораль проста: не нужно использовать базу данных в качестве языка программирования wink

Неактивен

 

#5 11.12.2011 21:33:09

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Cовпадающий explain, но разное выполнение.

Ну то есть либо вытащить все данные из таблицы на клиент и там на процедурном языке спокойно посчитать всё что нужно, либо курсором пробежать по таблице в хранимой процедурке и сделать примерно то же самое? smile


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#6 12.12.2011 01:26:19

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Cовпадающий explain, но разное выполнение.

Я подозреваю, что даже в базе пробежать с переменной один раз по таблице
будет быстрее wink

Неактивен

 

#7 12.12.2011 01:29:40

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Cовпадающий explain, но разное выполнение.

Понятно. Спасибо smile.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#8 12.12.2011 10:44:54

evgeny
Гуру
Зарегистрирован: 04.05.2009
Сообщений: 335

Re: Cовпадающий explain, но разное выполнение.

По моему ещё один классический пример когда эффективно использовать переменные.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson