最近我在Windows7机器上安装了PostgreSQL 9.0 w / Postgis。然后,我将几个表加载到一个模式中。 现在,我想做一个非常简单的查询,在这个时候,我可以看到它需要超过10分钟。 我搜索了很多地方,也在stackoverflow.com,直到现在我都能理解我的错误。
我的问题:
Tbl_Proprietarios - 230000条记录
Tbl_Predio - 160000条记录
SELECT id_predios
FROM "Tbl_Predio"
where id_predios not in
(
SELECT id_predios
FROM "Tbl_Proprietarios"
)
;
感谢
答案 0 :(得分:2)
尝试左外连接:
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
上有索引。
答案 1 :(得分:0)
应该在一台体面的机器上运行几秒钟。 表定义?索引?查询计划?配置?存储器?
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)
EDIT2: 测试脚本:
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
)
;
答案 2 :(得分:0)
根据我在SQL Server上的经验in
运算符通常非常慢。
通常情况更好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
要知道发生了什么,请使用EXPLAIN。