SELECT въпрос
7 отговора
500 прегледа
SELECT въпрос
Здравейте. Имам едно такова питане - правя следния INSERT/SELECT
Питането ми е защо това работи нормално, а при промяна във WHERE клаузата на:
сървъра се претоварва (out of memory)?
Каква е разликата между два разделени SELECT-a и два обединени чрез UNION в една и съща заявка? Дано ме разбрахте какво имам предвид.
Има три вида хора. Част от проблема, част от решението и част от пейзажа.
INSERT INTO new_table
(
SELECT
field_1,
field_2
FROM
compare_table
WHERE
field_1 NOT IN (SELECT ex_field_1 FROM exist_table1)
AND field_1 NOT IN (SELECT ex_field_1 FROM exist_table2)
)
Питането ми е защо това работи нормално, а при промяна във WHERE клаузата на:
....
WHERE
field_1 NOT IN (SELECT ex_field_1 FROM exist_table1 UNION SELECT ex_field_1 FROM exist_table2)
сървъра се претоварва (out of memory)?
Каква е разликата между два разделени SELECT-a и два обединени чрез UNION в една и съща заявка? Дано ме разбрахте какво имам предвид.
Има три вида хора. Част от проблема, част от решението и част от пейзажа.
разделяй и владей
А какво ти дава EXPLAIN ANALYZE от въпросните вложени заявки и съответно от обединението (UNION) на двете?
Пробвай да извъртиш нещата също и с EXISTS синтаксис.
По принцип от доста голямо значение е на каква база данни го пускаш това, но предполагам, че в първия случай използва паметта разделно, т.е. пуска първата подзаявка, намира съвпаденията, след което освобождава паметта за втората или нещо подобно. Докато с UNION трябва всичко да се зареди наведнъж на едно място и да се разкарат дублиращите се записи, естествено.
Това малко наизуст го говоря де, но си го представям като да ходиш на пазар за домати и краставици - ако купиш доматите, прибереш се, и после отидеш за краставиците ще можеш да го направиш с една по-малка торба, отколкото ако искаш наведнъж да купиш и доматите и краставиците, в който случай рискуваш да ти се скъса торбата по пътя.
Everything louder than everything else...
Пробвай да извъртиш нещата също и с EXISTS синтаксис.
По принцип от доста голямо значение е на каква база данни го пускаш това, но предполагам, че в първия случай използва паметта разделно, т.е. пуска първата подзаявка, намира съвпаденията, след което освобождава паметта за втората или нещо подобно. Докато с UNION трябва всичко да се зареди наведнъж на едно място и да се разкарат дублиращите се записи, естествено.
Това малко наизуст го говоря де, но си го представям като да ходиш на пазар за домати и краставици - ако купиш доматите, прибереш се, и после отидеш за краставиците ще можеш да го направиш с една по-малка торба, отколкото ако искаш наведнъж да купиш и доматите и краставиците, в който случай рискуваш да ти се скъса торбата по пътя.
Everything louder than everything else...
Редактирано от Dakota на
Re: SELECT въпрос
Като допълнение, това би трябвало да е много по-бързо особено при наличие на индекси:
INSERT INTO new_table
(
SELECT
field_1,
field_2
FROM
compare_table
where not exists
(
select * from exist_table1, exist_table2
where exist_table1.ex_field_1=exist_table2.ex_field_1
and compare_table.field_1=exist_table1.ex_field_1
)
)
NOT EXISTS
И аз съм за not exists, ама без join:
... NOT EXISTS ... AND NOT EXISTS ...
... NOT EXISTS ... AND NOT EXISTS ...
Re: SELECT въпрос
Може да е малко глупав въпроса ми (salle да ме прощава), но в допълнение към основното ми UNION питане, за което все още нямам отговор - каква е разликата между NOT IN и NOT EXISTS в конкретния случай?
Редактирано от mr.vain на
IN или EXISTS
Двете всъщност работят по доста различен начин.
В случая с IN, в повечето случаи подзаявката се изпълнява, махат се дублиращите се записи и евентуално се сортира, след което се свързва с главната таблица. Ако има някакви индекси, те се използват единствено в рамките на подзаявката и не участват в свързването.
При EXISTS, обикновено се започва с главната таблица, като за всеки ред се проверява дали има съвпадение в резултата от подзаявката, което предполага full scan върху главната таблица, като индексите от вторичната се използват при свързването.
Не случайно съм удебелил някои от думите, защото нещата силно зависят от това какви и най-вече колко на брой данни имаш в едната и в другата таблица, а също и какви индекси имаш.
Като цяло, ако в подзаявката имаш относително малко записи е по-добре да използваш IN, в противен случай - EXISTS. Но това е много общо - пак повтарям - всичко зависи от конкретните условия, а също и от базата от данни, която използваш, защото всяка СУБД си има собствено мнение по въпроса и си прави собствените си оптимизации.
Everything louder than everything else...
В случая с IN, в повечето случаи подзаявката се изпълнява, махат се дублиращите се записи и евентуално се сортира, след което се свързва с главната таблица. Ако има някакви индекси, те се използват единствено в рамките на подзаявката и не участват в свързването.
При EXISTS, обикновено се започва с главната таблица, като за всеки ред се проверява дали има съвпадение в резултата от подзаявката, което предполага full scan върху главната таблица, като индексите от вторичната се използват при свързването.
Не случайно съм удебелил някои от думите, защото нещата силно зависят от това какви и най-вече колко на брой данни имаш в едната и в другата таблица, а също и какви индекси имаш.
Като цяло, ако в подзаявката имаш относително малко записи е по-добре да използваш IN, в противен случай - EXISTS. Но това е много общо - пак повтарям - всичко зависи от конкретните условия, а също и от базата от данни, която използваш, защото всяка СУБД си има собствено мнение по въпроса и си прави собствените си оптимизации.
Everything louder than everything else...
всъщност ето и пример
EXPLAIN ANALYZE SELECT * FROM call WHERE abstract_call_sid IN
(SELECT abstract_call_sid FROM abstract_call)
Hash IN Join (cost=4550.12..15782.41 rows=195208 width=20) (actual time=2360.800..5834.935 rows=195208 loops=1)
Hash Cond: ("outer".abstract_call_sid = "inner".abstract_call_sid)
-> Seq Scan on call (cost=0.00..3301.08 rows=195208 width=20) (actual time=0.045..905.952 rows=195208 loops=1)
-> Hash (cost=3299.10..3299.10 rows=195210 width=4) (actual time=2065.334..2065.334 rows=0 loops=1)
-> Seq Scan on abstract_call (cost=0.00..3299.10 rows=195210 width=4) (actual time=0.045..993.545 rows=195210 loops=1)
Total runtime: 6656.806 ms
EXPLAIN ANALYZE SELECT * FROM call WHERE EXISTS
(SELECT NULL FROM abstract_call WHERE abstract_call.abstract_call_sid=call.abstract_call_sid)
Seq Scan on call (cost=0.00..591555.38 rows=97604 width=20) (actual time=0.143..5015.186 rows=195208 loops=1)
Filter: (subplan)
SubPlan
-> Index Scan using abstract_call_pkey on abstract_call (cost=0.00..3.01 rows=1 width=0) (actual time=0.014..0.014 rows=1 loops=195208)
Index Cond: (abstract_call_sid = $0)
Total runtime: 5835.826 ms
Everything louder than everything else...
Редактирано от Dakota на
Re: всъщност ето и пример
Благодаря за примера, наистина е полезен за мен. Остан отворен обаче първоначалният ми въпрос за UNION-a?
Някаква идея? Salle?
Има три вида хора. Част от проблема, част от решението и част от пейзажа.
Някаква идея? Salle?
Има три вида хора. Част от проблема, част от решението и част от пейзажа.