我有一个主/详细表情况。对于主表的每个条目,我在详细信息表中有几十个。
让我们说这些是我的表:
+-----------------------
| Master
+-----------------------
| master_key integer,
| insert_date timestamp
+-----------------------
+-----------------------
| Detail
+-----------------------
| detail_key integer,
| master_key integer
| quantity numeric
| amount numeric
+-----------------------
我最常用的查询类似于
SELECT extract(year from insert_date) AS Insert_Year, extract(month from insert_date) AS Insert_Month, sum(quantity) AS Quantity, sum(amount) AS Amount
FROM Master, Detail
WHERE (amount not null) and (insert_date <= '2016-12-31') and (insert_date >= '2015-01-01') and (Detail.master_key=Master.master_key)
GROUP BY Insert_Year, Insert_Month
ORDER BY Insert_Year ASC, Insert_Month ASC;
此查询变得缓慢,因为两个表中的数年都有大量数据。
原因我在两个表都有索引,而EXPLAIN ANALYZE
告诉我,INDEX扫描的模式超过了空洞执行时间的80%。
"Sort (cost=44013.52..44013.53 rows=1 width=19) (actual time=17073.129..17073.129 rows=16 loops=1)"
" Sort Key: (date_part('year'::text, master.insert_date)), (date_part('month'::text, master.insert_date))"
" Sort Method: quicksort Memory: 26kB"
" -> HashAggregate (cost=44013.49..44013.51 rows=1 width=19) (actual time=17073.046..17073.053 rows=16 loops=1)"
" Group Key: date_part('year'::text, master.insert_date), date_part('month'::text, master.insert_date)"
" -> Nested Loop (cost=0.43..43860.32 rows=15317 width=19) (actual time=0.056..15951.178 rows=843647 loops=1)"
" -> Seq Scan on master (cost=0.00..18881.38 rows=3127 width=12) (actual time=0.027..636.202 rows=182338 loops=1)"
" Filter: ((date(insert_date) >= '2015-01-01'::date) AND (date(insert_date) <= '2016-12-31'::date))"
" Rows Removed by Filter: 443031"
" -> Index Scan using idx_detail_master_key on detail (cost=0.43..7.89 rows=7 width=15) (actual time=0.055..0.077 rows=5 loops=182338)"
" Index Cond: (master_key = master.master_key)"
" Filter: (amount IS NOT NULL)"
" Rows Removed by Filter: 2"
"Planning time: 105.317 ms"
"Execution time: 17073.396 ms"
所以我的想法是通过将索引大小定义为部分来减小索引大小。在大多数情况下,仅查询过去2年的数据。
所以我尝试了类似的东西:
CREATE INDEX idx_detail_table_master_keys
ON detail (master_key)
WHERE master_key in (SELECT master_key FROM master WHERE (extract( year from insert_date) = 2016) or (extract( year from insert_date) = 2015))
原因这不是最终版本,它只是一个概念证明而且失败了。 PGAdmin告诉我,我不允许在创建索引时使用子选择。
所以我的问题是:根据另一个表的数据创建一个部分索引是不是很有意思?
因为我会感谢任何提示像这样加速星座。
问候
答案 0 :(得分:0)
基于另一个表的数据,不可能创建部分索引,因为像postgresql这样的关系数据库有三种连接方式:嵌套循环,散列连接和排序合并。所有这些方法都单独加载连接表。由于数据库优化器决定将使用哪些方法以及连接将在哪个方向执行,因此创建覆盖另一个表的数据的表索引是没有意义的。这就是您无法定义此类索引的原因。有关此主题的更详细说明,请访问:http://use-the-index-luke.com/sql/join(以及在线图书的以下部分)
如需进一步优化,请参阅Gabriel的Messanger的评论