SQLinfo.ru - Все о MySQL

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

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

Вы не зашли.

#1 04.09.2019 11:58:46

klow
Старожил
Зарегистрирован: 06.12.2014
Сообщений: 411

Быстродействие

Добрый день!
Прошу помощи. Запутался даже не в трех соснах, а в дух.
Есть запрос

SELECT
  s.id, s.TId, t.id kid
FROM
(SELECT
  seq id,
  zb_GetTrackId(CONCAT('http://site.com/maps/?l=1&v=1&id=', seq)) TId
FROM seq_1_to_100) s
  JOIN tracks t ON t.id = s.id
WHERE TId IS NOT NULL;

Он выполняется за миллисекунды
Но если его изменить JOIN tracks t ON t.id = s.TId
То он уже выполняется за секунды (14-16 сек). Почему так????
Функция zb_GetTrackId возвращает ID из URL.

Результат выполнения запроса в обоих случаях одинаков:
id BIGINT(20), TId INT(11), kid INT(11)
1    1    1
34    34    34
42    42    42
44    44    44
47    47    47
48    48    48
53    53    53
60    60    60
69    69    69
70    70    70
71    71    71
72    72    72
73    73    73
74    74    74
75    75    75
76    76    76

План запроса в первом случае
seq_1_to_100    1    SIMPLE    index    PRIMARY    PRIMARY    8        100    Using where; Using index
t    1    SIMPLE    eq_ref    PRIMARY    PRIMARY    4    seq_1_to_100.seq    1    Using where; Using index

Во втором
seq_1_to_100    1    SIMPLE    index        PRIMARY    8        100    Using where; Using index
t    1    SIMPLE    index        IDX_tracks_Department_id    4        20873    Using where; Using index; Using join buffer (flat, BNL join)

Почему не используется PRIMARY, а используется индекс IDX_tracks_Department_id? Он каким боком тут?
Таблица
CREATE TABLE tracks (
  id int(11) NOT NULL AUTO_INCREMENT,
  Department_id int(11) NOT NULL,
  Name varchar(50) NOT NULL,
  Parent_id int(11) DEFAULT NULL,
  Nagr_id bigint(20) DEFAULT NULL,
  CorrDate datetime NOT NULL,
  UserName varchar(50) NOT NULL,
  PRIMARY KEY (id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 27308,
AVG_ROW_LENGTH = 862,
CHARACTER SET utf8,
COLLATE utf8_unicode_ci;

ALTER TABLE tracks
ADD INDEX IDX_tracks_Department_id (Department_id);

ALTER TABLE tracks
ADD CONSTRAINT FK_tracks_department_Id FOREIGN KEY (Department_id)
REFERENCES department (Id);

ALTER TABLE tracks
ADD CONSTRAINT FK_tracks_tracks_id FOREIGN KEY (Parent_id)
REFERENCES tracks (id) ON DELETE CASCADE ON UPDATE CASCADE;


Версия MariaDB - 10.2.26

Отредактированно klow (04.09.2019 12:11:13)


Прикрепленные файлы:
Attachment Icon plan 1.png, Размер: 9,022 байт, Скачано: 331

Неактивен

 

#2 06.09.2019 09:31:43

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

Re: Быстродействие

Выглядит как бага. Пробовали запустить на ванильном MySQL?

Я бы попробовал сделать воспроизводимый случай и зарепортил в Марию.
Конкретно про починку «чтобы работало» — можно добавить use index / force index на вторую таблицу. Возможно, базе также не будет сносить крышу, если условие на tid вынести в подзапрос (тогда снаружи останется только условие на id): это в любом случае только ускорит его.

Неактивен

 

#3 06.09.2019 09:45:41

klow
Старожил
Зарегистрирован: 06.12.2014
Сообщений: 411

Re: Быстродействие

Спасибо за ответ!
На MySQL не пробовал.
use index / force index - пробовал. Без результата. Был очень удивлен.
Не думаю, что условие на tid в подзапросе укорит выполнение, я не про этот случай, а в общем. Так как нужно делать условие не на 

TId IS NOT NULL
, а повторно вызывать функцию
zb_GetTrackId(CONCAT('http://site.com/maps/?l=1&v=1&id=', seq)) = IS NOT NULL
. Получается функция вызывается два раза для одной строки.
Если я правильно понял смысл предложения.
В данном конкретном случае это точно ничего не меняет - проверил.
У меня складывается впечатление, что я что-то элементарное упускаю. Ну не может быть такая бага!

Отредактированно klow (06.09.2019 09:47:58)

Неактивен

 

#4 06.09.2019 09:59:01

klow
Старожил
Зарегистрирован: 06.12.2014
Сообщений: 411

Re: Быстродействие

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

Неактивен

 

#5 06.09.2019 11:01:52

klow
Старожил
Зарегистрирован: 06.12.2014
Сообщений: 411

Re: Быстродействие

Во вложении скрипты для воспроизведения проблемы. Кто может проверить у себя?


Прикрепленные файлы:
Attachment Icon test.sql, Размер: 560 байт, Скачано: 838

Неактивен

 

#6 06.09.2019 13:00:30

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

Re: Быстродействие

Так. У меня воспроизводится (MySQL 8.0.17), и заодно там написан ответ, почему так.
Если сделать EXPLAIN EXTENDED, то видно, что MySQL пытается вести себя умно — преобразовывает запрос:

[surfer] root test > explain SELECT   s.id1, s.Id2, t.id id3 FROM (SELECT   seq id1,   GetId(seq) Id2 FROM seq_1_to_20000 s) s   JOIN t ON t.id = s.id2;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+-------+----------+-----------------------------------------------------------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows  | filtered | Extra                                                           |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+-------+----------+-----------------------------------------------------------------+
|  1 | SIMPLE      | s     | NULL       | index | NULL          | PRIMARY | 4       | NULL | 11822 |   100.00 | Using index                                                     |
|  1 | SIMPLE      | t     | NULL       | index | NULL          | PRIMARY | 4       | NULL | 11822 |    10.00 | Using where; Using index; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+-------+----------+-----------------------------------------------------------------+
2 rows in set, 1 warning (0.00 sec)

[surfer] root test > show warnings\G
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`s`.`seq` AS `id1`,`GetId`(`test`.`s`.`seq`) AS `Id2`,`test`.`t`.`id` AS `id3` from `test`.`seq_1_to_20000` `s` join `test`.`t` where (`test`.`t`.`id` = `GetId`(`test`.`s`.`seq`))
1 row in set (0.00 sec)


Ожидаемое поведение получается путем отключения derived_merge в optimizer_switch. Но багу отправьте всё равно, пожалуйста.

Неактивен

 

#7 06.09.2019 13:09:43

klow
Старожил
Зарегистрирован: 06.12.2014
Сообщений: 411

Re: Быстродействие

Спасибо!
Кстати это именно тот скрипт, на который мне и нужен был. Именно на нем я и увидел этот баг, но переделал в подзапрос, чтобы исключить влияние скорости выполнения самой функции.

Неактивен

 

Board footer

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