加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_丽江站长网 (http://www.0888zz.com/)- 科技、建站、数据工具、云上网络、机器学习!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

linux – PostgreSQL 8.4.4中大型连接查询的性能不佳,尽管有足够

发布时间:2021-03-05 13:17:19 所属栏目:Linux 来源:网络整理
导读:题 如何使这篇文章中描述的查询更快,特别是使用可用的RAM制作PostgreSQL? – 请注意,我已尝试正确配置effective_cache_size和shared_buffers.见下文. 背景 我必须定期加入一个约2.6亿行表(coreg_master),其中包含新数据.我已经对表进行了分区,以使每个分

如何使这篇文章中描述的查询更快,特别是使用可用的RAM制作PostgreSQL? – 请注意,我已尝试正确配置effective_cache_size和shared_buffers.见下文.

背景

我必须定期加入一个约2.6亿行表(coreg_master),其中包含新数据.我已经对表进行了分区,以使每个分区都适合RAM.我当然也有适当的索引设置.但是,当分区表与其他(小得多)表分开加入时,它在磁盘上执行完全随机的IO.这是由于大表上的嵌套循环索引扫描,由于我们没有很好的磁盘设置,因此非常慢.

我希望它使用所有可用的RAM来缓存大型分区表,我理解应该由Linux内核/文件系统本身来完成.但它仍然没有将表加载到RAM中,尽管它适合.我想这是因为访问模式不是顺序的,因此不会触发缓存?我不知道.查询计划和配置参数如下.

表结构

这是我的大表coreg_master的一个分区.分区表名为coreg_a,coreg_b等.

d coreg_a
                                   Table "public.coreg_a"
   Column    |       Type        |                         Modifiers                         
-------------+-------------------+-----------------------------------------------------------
 id          | integer           | not null default nextval('coreg_master_id_seq'::regclass)
 first_name  | character varying | 
 last_name   | character varying | 
 phone       | character varying | 
 city        | character varying | 
 zip         | integer           | 
 address     | character varying | 
 dob         | date              | 
 ip          | character varying | 
 source      | character varying | 
 gender      | character varying | 
 state       | character varying | 
 record_date | date              | 
 email       | character varying | 
Indexes:
    "coreg_a_name" btree (lower(first_name::text),lower(last_name::text))
Check constraints:
    "coreg_a_first_name_check" CHECK (first_name::text >= 'a'::text AND first_name::text < 'b'::text)
Inherits: coreg_master

以下是表appendable_24的分区,该表是与coreg_master连接的表的示例.它的分区方式与coreg_master相同,所以实际上coreg_a与appendable_24_a等一起加入,一次一个.

d appendable_24_a
       Table "public.appendable_24_a"
   Column   |       Type        | Modifiers 
------------+-------------------+-----------
 line_num   | integer           | not null
 first_name | character varying | 
 last_name  | character varying | 
 address    | character varying | 
 state      | character varying | 
 zip        | integer           | 
Indexes:
    "appendable_24_a_name_index" btree (lower(first_name::text),lower(last_name::text))
Check constraints:
    "appendable_24_a_first_name_check" CHECK (first_name::text >= 'a'::text AND first_name::text < 'b'::text)
Inherits: appendable_24

查询&解释分析

下面是最小连接的解释分析的输出(表根据first_name列的第一个字母进行分区),因为它不需要很长时间.但是,查询计划对于每个分区上的所有连接都是相同的,因此它应该代表较大的连接(注意,我对表进行了分析,总时间实际上是20秒,但在此处更快,因为结果被缓存):

explain analyze SELECT
          coreg_x.phone,coreg_x.email,coreg_x.record_date,appendable_24_x.line_num
        FROM appendable_24_x INNER JOIN coreg_x ON
          lower(appendable_24_x.first_name) = lower(coreg_x.first_name) AND
          lower(appendable_24_x.last_name) = lower(coreg_x.last_name) AND
          (coreg_x.phone IS NOT NULL OR coreg_x.email IS NOT NULL) AND
          similarity(lower(appendable_24_x.address),lower(coreg_x.address)) > 0.7
      ; 
                                                                                       QUE
RY PLAN 

------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------
-----
 Nested Loop  (cost=0.01..640.49 rows=875 width=39) (actual time=9.990..53.839 rows=29 loo
ps=1)
   Join Filter: (similarity(lower((appendable_24_x.address)::text),lower((coreg_x.address
)::text)) > 0.7::double precision)
   ->  Seq Scan on appendable_24_x  (cost=0.00..1.80 rows=80 width=34) (actual time=0.009.
.0.111 rows=80 loops=1)
   ->  Index Scan using coreg_x_name on coreg_x  (cost=0.01..7.95 rows=1 width=64) (actual
 time=0.024..0.137 rows=44 loops=80)
         Index Cond: ((lower((coreg_x.first_name)::text) = lower((appendable_24_x.first_na
me)::text)) AND (lower((coreg_x.last_name)::text) = lower((appendable_24_x.last_name)::tex
t)))
         Filter: ((coreg_x.phone IS NOT NULL) OR (coreg_x.email IS NOT NULL))
 Total runtime: 53.950 ms
(7 rows)

一些统计信息,配置参数和其他数据

> PostgreSQL版本:8.4.4
>操作系统:CentOS 5.5版(最终版)
>文件系统:ext3
>可用内存总量:8GB
> shared_buffers = 2GB
> effective_cache_size = 7200MB
>通过show all:http://pastie.org/1159746完整运行时配置
>最大分区coreg表(coreg_j)大小:~4900MB
>相应的行数:~3200万
>对应的(first_name,last_name)索引大小:~1000MB
>第二个分区表(appendable_24_j)大小:~1800kB
> appendable_24_j中的行:~25,000

解决方法

只有足够的ram来缓存你的数据库的一小部分,并且当你发布的查询计划显示时,先前访问的数据/有问题的索引的部分确实被缓存. (Postgres不缓存查询结果).

53毫秒运行时不是太破旧,我不确定未缓存数据20秒意味着PG选择了错误的查询计划.毕竟,只有相关的索引是1GB大,但看到分析输出慢速查询会很有趣.

如果这是您的问题,您可以尝试调整计划员成本,看看是否会对最坏情况的性能产生任何影响.

您可能还想稍微增加maintentance_work_mem,即使这与其无关.

(编辑:应用网_丽江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读