我试图理解为什么PostgreSQL不使用索引时,条件之一是在子查询。
我有(股票行情,日期)的索引
EXPLAIN ANALYZE SELECT OPEN
FROM
daily_prices dp
WHERE
dp.ticker = ( SELECT ticker FROM tickers_profile WHERE short_name = '1TECH' )
AND DATE <= '2022-07-05'
个字符
如果子查询是内联的(作为参数)
EXPLAIN ANALYZE SELECT OPEN
FROM
daily_prices dp
WHERE
dp.ticker = '03041'
AND DATE <= '2022-07-05'
Bitmap Heap Scan on daily_prices dp (cost=30.42..3646.10 rows=975 width=5) (actual time=0.506..0.758 rows=285 loops=1)
Recheck Cond: (((ticker)::text = '03041'::text) AND (date <= '2022-07-05'::date))
Heap Blocks: exact=16
-> Bitmap Index Scan on daily_prices_pkey (cost=0.00..30.18 rows=975 width=0) (actual time=0.490..0.490 rows=285 loops=1)
Index Cond: (((ticker)::text = '03041'::text) AND (date <= '2022-07-05'::date))
Planning Time: 0.077 ms
Execution Time: 0.793 ms
的字符串
我试过:
- CTE(带报表),性能相同
1.连接语句,性能相同
编辑:使用函数工作
CREATE
OR REPLACE FUNCTION get_ticker_from_short_name ( _short_name VARCHAR ) RETURNS TEXT AS $BODY$ SELECT
ticker
FROM
tickers_profile
WHERE
short_name = _short_name$BODY$ LANGUAGE SQL VOLATILE COST 100
EXPLAIN ANALYZE SELECT OPEN
FROM
daily_prices dp
WHERE
dp.ticker = ( SELECT get_ticker_from_short_name ( '1TECH' ) )
AND DATE <= '2022-07-05'
Bitmap Heap Scan on daily_prices dp (cost=36.61..3969.86 rows=1065 width=5) (actual time=0.369..0.565 rows=285 loops=1)
Recheck Cond: (((ticker)::text = $0) AND (date <= '2022-07-05'::date))
Heap Blocks: exact=16
InitPlan 1 (returns $0)
-> ProjectSet (cost=0.00..5.27 rows=1000 width=32) (actual time=0.314..0.314 rows=1 loops=1)
-> Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.000..0.001 rows=1 loops=1)
-> Bitmap Index Scan on daily_prices_pkey (cost=0.00..31.08 rows=1065 width=0) (actual time=0.362..0.362 rows=285 loops=1)
Index Cond: (((ticker)::text = $0) AND (date <= '2022-07-05'::date))
Planning Time: 0.088 ms
Execution Time: 0.604 ms
3条答案
按热度按时间x6492ojm1#
PostgreSQL可以在那里使用索引,但它不喜欢这样,可能是因为
daily_prices.ticker
的一些值经常出现,这会使索引扫描成为一个糟糕的选择。优化器不知道子查询将返回哪个值。也许可以将作业拆分为两个查询,这样优化器就知道何时计划第二个查询。如果您知道没有一个频繁值可以返回,您可以添加一个
WHERE
条件,如AND dp.ticker NOT IN ('frequent value 1', 'frequent value 2')
。xoefb8l82#
使用函数对我的情况很有效
8aqjt8rx3#
我也遇到过类似的问题。
我从
WHERE dp.ticker =
改为WHERE dp.ticker IN
修复了它。固定查询:
字符串