SQL Statement sehr inperformant

Maris

Aktiver Benutzer
Beiträge
32
Hallo zusammen,

das folgende Statement dauert ewig. Kann mir jemand helfen wie ich es umstellen muss?

Ich möchte das die Daten aus Field1 von Settings ausgeben werden, jedoch dürfen keine Daten aus Field1 der Tabelle Settings_Blacklist enthalten sein.

SELECT Field1
FROM operations.settings_final
WHERE Field1 NOT IN
(

SELECT Field1 FROM operations.settings_blacklist

);

LG,
Maris
 
Werbung:
Kannst du nicht durch umstellen beschleunigen. Du kannst nur:
a) Einen schnelleren Server kaufen
b) Eine bessere Datenbank verwenden
c) Eventuell einen Index auf Field1 in operations.settings_final legen
 
Kann man das nicht so Joinen das der Wert der einen Tabelle nicht in der anderen enthalten ist?
 
Code:
SELECT f.Field1
FROM operations.settings_final f
LEFT JOIN operations.settings_blacklist b
ON f.field1 = b.field1
WHERE b.field1 IS NULL
...ginge, aber ich glaube eigentlich nicht das das schneller ist.
 
...ginge, aber ich glaube eigentlich nicht das das schneller ist.

Kann man ja prüfen:

Code:
test=# create table settings as select s, 'setting ' || s::text from generate_series(1, 10000000) s;
SELECT 10000000
test=*# create table blacklist as select (random()*1000000)::int r from generate_series(1, 10000) s;
SELECT 10000

test=*# analyse blacklist;
ANALYZE
test=*# analyse settings;
ANALYZE
test=*# explain analyse select * from settings where s not in (select r from blacklist);
  QUERY PLAN   
--------------------------------------------------------------------------------------------------------------------------
 Seq Scan on settings  (cost=170.00..188863.10 rows=4999964 width=19) (actual time=12.157..2678.397 rows=9990055 loops=1)
  Filter: (NOT (hashed SubPlan 1))
  Rows Removed by Filter: 9945
  SubPlan 1
  ->  Seq Scan on blacklist  (cost=0.00..145.00 rows=10000 width=4) (actual time=0.020..3.968 rows=10000 loops=1)
 Planning time: 0.176 ms
 Execution time: 3338.145 ms
(7 Zeilen)

test=*# explain analyse select * from settings left join blacklist on settings.s=blacklist.r where blacklist.r is null;
  QUERY PLAN   
------------------------------------------------------------------------------------------------------------------------------
 Hash Anti Join  (cost=270.00..290148.97 rows=9989983 width=23) (actual time=7.900..3802.351 rows=9990055 loops=1)
  Hash Cond: (settings.s = blacklist.r)
  ->  Seq Scan on settings  (cost=0.00..163693.28 rows=9999928 width=19) (actual time=0.054..1397.238 rows=10000000 loops=1)
  ->  Hash  (cost=145.00..145.00 rows=10000 width=4) (actual time=7.797..7.797 rows=10000 loops=1)
  Buckets: 16384  Batches: 1  Memory Usage: 480kB
  ->  Seq Scan on blacklist  (cost=0.00..145.00 rows=10000 width=4) (actual time=0.046..3.547 rows=10000 loops=1)
 Planning time: 0.195 ms
 Execution time: 4458.254 ms
(8 Zeilen)

test=*#

wir kennen natürlich jetzt nicht die originalen Tabellen des Fragestellers, nicht die Verteilung der Werte etc.
 
Ich finde es aber duraus nachvollziehbar das es länger dauert und das vor allem je größer die Blacklist wird. Das mit IN ( Subquery ) sollte schon die gängige Wahl sein.
 
Ich kann es gern mit dem LeftJoIN ausprobieren, nur verstehe ich das mit NULL nicht. Ich habe keine NULL - WErte in beiden Tabellen.
 
Werbung:
Du kannst es auch einmal so versuchen. Indexe auf field1 müssen natürlich vorhanden sein.

Code:
SELECT  Field1
FROM    operations.settings_final o
WHERE   NOT EXISTS
        (
        SELECT  1
        FROM operations.settings_blacklist b
        WHERE o.field1 = b.field1
        );
 
Zurück
Oben