On Mon, 2006-12-04 at 21:24 +0500, Anton wrote:
> Подробности:
> SELECT collect_time FROM n_traffic WHERE collect_time > '1970-01-01
> 00:00:00'
> AND login_id IN (SELECT login_id FROM n_logins WHERE account_id = '1655')
> ORDER BY collect_time LIMIT 1
> --------------------------------
> Limit (cost=0.00..2028.44 rows=1 width=8) (actual
> time=4434.532..4434.532 rows=0 loops=1)
> -> Nested Loop IN Join (cost=0.00..722123.09 rows=356 width=8)
> (actual time=4434.527..4434.527 rows=0 loops=1)
> -> Index Scan using n_traffic_collect_time on n_traffic
> (cost=0.00..9723.29 rows=225023 width=12) (actual time=0.036..830.414
> rows=224971 loops=1)
> Index Cond: (collect_time > '1970-01-01
> 00:00:00'::timestamp without time zone)
Здесь явно неразумный план: выборка из большой таблицы всех (видимо)
записей по условию, которое всегда true. Здесь даже seq scan был бы
быстрее (ANALYZE давно делали?).
> -> Index Scan using n_logins_pkey on n_logins
> (cost=0.00..3.15 rows=1 width=4) (actual time=0.010..0.010 rows=0
> loops=224971)
Далее по всем этим найденным записям прогоняется поиск в n_logins.
Поиск сам по себе быстрый, но много-многократный. В итоге
Nested Loop IN Join выше выполняется уже 4 секунды.
> Index Cond: ("outer".login_id = n_logins.login_id)
> Filter: (account_id = 1655)
> Total runtime: 4434.827 ms
> (8 rows)
На мой взгляд, как раз вариант, который предложил Фёдор, должен
использовать более приемлемый join. Можно взглянуть на его EXPLAIN?
И, кстати, во времена семёрки рекомендовалось использовать JOIN в явном
виде, когда оптимизатор выбирал не лучший вариант, то есть задавать
порядок JOIN'а вручную. Насчёт восьмёрки вроде проскакивало, что
оптимизатор умничает даже в случае явного JOIN, хотя я не уверен, так
что можно попробовать и этот вариант.
--
Fduch M. Pravking