|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Тестирую переход с Mysql на PostgreSQL Столкнулся с проблемой есть простая таблица Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23.
В ней около 12 миллионов записей , задача вывести строки у который нет потомков (древовидная структура ) Делаю запрос Код: sql 1.
который длиться около 20 секунд , тот же запрос на Mysql занимает 0.21 секунды Подскажите пожалуйста, что не так с таблицей ? Eplain: Gather (cost=320462.73..792817.22 rows=1 width=49) Workers Planned: 2 -> Parallel Hash Left Join (cost=319462.73..791817.12 rows=1 width=49) Hash Cond: (geo.id = p.parent_id) Filter: (p.id IS NULL) -> Parallel Seq Scan on geo (cost=0.00..212933.33 rows=6128432 width=49) -> Parallel Hash (cost=212933.33..212933.33 rows=6128432 width=16) -> Parallel Seq Scan on geo p (cost=0.00..212933.33 rows=6128432 width=16) ... |
|||
:
Нравится:
Не нравится:
|
|||
12.09.2020, 14:00 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Вы уверены, что Код: sql 1.
а не Код: sql 1.
у Вас же Код: sql 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
12.09.2020, 16:09 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Уверен, left join проверка на потомков которых нет , т.е. where p.id ISNULL Проблема я думаю, не в запросе а в таблице, либо в тонких настройках БД ... |
|||
:
Нравится:
Не нравится:
|
|||
12.09.2020, 16:24 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
и сколько же у вас среди 12 млн записей с NULL ? и зачем вы хотите их ВСЕ и сразу? LIMIT надо бы юзать. Код: plsql 1.
это не нужно вообще, у вас же PK там и вопрос на миллион: а зачем вам вообще LEFT JOIN тут? Bekass проверка на потомков, которых нет для этого WHERE хватит. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.09.2020, 19:01 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Для того чтобы найти записи у которые НЕТ потомков, нужно выбрать по LEFT JOIN записи которых не существует, это как бы классический SQL запрос. nextval('geo_id_seq'::regclass) - ЭТО авто инкремет ключевого поля ... |
|||
:
Нравится:
Не нравится:
|
|||
12.09.2020, 22:47 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Bekass, я не вижу каким образом он 0.21s может занимать на mysql и никакими настройками базы вы такой скорости не получите. тут как ни делай а надо все строки проверять и никаким индексом это не вылечить. ps: explain analyze покажите - может получится ускорить раз в несколько но точно не до 200ms ... |
|||
:
Нравится:
Не нравится:
|
|||
12.09.2020, 23:11 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Bekass Для того чтобы найти записи у которые НЕТ потомков, нужно выбрать по LEFT JOIN записи которых не существует, это как бы классический SQL запрос. nextval('geo_id_seq'::regclass) - ЭТО авто инкремет ключевого поля а почему вы тут Код: sql 1. 2. 3. 4.
не можете просто написать: Код: sql 1. 2.
? ... |
|||
:
Нравится:
Не нравится:
|
|||
12.09.2020, 23:36 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Bekass nextval('geo_id_seq'::regclass) - ЭТО авто инкремет ключевого поля так сделайте тип bigserial вместо int8 ... |
|||
:
Нравится:
Не нравится:
|
|||
12.09.2020, 23:41 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Алексей Роза Bekass nextval('geo_id_seq'::regclass) - ЭТО авто инкремет ключевого поля так сделайте тип bigserial вместо int8 Такого типа нет, почитайте документацию и посмотрите во что превращается псевдотип serial/bigserial после создания и как он в plain text dump выглядит. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
13.09.2020, 09:14 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
где нет, в SQL-стандарте? Там дохрена чего нет, это нормально, он стааарый пофигу что там макрос разворачивает в команду "создать последовательность", половина PG на таких макросах это путь ООП и он правильный. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.09.2020, 09:18 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Алексей Роза Bekass Для того чтобы найти записи у которые НЕТ потомков, нужно выбрать по LEFT JOIN записи которых не существует, это как бы классический SQL запрос. nextval('geo_id_seq'::regclass) - ЭТО авто инкремет ключевого поля а почему вы тут Код: sql 1. 2. 3. 4.
не можете просто написать: Код: sql 1. 2.
? потому что это будет решение другой задачи... включите голову наконец и кончайте ересь советовать... чтобы выбрать все записи у которых нет потомков надо выбрать все записи вообще и далее убрать те из них которые упомянуты в parent_id в той же таблице (может в той же строке а может и в других каких то). Так что авторское решение вполне логичное (другой вопрос что ВОЗМОЖНО можно сделать быстрее а для этого надо понимать сколько уникальных parent_id в таблице). select count(distinct parent_id) from "public"."geo"; -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
13.09.2020, 09:18 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Алексей Роза где нет, в SQL-стандарте? Там дохрена чего нет, это нормально, он стааарый пофигу что там макрос разворачивает в команду "создать последовательность", половина PG на таких макросах это путь ООП и он правильный. при этом это макрос для ленивых людей... по факту в pg_dump и в отображении структуры таблицы внутри базы bigserial отображается именно как DEFAULT nextval('geo_id_seq'::regclass) (и чем меньше его использовать этот макрос тем лучше потому что он важные детали реализации скрывает, например тот факт что serial тип вполне может за пределы int поля выйти и об этом надо помнить). Вы хоть раз то в psql \d+ имя таблицы то делали с serial полем? -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
13.09.2020, 09:22 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
А я и не советую, вы почитайте внимательно, там вопрос. Это очень странная задача - лефтджойнить 12 лямов строк и все разом выводить... ... |
|||
:
Нравится:
Не нравится:
|
|||
13.09.2020, 09:24 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Может я опять что-то не доглядел, но объясните, как поле объявленное "id" int8 NOT NULL (т.е. не допускает вставки NULL) да еще и являющееся первичным ключем, может дать TRUE в условии id IS NULL? ... |
|||
:
Нравится:
Не нравится:
|
|||
13.09.2020, 09:28 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Алексей Роза А я и не советую, вы почитайте внимательно, там вопрос. Это очень странная задача - лефтджойнить 12 лямов строк и все разом выводить... потому что найти 'вывести строки у который нет потомков' по другому не решается... а вот ваши WHERE geo.id IS NULL AND geo.parent_id IS NULL решают совсем другую задачу (причем непонятно какую) Задачу можно обсуждать конечно, но сначала надо рабочее решение предложить а не явно неправильные варианты. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
13.09.2020, 09:29 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Guzya Может я опять что-то не доглядел, но объясните, как поле объявленное "id" int8 NOT NULL (т.е. не допускает вставки NULL) да еще и являющееся первичным ключем, может дать TRUE в условии id IS NULL? Так left join же, это значит что нет записей с таким parent_id у строки... что и соответствует решению... это стандартный с момента появления sql альтернативный метод записи запроса Код: plsql 1.
или вы про неверную идею Код: plsql 1. 2.
- так это к ее автору )). -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
13.09.2020, 09:33 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Maxim Boguk например тот факт что serial тип вполне может за пределы int поля выйти и об этом надо помнить поэтому все советуют делать сразу bigserial и не париться. Но когда есть 200% уверенность, что не вылезет, я таки ставлю serial. Maxim Boguk и чем меньше его использовать этот макрос тем лучше ну оставим это на полке "на вкус и цвет все фломастеры разные" мне в листинге нравится лаконичная запись "bigserial", там нужно быстренько глазами пробежать и всё понять если всё подряд разворачивать - это не дело. А то что \d+ показывает всё целиком никак не поможет эту последовательность ручками создать/удалить, всё равно в документацию лезть. Maxim Boguk Вы хоть раз то в psql \d+ имя таблицы то делали с serial полем? да написал пару инфосистем на пг. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.09.2020, 09:38 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Алексей Роза, - Почему у вас так много свободного времени, вы такой добродушный и веселый? Как вам это удаётся? - Я никогда ни с кем не спорю, особенно в интернете (и особенно если мне за это не платят почасовую ставку). - Но это-же невозможно! - Да, вы совершенно правы. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
13.09.2020, 09:50 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
[quot Maxim Boguk#22196035] Guzya select geo.* from geo where not exists (select from geo as p where geo.id = p.parent_id); -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru Результат не быстрее Left join В общем судя по экспертам с этого форума, с Mysql на PostgreSQL переходит , увы, не стоит ... |
|||
:
Нравится:
Не нравится:
|
|||
13.09.2020, 19:06 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Покажите план запроса с mysql. ... |
|||
:
Нравится:
Не нравится:
|
|||
13.09.2020, 20:45 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
[quot Bekass#22196196] Maxim Boguk пропущено... Результат не быстрее Left join В общем судя по экспертам с этого форума, с Mysql на PostgreSQL переходит , увы, не стоит 1)чтобы посоветовать что то внятное я запросил результаты explain analyze которые вы не прислали 2)я запросил результаты select count(distinct parent_id) from "public"."geo"; которые вы тоже не прислали 3)запросили план на mysql который вы тоже не прислали (и 0.21s для обработки 12M таблицы выглядит подозрительно мало как его не делай) 4)я бы еще посмотрел на explain (analyze, costs, buffers, timing) запроса с exists при включенном track_io_timing -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
13.09.2020, 21:05 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Maxim Boguk чтобы выбрать все записи у которых нет потомков надо выбрать все записи вообще и далее убрать те из них которые упомянуты в parent_id в той же таблице (может в той же строке а может и в других каких то). вообще-то надо выбрать все значения индекса ид для которых нет соответственного в индексе парент_ид. и для разницы зачитать остатние строки. для каких-нибудь структур типа сортированных списков алгоритмом типа мерджа( только анти), вполне может решаться "невероятно бистро", особо если "списки" уже в памяти, а проколов (исключений) для поднятия с диска записей "очень мало" относительно массы в 12 лямов,. которые душка пж так у порно вычитывать собирается по плану . а надо всего-то сравнить мощности множеств инд..... ... |
|||
:
Нравится:
Не нравится:
|
|||
14.09.2020, 08:35 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Maxim Boguk, 1) explain analyze select geo.* from geo LEFT JOIN geo as p ON geo.id = p.parent_id where p.id ISNULL LIMIT 100; Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
2) select count(distinct parent_id) from "public"."geo"; COUNT 2939789 https://prnt.sc/ugwwap 3) MYSQL Explain https://prnt.sc/ugwtwy Запрос https://prnt.sc/ugwuij COUNT: https://prnt.sc/ugwyrh 4) "я бы еще посмотрел на explain (analyze, costs, buffers, timing) запроса с exists при включенном track_io_timing" тут не совсем понял как делать ... |
|||
:
Нравится:
Не нравится:
|
|||
14.09.2020, 11:57 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Bekass Maxim Boguk, 3) MYSQL Explain https://prnt.sc/ugwtwy Запрос https://prnt.sc/ugwuij COUNT: https://prnt.sc/ugwyrh 4) "я бы еще посмотрел на explain (analyze, costs, buffers, timing) запроса с exists при включенном track_io_timing" тут не совсем понял как делать По mysql - а попробуйте выполнить и замерять время выполнения (это важно) для select count(*) from geo LEFT JOIN geo as p ON geo.id = p.parent_id where p.id ISNULL; потому что есть у меня подозрение почему вы такую скорость получаете на mysql по 4) set track_io_timing to on; explain (analyze, costs, buffers, timing) select geo.* from geo where not exists (select from geo as p where geo.id = p.parent_id); ... |
|||
:
Нравится:
Не нравится:
|
|||
14.09.2020, 17:03 |
|
Left join медленный запрос
|
|||
---|---|---|---|
#18+
Спасибо за помощь, Maxim [quot Maxim Boguk#22196748] Bekass Maxim Boguk, 3) По mysql - а попробуйте выполнить и замерять время выполнения (это важно) для select count(*) from geo LEFT JOIN geo as p ON geo.id = p.parent_id where p.id ISNULL; потому что есть у меня подозрение почему вы такую скорость получаете на mysql Дело в том что mysql как порядочная БД сортирует индексы, в выборке первые 1000 значений, понятное дело если в запрос ORDER BY добавить , то время увеличится, например Код: sql 1.
Выдаст 37, что не плохо https://prnt.sc/uh8s3v тот же запрос на POSTGRE https://prnt.sc/uh8w76 на меньшем количестве записей занимает 200с !!! 4) запрос выполнен : Код: sql 1. 2.
Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
... |
|||
:
Нравится:
Не нравится:
|
|||
14.09.2020, 23:17 |
|
|
start [/forum/topic.php?fid=53&msg=39998031&tid=1994471]: |
0ms |
get settings: |
9ms |
get forum list: |
12ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
270ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
55ms |
get tp. blocked users: |
1ms |
others: | 324ms |
total: | 687ms |
0 / 0 |