Re: Simple DELETE on modest-size table runs 100% CPU forever

Поиск
Список
Период
Сортировка
От Craig James
Тема Re: Simple DELETE on modest-size table runs 100% CPU forever
Дата
Msg-id CAFwQ8rfito2szEXHOWFukMmAjnZYfXfR1tM-67JUL4==ue=uhw@mail.gmail.com
обсуждение исходный текст
Ответ на Re: Simple DELETE on modest-size table runs 100% CPU forever  (Andres Freund <andres@anarazel.de>)
Ответы RE: Simple DELETE on modest-size table runs 100% CPU forever  (Ravi Rai <ravi.p.rai@live.com>)
Список pgsql-performance
On Thu, Nov 14, 2019 at 2:29 PM Andres Freund <andres@anarazel.de> wrote:
Hi,

On 2019-11-14 14:19:51 -0800, Craig James wrote:
> I'm completely baffled by this problem: I'm doing a delete that joins three
> modest-sized tables, and it gets completely stuck: 100% CPU use forever.
> Here's the query:

I assume this is intended to be an equivalent SELECT? Because you did
mention DELETE, but I'm not seeing one here?  Could you actually show
that query - surely that didn't include a count() etc...  You can
EPLAIN DELETEs too.

Sorry, my explanation was misleading. It is a "delete ... where id in (select ...)". But I discovered that the select part itself never completes, whether you include it in the delete or not. So I only showed the select, which I converted to a "select count(1) ..." for simplicity.
 
> explain analyze
>  select count(1) from registry.categories
>   where category_id = 15 and id in
>     (select c.id from registry.categories c
>      left join registry.category_staging_15 st on (c.id = st.id)  where
> c.category_id = 15 and st.id is null);
>
> If I leave out the "analyze", here's what I get (note that the
> categories_staging_N table's name changes every time; it's
> created on demand as "create table categories_staging_n(id integer)").

> Aggregate  (cost=193.54..193.55 rows=1 width=8)
>   ->  Nested Loop Semi Join  (cost=0.84..193.54 rows=1 width=0)
>         Join Filter: (categories.id = c.id)
>         ->  Index Scan using i_categories_category_id on categories
>  (cost=0.42..2.44 rows=1 width=4)
>               Index Cond: (category_id = 23)
>         ->  Nested Loop Anti Join  (cost=0.42..191.09 rows=1 width=4)
>               Join Filter: (c.id = st.id)
>               ->  Index Scan using i_categories_category_id on categories c
>  (cost=0.42..2.44 rows=1 width=4)
>                     Index Cond: (category_id = 23)
>               ->  Seq Scan on category_staging_23 st  (cost=0.00..99.40
> rows=7140 width=4)
>
> The tables are small. From a debugging printout:


Is categories.category_id unique?

No, categories.category_id is not unique. It has a b-tree index.
 
Does the plan change if you ANALYZE
the tables?

No. No difference.

But interestingly, it changes as the process goes forward. And it's inconsistent. Here's an example: it's going through several "categories" to update each. The first plan works, and it typically uses this plan a few times. But when selects the second plan, it gets stuck.

----------------
15994 items in table registry.category_staging_15
245598 items in table registry.categories
309398 items in table registry.smiles
15994 items in joined registry.category_staging_15 / registry.categories
0 items to be inserted
inserted: 0E0
EXPLAIN: Aggregate  (cost=3464.82..3464.83 rows=1 width=8)
EXPLAIN:   ->  Hash Semi Join  (cost=2029.16..3464.05 rows=311 width=0)
EXPLAIN:         Hash Cond: (categories.id = c.id)
EXPLAIN:         ->  Index Scan using i_categories_category_id on categories  (cost=0.42..1405.28 rows=7900 width=4)
EXPLAIN:               Index Cond: (category_id = 15)
EXPLAIN:         ->  Hash  (cost=1933.44..1933.44 rows=7624 width=4)
EXPLAIN:               ->  Hash Anti Join  (cost=431.28..1933.44 rows=7624 width=4)
EXPLAIN:                     Hash Cond: (c.id = st.id)
EXPLAIN:                     ->  Index Scan using i_categories_category_id on categories c  (cost=0.42..1405.28 rows=7900 width=4)
EXPLAIN:                           Index Cond: (category_id = 15)
EXPLAIN:                     ->  Hash  (cost=230.94..230.94 rows=15994 width=4)
EXPLAIN:                           ->  Seq Scan on category_staging_15 st  (cost=0.00..230.94 rows=15994 width=4)
0 items deleted
7997 items inserted
----------------
6250 items in table registry.category_staging_25
245598 items in table registry.categories
309398 items in table registry.smiles
6250 items in joined registry.category_staging_25 / registry.categories
6250 items to be inserted
inserted: 3125
EXPLAIN: Aggregate  (cost=173.51..173.52 rows=1 width=8)
EXPLAIN:   ->  Nested Loop Semi Join  (cost=0.84..173.51 rows=1 width=0)
EXPLAIN:         Join Filter: (categories.id = c.id)
EXPLAIN:         ->  Index Scan using i_categories_category_id on categories  (cost=0.42..2.44 rows=1 width=4)
EXPLAIN:               Index Cond: (category_id = 25)
EXPLAIN:         ->  Nested Loop Anti Join  (cost=0.42..171.06 rows=1 width=4)
EXPLAIN:               Join Filter: (c.id = st.id)
EXPLAIN:               ->  Index Scan using i_categories_category_id on categories c  (cost=0.42..2.44 rows=1 width=4)
EXPLAIN:                     Index Cond: (category_id = 25)
EXPLAIN:               ->  Seq Scan on category_staging_25 st  (cost=0.00..90.50 rows=6250 width=4)


This plan doesn't look like it'd actually take long, if the estimates
are correct.

Another data point: during this query, Postgres is burning 100% CPU and doing no I/O. Pretty much for hours if I let it go. 
 
Thanks for your help,
Craig

В списке pgsql-performance по дате отправления:

Предыдущее
От: Andres Freund
Дата:
Сообщение: Re: Simple DELETE on modest-size table runs 100% CPU forever
Следующее
От: Ravi Rai
Дата:
Сообщение: RE: Simple DELETE on modest-size table runs 100% CPU forever