172 похожих чатов

Пытаюсь из одной таблицы в которой 1.5 млн записей выбрать

те записи которых нету в другой таблицы на 1 млн записей. С помощью запроса SELECT id FROM table WHERE id not in (SELECT id FROM temp) . Запрос что-то долго выполняется. Будет ли быстрей если заменить not exists ?

14 ответов

20 просмотров

https://t.me/pgsql/303899

Скорее всего быстрее будет LEFT OUTER JOIN, где поле в правой таблице NULL

Подскажите, кто знает, в подобных запросах подчиненный SELECT выполнится один раз, и его результаты будут использованы многократно, или для каждой записи (SELECT id FROM temp) будет выполняться повторно?

Dmitriy Sviridov
А в плане запроса этого не видно?

Придется ставить эксперимент

Юра
Придется ставить эксперимент

Там зависит от числа записей. Для небольшого числа - nested loop + index_scan, если очень много - merge_join, где-то посерединке (или если в одной таблице отбираемых записей гораздо меньше, чем в другой) - hash_join

Вангую что разницы не будет никакой. Думаю это как раз случай иллюстрирующий то что синтаксис языка SQL позволяет абстрагироваться от способа доступа, который оптимизатор выбирает на свое усмотрение. И ни что не мешает ему построить два идентичных плана на разные тексты запросов.

punkin ☘- Автор вопроса
Denis
Вангую что разницы не будет никакой. Думаю это как...

Поменял на запрос LEFT JOIN table1 ON (table2.id=table1.id) WHERE table1.id IS NULL . Отработал за 5 секунд . прошлый запрос спустя пол часа так и не завершился

punkin ☘
Поменял на запрос LEFT JOIN table1 ON (table2.id=t...

Похоже это какие-то заморочки оптимизатора постгреса. Тест create table t1 (a integer); create table t2 (a integer); insert into t1 values(1); insert into t1 values(2); insert into t1 values(3); insert into t1 values(4); insert into t1 values(5); insert into t1 values(6); insert into t1 values(7); insert into t2 values(1); insert into t2 values(2); insert into t2 values(3); insert into t2 values(4); insert into t2 values(5); analyze t1; analyze t2; explain select a from t1 where a not in (select a from t2); explain select * from t1 LEFT JOIN t2 ON (t1.a=t2.a) WHERE t2.a IS NULL; показывает что в случае с WHERE id not in (SELECT id FROM temp) он делает два вложенных seqscan и фильтр между ними: "Seq Scan on t1 (cost=1.06..2.15 rows=4 width=4)" " Filter: (NOT (hashed SubPlan 1))" " SubPlan 1" " -> Seq Scan on t2 (cost=0.00..1.05 rows=5 width=4)" а в случае LEFT JOIN - хэш антиджойн "Hash Anti Join (cost=1.11..2.23 rows=2 width=8)" " Hash Cond: (t1.a = t2.a)" " -> Seq Scan on t1 (cost=0.00..1.07 rows=7 width=4)" " -> Hash (cost=1.05..1.05 rows=5 width=4)" " -> Seq Scan on t2 (cost=0.00..1.05 rows=5 width=4)" К примеру Оракл в обоих случаях сразу делает хэш-джойн --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 4 (100)| | |* 1 | HASH JOIN ANTI NA | | 164 | 4264 | 4 (0)| 00:00:01 | | 2 | TABLE ACCESS FULL| T1 | 164 | 2132 | 2 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL| T2 | 164 | 2132 | 2 (0)| 00:00:01 | --------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("A"="A") ---------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 164 | 4264 | 4 (0)| 00:00:01 | |* 1 | FILTER | | | | | | |* 2 | HASH JOIN OUTER | | 164 | 4264 | 4 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL| T1 | 164 | 2132 | 2 (0)| 00:00:01 | | 4 | TABLE ACCESS FULL| T2 | 164 | 2132 | 2 (0)| 00:00:01 | ---------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("T2"."A" IS NULL) 2 - access("T1"."A"="T2"."A"(+))

Denis
Похоже это какие-то заморочки оптимизатора постгре...

Надо заметить, что filter hash он считает быстрее hash antijoin. В принцыпе логично: join требует ещё и размножать значения таблицы и помещать туда второе отношэние. Хотя тут, понятно, должэн бы догадаться, что ничего такого быть не можэт при left join null -- но не догадался. Впрочем, боюсь, этот пример не показателен -- маленькие таблицы без ключей и индэксов.

Ilya Anfimov
Надо заметить, что filter hash он считает быстрее ...

А пры чом тут ключи и индэксы? Таплицы джойнятся цэликом, бэз филтра. В вапросе вышэ 1.5млн записей в адной таплице и 1млн ва фтарой, какие туд индэксы.

Denis
А пры чом тут ключи и индэксы? Таплицы джойнятся ц...

> Таплицы джойнятся цэликом, бэз филтра. Это, в общем, некоторая математическая модэль одного этапа операцыи. Которая не очень прямо преобразуется в план запроса (точнее, вообще не имеет отношэния к реальности выполнения). >В вапросе вышэ 1.5млн записей Что было в запросе вышэ -- мы можэм только гадать, потому мне нет смысла обсуждать это серьёзно.

Похожие вопросы

Обсуждают сегодня

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Карта сайта