Dr.*_*YSG 4 postgresql index index-tuning
这个问题与我之前问过的问题有关:PostgreSQL 中复合索引中的列顺序(和查询顺序)
我想我可以在这里尖锐和限制我的问题,而不是超载这个问题。鉴于以下查询(和 EXPLAIN ANALYZE),我正在创建的复合索引有帮助吗?
第一个查询仅使用简单索引(大纲上的 GIST)和(pid 上的 BTREE)运行。
查询是:
EXPLAIN ANALYZE SELECT DISTINCT ON (path) oid, pid, product_name, type, path, size
FROM portal.inventory AS inv
WHERE ST_Intersects(st_geogfromtext('SRID=4326;POLYGON((21.51947021484375 51.55059814453125, 18.9129638671875 51.55059814453125, 18.9129638671875 48.8287353515625, 21.51947021484375 48.8287353515625, 21.51947021484375 51.55059814453125))'), inv.outline)
AND (inv.pid in (20010,20046))
Run Code Online (Sandbox Code Playgroud)
——
结果如下(速度更快,但也许这只是因为数据库是热的)。
"Unique (cost=581.76..581.76 rows=1 width=89) (actual time=110.436..110.655 rows=249 loops=1)"
" -> Sort (cost=581.76..581.76 rows=1 width=89) (actual time=110.434..110.477 rows=1377 loops=1)"
" Sort Key: path"
" Sort Method: quicksort Memory: 242kB"
" -> Bitmap Heap Scan on inventory inv (cost=577.48..581.75 rows=1 width=89) (actual time=39.257..105.878 rows=1377 loops=1)"
" Recheck Cond: ((pid = ANY ('{20010,20046}'::integer[])) AND ('0103000020E6100000010000000500000000000000FC843540000000007AC6494000000000B8E93240000000007AC6494000000000B8E9324000000000146A484000000000FC84354000000000146A484000000000FC843540000000007AC64940'::geography && outline))"
" Rows Removed by Index Recheck: 3731"
" Filter: (_st_distance('0103000020E6100000010000000500000000000000FC843540000000007AC6494000000000B8E93240000000007AC6494000000000B8E9324000000000146A484000000000FC84354000000000146A484000000000FC843540000000007AC64940'::geography, outline, 0::double precision, false) < 1e-005::double precision)"
" Rows Removed by Filter: 533"
" -> BitmapAnd (cost=577.48..577.48 rows=1 width=0) (actual time=38.972..38.972 rows=0 loops=1)"
" -> Bitmap Index Scan on inventory_pid_idx (cost=0.00..123.82 rows=6204 width=0) (actual time=1.116..1.116 rows=7836 loops=1)"
" Index Cond: (pid = ANY ('{20010,20046}'::integer[]))"
" -> Bitmap Index Scan on inventory_outline_idx (cost=0.00..453.41 rows=8212 width=0) (actual time=37.765..37.765 rows=63112 loops=1)"
" Index Cond: ('0103000020E6100000010000000500000000000000FC843540000000007AC6494000000000B8E93240000000007AC6494000000000B8E9324000000000146A484000000000FC84354000000000146A484000000000FC843540000000007AC64940'::geography && outline)"
"Total runtime: 110.731 ms"
Run Code Online (Sandbox Code Playgroud)
现在这里是添加复合索引的结果:(注意绝对时间更慢)
"Unique (cost=37.81..37.82 rows=1 width=89) (actual time=2464.353..2464.561 rows=249 loops=1)"
" -> Sort (cost=37.81..37.82 rows=1 width=89) (actual time=2464.349..2464.389 rows=1377 loops=1)"
" Sort Key: path"
" Sort Method: quicksort Memory: 242kB"
" -> Bitmap Heap Scan on inventory inv (cost=33.54..37.80 rows=1 width=89) (actual time=2361.018..2459.653 rows=1377 loops=1)"
" Recheck Cond: (('0103000020E6100000010000000500000000000000FC843540000000007AC6494000000000B8E93240000000007AC6494000000000B8E9324000000000146A484000000000FC84354000000000146A484000000000FC843540000000007AC64940'::geography && outline) AND (pid = ANY ('{20010,20046}'::integer[])))"
" Filter: (_st_distance('0103000020E6100000010000000500000000000000FC843540000000007AC6494000000000B8E93240000000007AC6494000000000B8E9324000000000146A484000000000FC84354000000000146A484000000000FC843540000000007AC64940'::geography, outline, 0::double precision, false) < 1e-005::double precision)"
" Rows Removed by Filter: 533"
" -> Bitmap Index Scan on inventory_compound_idx (cost=0.00..33.53 rows=1 width=0) (actual time=2321.684..2321.684 rows=1910 loops=1)"
" Index Cond: (('0103000020E6100000010000000500000000000000FC843540000000007AC6494000000000B8E93240000000007AC6494000000000B8E9324000000000146A484000000000FC84354000000000146A484000000000FC843540000000007AC64940'::geography && outline) AND (pid = ANY ('{20010,20046}'::integer[])))"
"Total runtime: 2558.022 ms"
Run Code Online (Sandbox Code Playgroud)
最后,这是表定义:
CREATE TABLE portal.inventory
(
oid bigint,
product_name character varying(100),
type character varying(25),
pid integer,
size bigint,
date timestamp without time zone,
path character varying(200),
outline geography(Polygon,4326)
)
WITH (
OIDS=FALSE
);
CREATE INDEX inventory_compound_idx
ON portal.inventory
USING gist
(outline, pid);
CREATE INDEX inventory_outline_idx
ON portal.inventory
USING gist
(outline);
CREATE INDEX inventory_pid_idx
ON portal.inventory
USING btree
(pid);
Run Code Online (Sandbox Code Playgroud)
更新:对下列问题的回答:
我可以调整表格,但我试图保持行细。您的建议各不相同,类型等是我想更改的内容。
基本上,每一行代表关于地理空间图像文件的一点元数据。我们管理着 5000 万,这很可能会增长到数亿或更多。在 DB 中,每个文件都由唯一的 OID 引用(对不起,术语重复)。它们按“产品”分组,其中 PID 是产品 ID。每个产品可能有大约 1,000 个 OID。每个图像文件都有一个地理空间边界框(轮廓)。这就是我搜索所需的全部内容。其余数据不会为空(type 是文本字符串,size 文件大小,date 是文件创建日期,path 是文件的 UNC 文件路径)。
现在这就是我按大纲排序查询的原因,然后是 PID。产品将按地理空间分组。因此,克拉科夫波兰的所有 OID 行都将在物理上位于同一区域。所以我假设如果我把桶缩小到一个小区域,第二个索引将非常小(比如一个城市区域大约 100 个产品)。IN( ..) 子句将退出。
PIDS 的实际值是从我在这里发布的另一个问题中提取的。但是那个表只针对产品,因此它的大小大约是 30K,这意味着快速搜索并且不需要复合查询。
我想知道 POSTGreSQL 规划器是否足够聪明,可以确定 (outline,pid) 的复合索引是否比 (pid, outline) 更快,如果两个索引都存在。好吧,我想我可以测试。
在 GiST 索引中,列的顺序与在 B 树索引中的意义不同。根据文档:
多列 GiST 索引可以与涉及索引列的任何子集的查询条件一起使用。附加列上的条件限制了索引返回的条目,但第一列上的条件是确定需要扫描多少索引的最重要的条件。如果 GiST 索引的第一列只有几个不同的值,即使附加列中有许多不同的值,它也会相对无效。
简而言之:将最具选择性的列放在首位。
您的EXPLAIN输出显示,所述条件pid是更具选择性(rows=7836)比在一个outline(rows=63112)。如果可以推广(单个示例可能会产生误导),我建议使用以下替代方法:
CREATE INDEX inventory_compound_idx ON portal.inventory USING gist (pid, outline);Run Code Online (Sandbox Code Playgroud)
如果您的大多数(重要)查询都包含两列的条件,则多列索引可能会很好地为您服务。否则,整体上单列可能更好。
这是一个有根据的猜测,因为我没有完整的信息。
不要oid用作列名。很容易与OID.
不要使用date时间戳列的名称。或者说:不要使用名称date的任何列,也不在所有标识符使用基本类型的名称。可能会导致令人困惑的错误和错误消息。
为类型创建一个查找表,只将一个小整数type_id放入大表中。紧紧包装固定长度的类型,以免浪费空间填充。细节。
我更喜欢类型text(或varchar没有长度限制)而不是varchar(n). 细节。
例如:
CREATE TABLE portal.inventory (
inventory_id bigint PRIMARY KEY
,type_id integer NOT NULL REFERENCES inv_type(type_id)
,pid integer NOT NULL
,size bigint NOT NULL
,ts timestamp NOT NULL
,outline geography(Polygon,4326)
,product_name text
,path text
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
535 次 |
| 最近记录: |