Странно: планировщик принимает решение с меньшими затратами, но (очень) большим временем выполнения запроса - PullRequest
1 голос
/ 17 июня 2010

Факты:

  • PGSQL 8.4.2, Linux
  • Я использую наследование таблиц
  • Каждая таблица содержит 3 миллиона строк
  • Устанавливаются индексы для соединяющихся столбцов
  • Статистика таблиц (анализ, анализ вакуума) актуальна
  • Единственная используемая таблица - это "узел" с разделенными подтаблицами varios
  • Рекурсивный запрос (pg> = 8.4)

Теперь вот объясненный запрос:

WITH    RECURSIVE
        rows AS
        (
        SELECT  *
        FROM    (
                SELECT  r.id, r.set, r.parent, r.masterid
                FROM    d_storage.node_dataset r
                WHERE   masterid = 3533933

                ) q
        UNION ALL
        SELECT  *
        FROM    (
                SELECT  c.id, c.set, c.parent, r.masterid
                FROM    rows r
                JOIN    a_storage.node c
                ON      c.parent = r.id

                ) q
        )
SELECT  r.masterid, r.id AS nodeid
FROM    rows r



                                                                           QUERY PLAN                                                                            
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
 CTE Scan on rows r  (cost=2742105.92..2862119.94 rows=6000701 width=16) (actual time=0.033..172111.204 rows=4 loops=1)
   CTE rows
     ->  Recursive Union  (cost=0.00..2742105.92 rows=6000701 width=28) (actual time=0.029..172111.183 rows=4 loops=1)
           ->  Index Scan using node_dataset_masterid on node_dataset r  (cost=0.00..8.60 rows=1 width=28) (actual time=0.025..0.027 rows=1 loops=1)
                 Index Cond: (masterid = 3533933)
           ->  Hash Join  (cost=0.33..262208.33 rows=600070 width=28) (actual time=40628.371..57370.361 rows=1 loops=3)
                 Hash Cond: (c.parent = r.id)
                 ->  Append  (cost=0.00..211202.04 rows=12001404 width=20) (actual time=0.011..46365.669 rows=12000004 loops=3)
                       ->  Seq Scan on node c  (cost=0.00..24.00 rows=1400 width=20) (actual time=0.002..0.002 rows=0 loops=3)
                       ->  Seq Scan on node_dataset c  (cost=0.00..55001.01 rows=3000001 width=20) (actual time=0.007..3426.593 rows=3000001 loops=3)
                       ->  Seq Scan on node_stammdaten c  (cost=0.00..52059.01 rows=3000001 width=20) (actual time=0.008..9049.189 rows=3000001 loops=3)
                       ->  Seq Scan on node_stammdaten_adresse c  (cost=0.00..52059.01 rows=3000001 width=20) (actual time=3.455..8381.725 rows=3000001 loops=3)
                       ->  Seq Scan on node_testdaten c  (cost=0.00..52059.01 rows=3000001 width=20) (actual time=1.810..5259.178 rows=3000001 loops=3)
                 ->  Hash  (cost=0.20..0.20 rows=10 width=16) (actual time=0.010..0.010 rows=1 loops=3)
                       ->  WorkTable Scan on rows r  (cost=0.00..0.20 rows=10 width=16) (actual time=0.002..0.004 rows=1 loops=3)
 Total runtime: 172111.371 ms
(16 rows)

(END) 

Пока все плохо, планировщик решает выбрать хеш-соединения (хорошо), но без индексов (плохо).

Теперь после выполнения следующих действий:

SET enable_hashjoins TO false;

Объясненный запрос выглядит так:

                                                                                    QUERY PLAN                                                                                      
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 CTE Scan on rows r  (cost=15198247.00..15318261.02 rows=6000701 width=16) (actual time=0.038..49.221 rows=4 loops=1)
   CTE rows
     ->  Recursive Union  (cost=0.00..15198247.00 rows=6000701 width=28) (actual time=0.032..49.201 rows=4 loops=1)
           ->  Index Scan using node_dataset_masterid on node_dataset r  (cost=0.00..8.60 rows=1 width=28) (actual time=0.028..0.031 rows=1 loops=1)
                 Index Cond: (masterid = 3533933)
           ->  Nested Loop  (cost=0.00..1507822.44 rows=600070 width=28) (actual time=10.384..16.382 rows=1 loops=3)
                 Join Filter: (r.id = c.parent)
                 ->  WorkTable Scan on rows r  (cost=0.00..0.20 rows=10 width=16) (actual time=0.001..0.003 rows=1 loops=3)
                 ->  Append  (cost=0.00..113264.67 rows=3001404 width=20) (actual time=8.546..12.268 rows=1 loops=4)
                       ->  Seq Scan on node c  (cost=0.00..24.00 rows=1400 width=20) (actual time=0.001..0.001 rows=0 loops=4)
                       ->  Bitmap Heap Scan on node_dataset c  (cost=58213.87..113214.88 rows=3000001 width=20) (actual time=1.906..1.906 rows=0 loops=4)
                             Recheck Cond: (c.parent = r.id)
                             ->  Bitmap Index Scan on node_dataset_parent  (cost=0.00..57463.87 rows=3000001 width=0) (actual time=1.903..1.903 rows=0 loops=4)
                                   Index Cond: (c.parent = r.id)
                       ->  Index Scan using node_stammdaten_parent on node_stammdaten c  (cost=0.00..8.60 rows=1 width=20) (actual time=3.272..3.273 rows=0 loops=4)
                             Index Cond: (c.parent = r.id)
                       ->  Index Scan using node_stammdaten_adresse_parent on node_stammdaten_adresse c  (cost=0.00..8.60 rows=1 width=20) (actual time=4.333..4.333 rows=0 loops=4)
                             Index Cond: (c.parent = r.id)
                       ->  Index Scan using node_testdaten_parent on node_testdaten c  (cost=0.00..8.60 rows=1 width=20) (actual time=2.745..2.746 rows=0 loops=4)
                             Index Cond: (c.parent = r.id)
 Total runtime: 49.349 ms
(21 rows)

(END) 

-> невероятно быстрее, потому что использовались индексы. Примечание. Стоимость второго запроса несколько выше, чем для первого.

Итак, главный вопрос: почему планировщик принимает первое решение, а не второе?

Также интересно:

Via

SET enable_seqscan TO false;

я темп. отключено последующее сканирование. Затем планировщик использовал индексы и хеш-объединения, а запрос все еще был медленным. Таким образом, проблема, похоже, заключается в хеш-соединении.

Может быть, кто-то может помочь в этой запутанной ситуации?

thx, R.

Ответы [ 3 ]

1 голос
/ 18 июня 2010

Если ваше объяснение значительно отличается от реальности (стоимость ниже, но время больше), вероятно, ваши статистические данные устарели или представлены в нерепрезентативной выборке.

Попробуйте еще раз со свежей статистикой. Если это не помогает, увеличьте размер выборки и снова создайте статистику.

0 голосов
/ 21 июня 2010

Хеш-соединение ожидало 600070 результирующих строк, но получило только 4 (в 3 циклах, в среднем по 1 строке на цикл).Если бы 600070 был точным, хэш-соединение, вероятно, было бы уместным.

0 голосов
/ 17 июня 2010

Попробуйте это:

set seq_page_cost = '4.0'; set random_page_cost = '1.0; ОБЪЯСНИТЬ АНАЛИЗ ....

Сделайте это в своей сессии, чтобы увидеть, если это что-то меняет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...