Оптимизация запросов Postgres - PullRequest
1 голос
/ 29 апреля 2010

Привет, ребята, пытаясь оптимизировать этот запрос для решения проблемы с дубликатами пользователей:

SELECT userid, 'ismaster' AS name, 'false' AS propvalue FROM user 
WHERE userid NOT IN (SELECT userid FROM userprop WHERE name = 'ismaster');

Проблема в том, что выбор после NOT IN составляет 120 000 записей, и он занимает вечность.

Использование префикса объяснения, предложенного в комментариях, возвращает:

                                    QUERY PLAN

--------------------------------------------------------------------------------
--
 Seq Scan on user  (cost=5559.38..122738966.99 rows=61597 width=8)
   Filter: (NOT (SubPlan 1))
   SubPlan 1
     ->  Materialize  (cost=5559.38..7248.33 rows=121395 width=8)
           ->  Seq Scan on userprop  (cost=0.00..4962.99 rows=121395 width=8
)
                 Filter: ((name)::text = 'ismaster'::text)
(6 rows)

Есть предложения?

Ответы [ 3 ]

0 голосов
/ 29 апреля 2010

Индексируется ли столбец имени? Насколько избирательным является значение имени? Также каждый раз, когда вы хотите, чтобы кто-то порекомендовал внести изменения в запрос, предоставьте план запроса, даже если он выглядит простым запросом. Таким образом, мы действительно знаем, что делает планировщик.

0 голосов
/ 29 апреля 2010

Согласно этому ответу , использование LEFT JOIN ... IS NULL может быть быстрее или медленнее, чем NOT EXISTS, в зависимости от СУБД, хотя они эквивалентны PostGres.

SELECT u.userid, 'ismaster' AS name, 'false' AS propvalue FROM user u
LEFT JOIN userprop up ON u.userid = up.userid AND up.name <> 'ismaster'
WHERE up.userid IS NULL
0 голосов
/ 29 апреля 2010

Вы указали индекс для идентификатора пользователя?

Или попробуйте другой вариант:

SELECT userid, 'ismaster' AS name, 'false' AS propvalue FROM user 
WHERE NOT EXISTS 
 (SELECT * FROM userprop 
 WHERE userpop.userid = user.userid 
   AND name = 'ismaster');
...