powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Запрос с NOT IN (SELECT) - не использует индекс?
5 сообщений из 5, страница 1 из 1
Запрос с NOT IN (SELECT) - не использует индекс?
    #34745316
Cane Cat Fisher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
CREATE TABLE test_nop AS (
		  	SELECT abonid 
		  	  FROM jnop s
		  	 WHERE ...
);

CREATE  TABLE test_sald AS (
		  	SELECT abonid 
		  	  FROM jsald s
		  	 WHERE ...
);

CREATE INDEX idx_test_sald ON test_sald (abonid);

EXPLAIN 
SELECT abonid
	FROM test_nop
	WHERE abonid NOT IN (SELECT abonid FROM test_sald)
;

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
                              QUERY PLAN                               
-----------------------------------------------------------------------
 Seq Scan on test_nop  (cost=0.00..55698670.46 rows=51477 width=4)
   Filter: (NOT (subplan))
   SubPlan
     ->  Seq Scan on test_sald  (cost=0.00..921.99 rows=63999 width=4)
(4 rows)

То что внешняя таблица (test_nop) сканируется польностью, это понятно. Но искать каждую запись в подзапросе, мне кажется, нужно по индексу... Или я неправ?
...
Рейтинг: 0 / 0
Запрос с NOT IN (SELECT) - не использует индекс?
    #34745382
mwolf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
SELECT test_nop.abonid
FROM test_nop , (SELECT abonid FROM test_sald) as t
WHERE test_nop.abonid <> t.abonid 

а так?
...
Рейтинг: 0 / 0
Запрос с NOT IN (SELECT) - не использует индекс?
    #34745412
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SELECT abonid FROM test_nop
EXCEPT
SELECT abonid FROM test_sald;
...
Рейтинг: 0 / 0
Запрос с NOT IN (SELECT) - не использует индекс?
    #34748184
Cane Cat Fisher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
to mwolf : Добрый ты человек, боярин ;-) А если б я попробовал не подумав? А ведь меня интересует разность, а не почти полное декартово произведение...


to LeXa NalBat :

Действительно, с EXCEPT работает удовлетворительно. Если в варианте с NOT IN я вообще не дождался результата (более двух часов), то с EXCEPT отработало за 6 секунд. Самое удивительное, что, судя по плану, оно ухитрилось сделать это все же без использования индексов.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
                                                                QUERY PLAN                                                                
------------------------------------------------------------------------------------------------------------------------------------------
 SetOp Except  (cost=19886.09..20720.88 rows=16696 width=4) (actual time=5931.982..5943.654 rows=2 loops=1)
   ->  Sort  (cost=19886.09..20303.48 rows=166957 width=4) (actual time=4656.240..5315.892 rows=166957 loops=1)
         Sort Key: abonid
         ->  Append  (cost=0.00..4075.14 rows=166957 width=4) (actual time=0.054..3192.049 rows=166957 loops=1)
               ->  Subquery Scan "*SELECT* 1"  (cost=0.00..2513.06 rows=102953 width=4) (actual time=0.047..1212.149 rows=102953 loops=1)
                     ->  Seq Scan on test_nop  (cost=0.00..1483.53 rows=102953 width=4) (actual time=0.035..424.763 rows=102953 loops=1)
               ->  Subquery Scan "*SELECT* 2"  (cost=0.00..1562.08 rows=64004 width=4) (actual time=0.054..771.256 rows=64004 loops=1)
                     ->  Seq Scan on test_sald  (cost=0.00..922.04 rows=64004 width=4) (actual time=0.043..279.049 rows=64004 loops=1)
 Total runtime: 5952.649 ms
(9 rows)


А решить проблему удалось переписыванием запроса через NOT EXISTS:

Код: plaintext
1.
2.
3.
SELECT abonid
	FROM test_nop
	WHERE NOT EXISTS (SELECT * FROM test_sald WHERE test_nop.abonid = test_sald.abonid)

Вот здесь оно наконец-то подхватило индекс.

Код: plaintext
1.
2.
3.
4.
5.
6.
 Seq Scan on test_nop  (cost=0.00..2583.88 rows=500 width=4) (actual time=956.520..1662.582 rows=2 loops=1)
   Filter: (NOT (subplan))
   SubPlan
     ->  Index Scan using idx_test_sald on test_sald  (cost=0.00..823.00 rows=321 width=4) (actual time=0.010..0.010 rows=1 loops=102953)
           Index Cond: ($0 = abonid)
 Total runtime: 1811.748 ms

В пожелтевших рукописях встретил упоминания, что в древних версиях сервера (до 7.2) была такая проблема - IN работало медленне, чем EXISTS, при прочих равных условиях. Выходит, где-то что-то недофиксили... Пойду переписывать все IN на EXISTS...
...
Рейтинг: 0 / 0
Запрос с NOT IN (SELECT) - не использует индекс?
    #34748365
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
попробуйте еще

select a.abonid from test_nop as a natural full outer join test_sald as b where b.abonid is null

или если выругается

select a_abonid from ( select a.abonid as a_abonid, b.abonid as b_abonid from test_nop as a natural full outer join test_sald as b ) as c where b_abonid is null
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Запрос с NOT IN (SELECT) - не использует индекс?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]