|
|
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
Есть 2 запроса, каждый из которых возвращает множество идентификаторов (по 3000 штук) Нужно найти их пересечение. Просто-напросто эти 2 запроса я вначале объединял через INNER JOIN как положено с использованием индексов. Такой запрос выполняется не очень быстро. Все варианты с разными индексами и разными комбинациями условий испробовал - результат не устраивает. В то же время каждый из подзапросов отдельно выполняется в 10 раз быстрее. Вот и хочу последовательно их выполнить и найти пересечение. Можно это сделать и на уровне php, но на уровне MySQL должно быть быстрее (т.к. нет лишней передачи данных между сервером и клиентом + выполняется скомпилированный MySQL-код - быстрее интерпретируемого php) Попробовал так: Код: sql 1. 2. Но такой вариант выполняется медленнее, чем первоначальный (т.к. индексов в этом запросе нет, то перебираются каждый с каждым). Т.е. здесь нужно получать НЕ декартово произведение, а выполнить элементарную арифметическую операцию со списками (пересечение списков). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.07.2015, 19:54:18 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
Если сделать так: Код: sql 1. то MySQL начинает выполнять QUERY2 для каждой записи из QUERY1 MySQL настолько туп, что не может определить, что запрос QUERY2 никак не связан с внешним запросом QUERY1 ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.07.2015, 21:56:31 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
Т.е. мне вообще непонятно, как в MySQL: а) ОДНОКРАТНО выполнить подзапрос (который никак не связан с основным запросом) б) проверить вхождение идентификатора записи из основного запроса в множество идентификаторов, возвращённых вложенным подзапросом в) при этом скорость выполнения такого запроса должна быть приблизительно такой же (разве что чуть-чуть больше), что и отдельное последовательное выполнение этих запросов ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.07.2015, 22:15:02 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
Cyrax_02MySQL настолько туп, что не может определить, что запрос QUERY2 никак не связан с внешним запросом QUERY1 ?да в 5.6 вроде поправили, но насколько качественно, хз Cyrax_02как Код: sql 1. 2. 3. 4. 5. если не устраивает, давайте конкретный текст вашего "каменного цветка" ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.07.2015, 07:22:53 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
Cyrax_02Т.е. мне вообще непонятно, как в MySQL: в) при этом скорость выполнения такого запроса должна быть приблизительно такой же (разве что чуть-чуть больше), что и отдельное последовательное выполнение этих запросов Мне кажется это вообще не реально . Сама выборка гораздо менее затратная штука, чем последующая связка. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.07.2015, 07:50:45 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
tanglir Код: sql 1. 2. 3. 4. 5. Этот вариант я уже прокомментировал: авторПопробовал так: Код: sql 1. 2. Но такой вариант выполняется медленнее, чем первоначальный (т.к. индексов в этом запросе нет, то перебираются каждый с каждым). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.07.2015, 11:58:09 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
авторМне кажется это вообще не реально. Сама выборка гораздо менее затратная штука, чем последующая связка. Как мы сами убедились, на уровне декартовых множеств связка выполняется слишком медленно (очевидно, это связано с тем, что работа идёт со строками, а не с числами + обусловлено декартовой логикой). Посему нужно вычислять не декартово произведение, а арифметическое. Арифметическое произведение числовых списков. Либо заставить MySQL выполнять независимый вложенный запрос в WHERE только 1 раз ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.07.2015, 12:00:51 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
Cyrax_02Этот вариант я уже прокомментировал: авторПопробовал так: Код: sql 1. 2. Но такой вариант выполняется медленнее, чем первоначальный (т.к. индексов в этом запросе нет, то перебираются каждый с каждым).Прокомментировали, только вот ни реального запроса, ни хотя бы планов не показали. И почему "WHERE COND1" - снаружи? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.07.2015, 12:48:44 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
Cyrax_02, Добрый день. Если query1.id уникальный, то вашу задачу можно решить через UNION ALL + group by. Почти аналогичная задача приводилась 16945040 , а решение приводил тут 16949405 PS. Было бы здорово, если при постановке задачи приводить таблички с данными, а то писать SQL скрипты как-то не охото. С уважением, biwed.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.07.2015, 13:44:15 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
Cyrax_02Если сделать так: Код: sql 1. то MySQL начинает выполнять QUERY2 для каждой записи из QUERY1 MySQL настолько туп, что не может определить, что запрос QUERY2 никак не связан с внешним запросом QUERY1 ? не должен он так делать, что то тут не так ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.07.2015, 14:09:03 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
bochkovCyrax_02Если сделать так: Код: sql 1. то MySQL начинает выполнять QUERY2 для каждой записи из QUERY1 MySQL настолько туп, что не может определить, что запрос QUERY2 никак не связан с внешним запросом QUERY1 ?не должен он так делать, что то тут не такТем не менее, такой баг есть. Исправлен он только начиная с версии 5.6. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.07.2015, 14:14:39 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
авторне должен он так делать, что то тут не так Именно так и происходит. Проверил в режиме профилирования авторЕсли query1.id уникальный, то вашу задачу можно решить через UNION ALL + group byТочно. А ведь сам не догадался... Только в Вашем варианте ещё having нужно будет использовать. Завтра протестирую этот вариант и сравню со своим (свой вариант я тоже придумал и тоже на UNION). Отпишусь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.07.2015, 21:49:47 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
miksoftbochkovпропущено... не должен он так делать, что то тут не такТем не менее, такой баг есть. Исправлен он только начиная с версии 5.6. да, а меня всегда это удивляло...ведь есчё до работы с базой, просто читая книжку по мусклу без привязки к субд - уже знал, что есть кореллированные подзапросы и независимые, и потом очень удивился что мускл их не различает ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.07.2015, 12:14:02 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
alex564657498765453miksoftТем не менее, такой баг есть. Исправлен он только начиная с версии 5.6.да, а меня всегда это удивляло...ведь есчё до работы с базой, просто читая книжку по мусклу без привязки к субд - уже знал, что есть кореллированные подзапросы и независимые, и потом очень удивился что мускл их не различаетВообще - различает. Баг касается только конструкции IN (SELECT ... ). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.07.2015, 12:53:36 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
авторВообще - различает. Баг касается только конструкции IN (SELECT ... )Если только этой конструкции, тогда её нужно переконструировать так, чтобы логика осталась прежней, но конструкция - иной (в которой глюк не наблюдается). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.07.2015, 12:59:56 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
Cyrax_02авторВообще - различает. Баг касается только конструкции IN (SELECT ... )Если только этой конструкции, тогда её нужно переконструировать так, чтобы логика осталась прежней, но конструкция - иной (в которой глюк не наблюдается).Собственно, так всегда и делаем - советуем переписать через JOIN или через EXISTS. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.07.2015, 13:02:08 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
Результат таков: 1) Классический вариант с INNER JOIN и с использованием наиболее подходящих индексов: 0.08 сек 2) Вариант с IN (SELECT) в версии MySQL до 5.6: 15 сек (подзапрос выполняется много раз - баг MySQL) 3) Вариант с EXISTS (коррелированный подзапрос): 15 сек 4) Мой вариант (получение 2 наборов идентификаторов - на уровне SQL, вычисление пересечения - на уровне php): Код: sql 1. 2. 3. 4. Код: php 1. 2. Здесь запрос выполняется = 0.0238-0.241 сек, [explode + intersect] = 0.0050-0.0052 сек. Итого: 0.0289-0.0294 сек 5) Вариант, предложенный biwed.ru : Код: sql 1. 2. 3. 4. 5. 6. Здесь обязательно: а) должны присутствовать DISTINCT (чтобы в пределах одной группы идентификаторов нельзя было набрать [intersect = 2]) б) должен быть UNION ALL (чтобы сохранить все идентификаторы, присутствующие в обоих выборках) Такой запрос выполняется 0.0277-0.283 сек , что на 0.001 сек быстрее предыдущего варианта (вывод достоверен - тестировал много раз). Причём если во второй выборке не указывать имена полей [AS id] и [AS intersect] (во второй выборке они не обязательны), то запрос будет выполняться на 0.0005 сек медленнее и соответственно, выигрыш по сравнению с предыдущим вариантом составит 0.0005 сек . ------------------------------------------------------------------------------------------------------ 6) Вариант с IN (SELECT) в версии MySQL 5.6 и выше: ??? сек Скорее всего, этот вариант сработает быстрее всех предложенных. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.07.2015, 23:06:31 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
авторТакой запрос выполняется 0.0277-0.283 сек Опечатка. Должно быть так: 0.0277-0. 0 283 сек ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.07.2015, 23:11:12 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
Cyrax_02, Добрый день. Cyrax_02 Результат таков: 5) Вариант, предложенный biwed.ru : Код: sql 1. 2. 3. 4. 5. 6. Здесь обязательно: а) должны присутствовать DISTINCT (чтобы в пределах одной группы идентификаторов нельзя было набрать [intersect = 2]) б) должен быть UNION ALL (чтобы сохранить все идентификаторы, присутствующие в обоих выборках) DISTINCT можно убрать переписав запрос. Получится как-то так. Код: sql 1. 2. 3. 4. 5. 6. С уважением, biwed.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.07.2015, 03:30:40 |
|
||
|
Пересечение наборов (списков) на уровне SQL-запроса
|
|||
|---|---|---|---|
|
#18+
biwed.ruDISTINCT можно убрать, переписав запрос. Получится как-то так: Код: sql 1. 2. 3. 4. 5. 6. Данная модификация (без DISTINCT) ускоряет запрос ещё на 0.0015 сек . ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.07.2015, 13:44:29 |
|
||
|
|

start [/forum/topic.php?fid=47&gotonew=1&tid=1832923]: |
0ms |
get settings: |
8ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
67ms |
get topic data: |
10ms |
get first new msg: |
7ms |
get forum data: |
3ms |
get page messages: |
53ms |
get tp. blocked users: |
1ms |
| others: | 235ms |
| total: | 407ms |

| 0 / 0 |
