我有一张有5万行的表格。它实际上是一个PostGIS表。
该查询分为4个部分(1个必填项)(3个可选)
- 长4纬度(我使用st_intersects)的相交箱(地理矩形)[必须]
- 日期字段上的日期范围(最小,最大)
- 当前使用IN(.....)的文件类型(最多8个文本值的集合),但是如果需要,我可以将其设为临时表。我看到很多人不喜欢IN。
- 国家(文本值)。
我预计将返回约100-4,000行
如果在表上创建复合索引,则应首先使用哪一列。细粒度可能是位置(数据分布在世界各地)。我目前将其作为GIST索引。
其他索引将是BTREE。
我的直觉说,使用细颗粒,最后选择。例如,只有大约12种文件类型,因此对于索引而言这将是非常大的存储桶。
PostgreSQL和PostGIS专家(谁知道系统的内部结构)怎么说?
更新:
让我提出这个问题。
- 我不希望任何人必须做我应该做的工作。我非常尊重您的时间。因此我将在后面进行解释分析。
- 我所寻找的只是一些指示,技巧和指南。
- 我阅读了这篇出色的小文章:https : //devcenter.heroku.com/articles/postgresql-indexes#managing-and-maintaining-indexes关于索引
- 我通常要做的是创建4个单独的索引(地理框,国家/地区名称,file_type和日期),但是要查看复合查询的作用。
告诉我这些假设是否有误。(我对复合索引的想法很陌生)
- 顺序很重要。选择最能减少行数的索引作为第一个索引(在我的情况下,简单的多边形或多多边形的位置(地理位置)将是最好的)。
- 有时查询会跳过索引。但是,如果我使用键(#1,#2,#3,#4)创建了一个复合查询,那么即使用户创建了要求#1,#3的内容,计划者仍会使用单个复合查询,因为他们要订购被维持。
- 通常,我将创建三个BTREE查询和一个GIST(针对地理位置类型)。PostGIS不支持从多个索引类型创建复合。因此,我将不得不使用GIST复合索引。但这不应该伤害任何事情。
- 如果我确实创建了其他一些复合或单值索引,则计划程序足够聪明,可以选择最聪明的一个。
- 国家/地区名称可以有大约250个不同的值,并且显然与位置(地理框)紧密相关,但是如果要减小行大小的下一个最佳索引是file_type,我应该在下一个使用。我不希望用户在他们的查询集中经常使用国家或日期。
- 我不必担心创建4个键的复合索引会大大增加索引数据的大小。即,如果一键索引将是性能提升的90%,那么再添加3项使其复利也不会有什么坏处。相反,我应该真正创建两个索引。一个单一的地理索引,还有一个复合索引,然后让计划者确定哪一个是最佳的,并且它将考虑索引表的大小。
再说一次,我不是要任何人来设计我的解决方案,也不是要别人的工作。但是我确实需要PostGreSQL文档不会告诉我有关实现的内容
[我没有显示EXPLAIN结果的原因是,我必须从24M行表中创建此25K行表。这比我想象的要花费更多的时间。我将事物分为1,000个项目组,并让用户针对25K行表进行查询。但是,我的下一个问题将涉及使用该查询的结果转到MASTER 25M行表并提取内容,这就是复合索引的性能真正达到HIT的位置。
下面的示例查询:
SELECT
public.product_list_meta_mv.cntry_name AS country,
public.product_list_meta_mv.product_producer AS producer,
public.product_list_meta_mv.product_name AS prod_name,
public.product_list_meta_mv.product_type AS ptype,
public.product_list_meta_mv.product_size AS size,
ST_AsGeoJSON(public.product_list_meta_mv.the_geom, 10, 2) AS outline
FROM
public.product_list_meta_mv
WHERE
public.product_list_meta_mv.cntry_name = 'Poland'
AND
ST_Intersects(public.product_list_meta_mv.the_geom,
st_geogfromtext('SRID=4326;POLYGON((21.23107910156250 51.41601562500000,
18.64379882812500 51.41601562500000,
18.64379882812500 48.69415283203130,
21.23107910156250 48.69415283203130,
21.23107910156250 51.41601562500000))'))
AND (date >= '1/2/1900 5:00:00 AM'
AND date <= '2/26/2014 10:26:44 PM')
AND (public.product_list_meta_mv.product_type in
('CIB10','DTED0','DTED1','DTED2','CIB01','CIB05')) ;
解释分析结果(我没有放入任何复合索引,并且从速度来看,我不知道是否需要这样做)。
"Bitmap Heap Scan on catalog_full cat (cost=4.33..37.49 rows=1 width=7428) (actual time=1.147..38.051 rows=35 loops=1)"
" Recheck Cond: ('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography && outline)"
" Filter: (((type)::text = ANY ('{CADRG,CIB10,DTED1,DTED2}'::text[])) AND (_st_distance('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography, outline, 0::double precision, false) < 1e-005::double precision))"
" Rows Removed by Filter: 61"
" -> Bitmap Index Scan on catalog_full_outline_idx (cost=0.00..4.33 rows=8 width=0) (actual time=0.401..0.401 rows=96 loops=1)"
" Index Cond: ('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography && outline)"
"Total runtime: 38.109 ms"
EXPLAIN ANALYZE SELECT pid,product_name,type,country,date,size,cocom,description,egpl_date,ST_AsGeoJSON(outline, 10, 2) AS outline
FROM portal.catalog_full AS cat
WHERE ST_Intersects(st_geogfromtext('SRID=4326;POLYGON((21.2200927734375 51.38031005859375, 18.65478515625 51.38031005859375, 18.65478515625 48.7298583984375, 21.2200927734375 48.7298583984375, 21.2200927734375 51.38031005859375))'), cat.outline)
AND (cat.type in ('CADRG','CIB10','DTED1','DTED2'))
EXPLAIN ANALYZE
查询。