理解PostgreSQL中的相关性

理解PostgreSQL中的相关性,postgresql,indexing,correlation,Postgresql,Indexing,Correlation,当数据库必须执行到另一个表的联接时,它可以从以下三种策略中进行广泛选择: 顺序扫描(当我们需要大多数记录时) 位图索引扫描(当我们需要一些记录时) 索引扫描(当我们需要相对较少的记录时,使用相关索引) 这里的理由是,如果需要保留大多数记录,则完全忽略索引、避免I/O惩罚并按顺序读取整个表更有效。在另一个极端,显然,如果我们只需要从索引中读取几个叶节点,这将比读取整个表更快 我不清楚的是相关性在这里扮演什么角色,以及我们应该如何思考它 以博士后为重点,此处描述了相关性: 列值的物理行顺序和逻辑

当数据库必须执行到另一个表的联接时,它可以从以下三种策略中进行广泛选择:

  • 顺序扫描(当我们需要大多数记录时)
  • 位图索引扫描(当我们需要一些记录时)
  • 索引扫描(当我们需要相对较少的记录时,使用相关索引)
这里的理由是,如果需要保留大多数记录,则完全忽略索引、避免I/O惩罚并按顺序读取整个表更有效。在另一个极端,显然,如果我们只需要从索引中读取几个叶节点,这将比读取整个表更快

我不清楚的是相关性在这里扮演什么角色,以及我们应该如何思考它

以博士后为重点,此处描述了相关性:

列值的物理行顺序和逻辑顺序之间的统计相关性。这个范围从-1到+1。当该值接近-1或+1时,由于减少了对磁盘的随机访问,估计对列的索引扫描要比接近零时便宜。(如果列数据类型没有<运算符,则此列为空。)

下面是一种方法,我们可以通过该方法获得给定表中每列的相关值:

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}对来估计物理相关性
  • 计划者可以使用这些系数来估计要获取的页数
例如,下面是我的twitter吸盘数据库的统计数据,运行在Raspberry Pi上: (目前约350万排)



您现在以用户“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)