Vergleich zweier Tabellen ergibt MYSQL Server gone away

dekan

Benutzer
Beiträge
10
Hallo ich vergleiche zweit Tabellen miteinander:

SELECT * FROM importing WHERE importing.AbotKundNr NOT IN ( SELECT KundNr FROM subscriber )

Ergebnis: #2006 - MySQL server has gone away

Gibt es weniger Rechen Intensive Alternativen?
 
Werbung:
Ich würde vorschlagen
Code:
SELECT * FROM importing LEFT JOIN subscriber ON importing.AbotKundNr = subscriber.KundenNr WHERE subscriber.KundenNr IS NULL
das sollte auch MySQL können.
 
Die Lösung von @ukulele ist aber laut explain teurer und braucht in der Ausführung länger. Ich habe mal 2 Tabellen angelegt:

Code:
test=# create table tab_a as select (random()*10000000)::int as id, repeat(md5(s::text), 20) as value from generate_series(1, 5000000) s;
SELECT 5000000
test=*# create table tab_b as select (random()*10000000)::int as id, repeat(md5(s::text), 20) as value from generate_series(1, 50000) s;
SELECT 50000

Also 5 Millionen und 50.000, damit es wenigstens etwas zu tun gibt.

Hier die 2 Explain Analyse - Ausgaben:

Code:
test=*# explain analyse select * from tab_a where id not in (select id from tab_b);
  QUERY PLAN   
-------------------------------------------------------------------------------------------------------------------------
 Seq Scan on tab_a  (cost=4792.00..483959.05 rows=2500002 width=648) (actual time=44.913..3491.240 rows=4975002 loops=1)
  Filter: (NOT (hashed SubPlan 1))
  Rows Removed by Filter: 24998
  SubPlan 1
  ->  Seq Scan on tab_b  (cost=0.00..4667.00 rows=50000 width=4) (actual time=0.062..27.455 rows=50000 loops=1)
 Planning time: 0.226 ms
 Execution time: 3847.303 ms
(7 Zeilen)

und die Version nach @ukulele :

Code:
test=*# explain analyse select * from tab_a left join tab_b on tab_a.id = tab_b.id where tab_b.id is null;
  QUERY PLAN   
---------------------------------------------------------------------------------------------------------------------------
 Hash Anti Join  (cost=9394.00..1363129.44 rows=4925863 width=1296) (actual time=70.641..13771.309 rows=4975002 loops=1)
  Hash Cond: (tab_a.id = tab_b.id)
  ->  Seq Scan on tab_a  (cost=0.00..466667.04 rows=5000004 width=648) (actual time=0.013..4561.754 rows=5000000 loops=1)
  ->  Hash  (cost=4667.00..4667.00 rows=50000 width=648) (actual time=70.392..70.392 rows=50000 loops=1)
  Buckets: 8192  Batches: 16  Memory Usage: 2158kB
  ->  Seq Scan on tab_b  (cost=0.00..4667.00 rows=50000 width=648) (actual time=0.059..25.219 rows=50000 loops=1)
 Planning time: 0.399 ms
 Execution time: 14136.331 ms
(8 Zeilen)
 
Ich vermute der Subselect wird zu jeder Zeile erneut ausgeführt. Ansonsten kann ich mir nicht erklären, wie eine derart schlechte Performance zustande kommen soll. Es sei denn, wir reden hier von einem RasPi oder vergleichbarer Hardware, auf dem der SQL läuft. Ansonsten dürfte ja wohl selbst MySQL das schaffen.
 
PG führt das Subselect, wie man sieht, nur einmal aus. Mag sein, daß MySQL da nicht so clever ist. Wäre mal interessant zu wissen, wie schnell "MySQL server has gone away" erfolgt und was es so vielleicht noch an Logs gibt (MySQL, OS).
 
Werbung:
Ist auch meiner Seits nur eine Vermutung, kann auch mit einem nicht vorhandenen Index oder sonstwie zusammen hängen. Ich denke normalerweise müsste auch MySQL den Subselect nur einmal durchführen.

@dekan:
Ein Explain zu dem Select könnte die Ursache deutlich zeigen.
 
Zurück
Oben