理解PostgreSQL中的相关性
当数据库必须执行到另一个表的联接时,它可以从以下三种策略中进行广泛选择:理解PostgreSQL中的相关性,postgresql,indexing,correlation,Postgresql,Indexing,Correlation,当数据库必须执行到另一个表的联接时,它可以从以下三种策略中进行广泛选择: 顺序扫描(当我们需要大多数记录时) 位图索引扫描(当我们需要一些记录时) 索引扫描(当我们需要相对较少的记录时,使用相关索引) 这里的理由是,如果需要保留大多数记录,则完全忽略索引、避免I/O惩罚并按顺序读取整个表更有效。在另一个极端,显然,如果我们只需要从索引中读取几个叶节点,这将比读取整个表更快 我不清楚的是相关性在这里扮演什么角色,以及我们应该如何思考它 以博士后为重点,此处描述了相关性: 列值的物理行顺序和逻辑
- 顺序扫描(当我们需要大多数记录时)
- 位图索引扫描(当我们需要一些记录时)
- 索引扫描(当我们需要相对较少的记录时,使用相关索引)
SELECT attname, correlation
FROM pg_stats
WHERE tablename = 'your_table';
据我所知,使用二级索引总是需要对聚集索引进行I/O搜索,以查找数据。据我所知,唯一能使I/O更好或更差的是,如果辅助索引非常接近磁盘上的聚集索引。但我不清楚相关性对于确定I/O寻道的成本有多大意义,因为始终需要寻道
有人能解释一下相关性在这里的物理意义吗?也许我的困惑是由于不理解数据库如何执行索引扫描而引起的。首先,我们有一些事情很难完全解释,但我会尝试,如果您已经很清楚其中的一些内容,请原谅 因此,随机IOs非常昂贵,因为我们在整个磁盘上读取随机数据块。 一行大容量读取几个块的速度要快得多(特别是在非ssd的磁驱动器上) 现在再进一步,您引用的文档专门讨论索引扫描,它通常是一个范围,而不是一个精确的值 因此,当索引相关时(可以通过相关索引对表进行聚类来强制),并且它正在查找一系列值(其中Id介于1000000和1001000之间),通过“扫描”索引返回的位置(块位置)很可能位于磁盘上几乎相同的位置 因此,它可以去索引ABC,找到1000行,找出它需要读取的块,也许只需几次搜索就可以得到它们。为获得该指数而进行的1次(大约)额外努力是值得的 现在,如果没有相关性,它通过索引进行搜索,发现这1000行都在不同的块中,在驱动器上的不同位置,那么它需要进行多达1000次的搜索才能找到所述数据。最好是从头到尾批量读取整个表。索引上的额外搜索只会让情况变得更糟,而批量读取现在对提高速度没有多大作用
请让我知道这是否有助于解释它。我认为可以通过阅读源代码找到真正的定义;-)
- 统计数据收集器可能使用{ctid,attribvalue}对来估计物理相关性
- 计划者可以使用这些系数来估计要获取的页数
您现在以用户“postgres”的身份连接到数据库“twitters”。
版本
----------------------------------------------------------------------------------------------------------------------------
PostgreSQL 9.6.9基于armv6l未知linux gnueabihf,由gcc(Raspbian 6.3.0-18+rpi1+deb9u1)6.3.0 20170516编译,32位
(1排)
计数
---------
3525068
(1排)
表“public.tweets”
列|类型|修饰符
----------------+--------------------------+------------------------------------------------------
seq | bigint |非空默认nextval('tweets|u seq|u seq'::regclass)
id | bigint |不为空
用户id | bigint |不为空
吸盘id |整数|非空默认值0
在|带时区的时间戳|创建|u
_dm | boolean | not null默认值为false
正文|正文|
在_reply_to _id | bigint |非空默认值0
父项| bigint |非空默认值0
_reply_to_me | boolean | not null默认值为false吗
_retweet | boolean | not null默认值为false吗
|u是否解析| boolean | not null默认值为false
|u是否为|布尔值|非空默认值为false
需要_refetch |布尔值|不为null默认值为false
_troll | boolean | not null默认值为false吗
fetch|U stamp |带时区的时间戳| not null默认值now()
索引:
“tweets_pkey”主键,btree(seq)
“tweets\u id\u key”唯一约束,btree(id)
“tweets\u userid\u id”唯一,btree(user\u id,id)
“tweets_created_at_idx”b树(created_at)
“tweets_du_idx”b树(创建于,用户id)
“tweets\u id\u idx”b树(id)在需要的地方
\connect twitters
SELECT version();
SELECT count(*) from tweets;
\d tweets
SELECT attname, correlation, n_distinct -- , null_frac
FROM pg_stats
WHERE tablename = 'tweets'
AND schemaname = 'public';
You are now connected to database "twitters" as user "postgres".
version
----------------------------------------------------------------------------------------------------------------------------
PostgreSQL 9.6.9 on armv6l-unknown-linux-gnueabihf, compiled by gcc (Raspbian 6.3.0-18+rpi1+deb9u1) 6.3.0 20170516, 32-bit
(1 row)
count
---------
3525068
(1 row)
Table "public.tweets"
Column | Type | Modifiers
----------------+--------------------------+------------------------------------------------------
seq | bigint | not null default nextval('tweets_seq_seq'::regclass)
id | bigint | not null
user_id | bigint | not null
sucker_id | integer | not null default 0
created_at | timestamp with time zone |
is_dm | boolean | not null default false
body | text |
in_reply_to_id | bigint | not null default 0
parent_seq | bigint | not null default 0
is_reply_to_me | boolean | not null default false
is_retweet | boolean | not null default false
did_resolve | boolean | not null default false
is_stuck | boolean | not null default false
need_refetch | boolean | not null default false
is_troll | boolean | not null default false
fetch_stamp | timestamp with time zone | not null default now()
Indexes:
"tweets_pkey" PRIMARY KEY, btree (seq)
"tweets_id_key" UNIQUE CONSTRAINT, btree (id)
"tweets_userid_id" UNIQUE, btree (user_id, id)
"tweets_created_at_idx" btree (created_at)
"tweets_du_idx" btree (created_at, user_id)
"tweets_id_idx" btree (id) WHERE need_refetch = true
"tweets_in_reply_to_id_created_at_idx" btree (in_reply_to_id, created_at) WHERE is_retweet = false AND did_resolve = false AND in_reply_to_id > 0
"tweets_in_reply_to_id_fp" btree (in_reply_to_id)
"tweets_parent_seq_fk" btree (parent_seq)
"tweets_ud_idx" btree (user_id, created_at)
Foreign-key constraints:
"tweets_parent_seq_fkey" FOREIGN KEY (parent_seq) REFERENCES tweets(seq)
"tweets_user_id_fkey" FOREIGN KEY (user_id) REFERENCES tweeps(id)
Referenced by:
TABLE "tweets" CONSTRAINT "tweets_parent_seq_fkey" FOREIGN KEY (parent_seq) REFERENCES tweets(seq)
attname | correlation | n_distinct
----------------+-------------+------------
seq | -0.519016 | -1 #<<-- PK
id | -0.519177 | -1 #<<-- NaturalKey
user_id | -0.0994714 | 1024 # FK to tweeps, cadinality ~= 5000)
sucker_id | 0.846975 | 5 # Low Card
created_at | -0.519177 | -0.762477 # High Card
is_dm | 1 | 1
body | 0.0276537 | -0.859618
in_reply_to_id | 0.104481 | 25956 # FK to self
parent_seq | 0.954938 | 1986 # FK To self
is_reply_to_me | 1 | 2
is_retweet | 0.595322 | 2
did_resolve | 0.909326 | 2
is_stuck | 1 | 1
need_refetch | 1 | 1
is_troll | 1 | 1
fetch_stamp | -0.519572 | 95960 # High Card
(16 rows)