提高postgreSQL

时间:2016-08-01 16:48:07

标签: sql database performance postgresql join

我正在尝试在postgreSQL数据库中的两个表之间进行左连接,并且发现它需要大约14分钟才能运行。从现有的SO帖子来看,似乎这种类型的连接应该在几秒钟的数量级,所以我想知道如何提高此连接的性能。我使用64-bitpostgreSQL version 9.4.4计算机Windows 8上运行8 GB RAM pgAdmin IIIexplain (analyze, buffers)。表格结构如下:

表A:“parcels_qtr”:

  

parcel(text)| yr(int)| qtr(文本)| lpid(pk,text)|

有1550万行,每列都被编入索引,“lpid”是主键。我还通过一个标准的真空过程来运行这个表。

表B:“postalvac_qtr”:

  

parcel(text)| yr(int)| qtr(文本)| lpid(pk,text)| vacCountY(int)|

有618,000条记录,除“vacCountY”以外的所有字段都被编入索引,“lpid”是主键。这也经历了标准的真空过程。

运行数据输出时,大约需要14分钟。使用EXPLAIN (ANALYZE, BUFFERS) select a.parcel, a.lpid, a.yr, a.qtr, b."vacCountY" from parcels_qtr as a left join postalvac_qtr as b on a.lpid = b.lpid; 运行时需要花一点多时间。第一个问题 - 这种性能上的差异完全归因于打印数据还是其他事情发生在这里?

第二个问题,我可以将运行时间缩短到几秒钟吗?

这是我的SQL代码:

shown.bs.modal

以下是我的解释声明的结果:https://explain.depesz.com/s/uKkK

我对postgreSQL很新,所以耐心和解释会非常感激!

1 个答案:

答案 0 :(得分:7)

你要求DB做很多工作。只看一下解释计划,就是:

  1. 读入整个表格(postalvac_qtr
  2. 根据lpid
  3. 构建哈希
  4. 读入另一个更大的表(parcels_qtr
  5. 散列15MM lpid中的每一个,并将它们与现有哈希表匹配
  6. 这些桌子有多大?您可以通过发出以下内容来检查:

    SELECT pg_size_pretty(pg_relation_size('parcels_qtr'));
    

    我几乎可以肯定这个散列连接会溢出到磁盘,以及它的结构方式(“从这两个表中”给我所有的数据“),这是不可能的不会。

    指数没有帮助,也没有。只要你要求整个表,使用索引只会让事情变慢 - 无论如何,postgres必须遍历整个表,所以它也可以发出顺序扫描。

    至于为什么查询的性能与explain analyze不同,我怀疑你是对的。将1-15行发送到您的客户端,2-尝试显示它们的组合将导致实际查询之外的显着减速。

    那么,你能做些什么呢?

    首先,这个查询试图做什么?您是否经常在这两个表中抓取所有数据,完全未经过滤?如果它很常见,您可能需要考虑回到需求阶段并找出解决该需求的另一种方法(例如,获取给定年份和季度的所有数据是否合理?)。如果它不常见(比如每日出口),则1-14分钟可能没问题。

    其次,你应该确保你的表不会膨胀。如果您在表格中遇到重要的updatedelete流量,那么这会随着时间的推移而增长。 autovacuum守护程序可以帮助解决这个问题,但偶尔发布vacuum full也会有所帮助。

    第三,您可以尝试调整数据库配置。在postgresql.conf中,有一些参数可用于服务器可用于磁盘缓存的预期RAM量,以及服务器可用于排序或连接的RAM量(在它溢出到磁盘之前)。通过修改这些参数,您可以提高速度。

    第四,您可能想要重新访问您的架构。您是希望将年份和季度作为两个单独的列,还是使用date类型的单个列更好?您想要一个text密钥吗?或者您最好使用bigint(序列或从text列派生),这可能会更快加入?两个表中实际需要parcelyrqtr字段,还是在一个表中重复数据?

    无论如何,我希望这有帮助。