PostgreSql использует IN statemente с очень низкой производительностью - PullRequest
2 голосов
/ 06 октября 2011

недавно я установил PostgreSQL 9.0 с Postgis на машине с Windows7. Затем я загрузил несколько таблиц в одну схему. Теперь я хочу сделать очень простой запрос, и сейчас я вижу, что это занимает более 10 минут. Я искал много мест, в том числе в stackoverflow.com, и до сих пор я могу понять, в чем моя ошибка.

моя проблема:

Tbl_Pprietarios - 230000 записей

Tbl_Predio - 160000 записей

SELECT id_predios 
FROM "Tbl_Predio"
where id_predios not in 
    (
    SELECT id_predios 
    FROM "Tbl_Proprietarios"
    )
;

спасибо

Ответы [ 3 ]

2 голосов
/ 06 октября 2011

Попробуйте левое внешнее объединение:

SELECT Tbl_Predio.id_predios
FROM Tbl_Predio
LEFT OUTER JOIN Tbl_Proprietarios ON Tbl_Predio.id_predios = Tbl_Proprietarios.id_predios
WHERE Tbl_Proprietarios.id_predios IS NULL;

Также убедитесь, что на Tbl_Proprietarios.id_predios.

есть индекс.
0 голосов
/ 06 октября 2011

По моему опыту работы с SQL Server * оператор 1001 * обычно работает очень медленно.

Обычно лучше exists:

SELECT id_predios 
  FROM "Tbl_Predio"
 WHERE not exists (
           SELECT 1
             FROM "Tbl_Proprietarios"
            WHERE "Tbl_Proprietarios".id_predios = "Tbl_Predio".id_predios
       )

(Примечание в MySQL обычно происходит наоборот, но логически зависит от выполняемого вами запроса)

Или вы можете использовать левое соединение:

SELECT id_predios 
  FROM "Tbl_Predio"
  left join "Tbl_Proprietarios" on "Tbl_Proprietarios".id_predios = "Tbl_Predio".id_predios
 WHERE "Tbl_Proprietarios".id_predios is null

Чтобы узнать, что происходит, используйте ОБЪЯСНИТЬ .

0 голосов
/ 06 октября 2011

Должен работать через несколько секунд на приличной машине.Определение таблицы?Индексы?план запроса?Конфигурация?Память?

SELECT id_predios 
FROM Tbl_Predio t1
WHERE NOT EXISTS ( 
  SELECT *
  FROM Tbl_Proprietarios t2
  WHERE t2.id_predios = t1.id_predios
  )
;

РЕДАКТИРОВАТЬ: план запроса с 2 * 999K записей:

 Hash Anti Join  (cost=29813.47..61463.98 rows=79 width=4) (actual time=3470.658..7142.042 rows=1045 loops=1)
   Hash Cond: (t1.id_predios = t2.id_predios)
   ->  Seq Scan on tbl_predio t1  (cost=0.00..13912.33 rows=999033 width=4) (actual time=0.038..1458.946 rows=999033 loops=1)
   ->  Hash  (cost=13911.54..13911.54 rows=998954 width=4) (actual time=3238.919..3238.919 rows=998954 loops=1)
         ->  Seq Scan on tbl_proprietarios t2  (cost=0.00..13911.54 rows=998954 width=4) (actual time=0.057..1479.807 rows=998954 loops=1)
 Total runtime: 7143.919 ms
(6 rows)

РЕДАКТИРОВАТЬ 2: тестовый сценарий:

DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp;

DROP TABLE tmp.Tbl_Predio CASCADE;
DROP TABLE tmp.Tbl_Proprietarios CASCADE;

CREATE TABLE tmp.Tbl_Predio ( id_predios INTEGER NOT NULL );
CREATE TABLE tmp.Tbl_Proprietarios ( id_predios INTEGER NOT NULL );

INSERT INTO tmp.Tbl_Predio ( id_predios) SELECT serie.val
    FROM generate_series(1,1000000) AS serie(val)
    ;

INSERT INTO tmp.Tbl_Proprietarios ( id_predios) SELECT serie.val
    FROM generate_series(1,1000000) AS serie(val)
    ;

DELETE FROM tmp.Tbl_Predio WHERE random() <= 0.001 ;
DELETE FROM tmp.Tbl_Proprietarios WHERE random() <= 0.001 ;

ALTER TABLE tmp.Tbl_Predio ADD PRIMARY KEY (id_predios) ;
ALTER TABLE tmp.Tbl_Proprietarios ADD PRIMARY KEY (id_predios) ;

EXPLAIN ANALYZE
SELECT id_predios
FROM tmp.Tbl_Predio t1
WHERE NOT EXISTS (
  SELECT *
  FROM tmp.Tbl_Proprietarios t2
  WHERE t2.id_predios = t1.id_predios
  )
;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...