PostgreSQL是一个由世界范围内开发人员在互联网上开发的对象-关系型数据库。她是商业数据库如Oracle和Informix一个开源替代。sql
PostgreSQL最初由加大伯克利分校开发。在1996年,一个团队开始在互联网上开发这个数据库。他们经过邮件来交流思想而且经过文件服务器来共享代码。PostgresSQL如今在专业特性、性能、可靠性上比得上商业数据库。她具备事务、视图、存储过程、引用一致性约束。她支持许多编程接口,包括ODBC、Java(JDBC)、TCL/TK、PHP、Perl和Python。得益于一大批有才干的网络开发者,PostgreSQL 继续以惊人的速度提高 。数据库
有两个方面的数据库性能调优。一个是提升数据库服务器使用的CPU、内存、磁盘驱动。第二个是优化发送到数据库的查询。这篇文章讨论硬件方面的性能调优。查询优化能够经过SQL命令如 CREATE INDEX、VACUUM 、VACUUM FULL、ANALYZE、CLUSTER 和 EXPLAIN 来完成。这些在《PostgreSQL:Introduction and Concepts》中讨论在 http://momjian.us/main/writings/pgsql/aw_pgsql_book/。编程
为了理解硬件调优问题,理解计算机里正在发生什么是很是重要的。简单来讲,计算机能够想象成一个被存储包围着的CPU。在和CPU同一芯片上是几个用来存储中间结果和不一样指针和计数的CPU寄存器。在这些周围是用来保存最近访问信息的CPU缓存。在CPU缓存外面是大量的用来保存正在执行程序和数据的随机访问主存(RAM)。在主存的外面是存储更多信息的磁盘驱动。磁盘驱动是惟一的持久存储区,因此任何要在关机后保持的信息都必须放在那里。总之,在CPU的周围有这些存储:
缓存
存储区域 | 度量单位 |
---|---|
CPU 寄存器 | bytes |
CPU 缓存 | kilobytes |
RAM | megabytes |
磁盘驱动 | gigabytes |
你能够看到距离CPU越远存储越大。理论上,大量的持久存储能够放在CPU旁边,可是会特别慢且比较昂贵。在实践中,常常被使用的信息存储在CPU旁边,不常常访问的信息存储远离CPU,当使用时被带到CPU。安全
在不一样存储区之间移动信息是自动发生的。编译器决定哪些信息保存在寄存器中。CPU芯片逻辑保证最近使用的信息保存在CPU缓存中。操做系统控制哪些信息存储在RAM并在磁盘驱动器间来回穿梭。服务器
CPU寄存器和CPU缓存不能被数据库管理员有效的调优。有效的数据库调优涉及在RAM中增长有用的信息,来尽量的阻止磁盘访问。网络
你可能认为这很容易,可是不是。计算机的RAM包含不少东西:多线程
合适的调优包括在RAM中尽量多的保存数据库信息,同时不影响操做系统的其余区域ide
PostgreSQL 不直接更改磁盘上的信息。相反,它请求读数据到PostgreSQL shared buffer cache。PostgreSQL后台来读和写这些块,而且最终刷到磁盘上。
须要访问表的后台先在缓存中查找须要的块。若是它们已经存在,能够立刻继续处理。若是没有,一个操做系统请求被发送去加载这些块。这些块从内核磁盘缓存或者直接从磁盘加载。这多是昂贵的操做。
你可能想,“我把所有的RAM都给PostgreSQL shared buffer cache”。然而,若是你那样作,会没有其余的空间分配给内核和其余任何要运行的程序。合适的PostgreSQL shared buffer cache 是不产生其余不良活动的最大空间。
为了理解不良活动,你须要去理解UNIX 操做系统怎么管理内存。若是有足够的内存去装进全部的程序和数据,只须要不多的内存管理。然而,若是全部东西不能装进内存,内核开始强制内存刷出到叫swap磁盘区域。它把最近没有使用的内存页移出。这个操做叫作swap pageout。Pageouts 不是问题由于它们发生在非活动时间段。糟糕的是当这些页必须从swap返回时,意为着移到swap的旧页必须移入RAM。这种叫 swap pagin。这种状况糟糕由于当页从swap移动时,程序必须暂停直到pagein完成。
Pagein 活动能够被系统分析工具如vmstat和sar展现,而且暗示没有足够的内存去有效运行。不要混淆swap pageins和ordinary pageins。它包含的页是做为的正常的操做系统读取文件系统的一部分。若是你不能发现swap pageins,许多pageouts 是一个好的暗示,你也正在进行swap pageins。
你可能好奇为何缓存大小如此重要。首先,假设PostgreSQL shared buffer cache 足够大去装下整个表。这张表的重复顺序扫描不须要访问磁盘,由于全部的数据已经在缓存中了。如今假设缓存比表小一个块大小。这个表的顺序扫描须要加载全部的表数据块进入缓存直到最后一个。当须要块时,最老的块被移出,这种状况就是表的第一个块。当另一个顺序扫描发生时,第一个块已经不在缓存中,须要把它从新装入,这时最老的块,也就是这个表的第二个块被移出缓存。这又会把下一个须要的块继续推出去直到这个表的最后。这是一个极端的例子,可是你能够明白减小一个块能够把缓存的效率从100%变为0%。它展现了找到正确的缓存大小能够极大的影响性能。
理想的,PostgreSQL shared buffer cache 应该是:
记住postmaster分配全部的共享内存在它启动的时候。这片区域保持相同的大小即便没有一我的访问数据库。一些操做系统pageout不涉及共享内存,一些锁定主存中的共享内存。锁定共享内存是推荐的。PostgreSQL管理员指南有关于各类操做系统内核参数配置信息。
另一个调优的参数是批量排序使用的内存大小。当排序大表或者结果集,PostgresSQL会分红几部分排序它们,把中间结果放到临时文件中。这些文件合并而且从新排序直到全部的行完成排序。增长批量大小能减小临时文件且常常能加快排序。然而,若是批量排序太大,它们会引发pageins,由于在排序时一部分批量排序pageout到swap区。这种状况下使用更小的批量排序和更多的临时文件是更快的。因此再次,swap pageins 指示已经分配了太多的内存。记住每一个后台排序如ORDER BY,CREATE INDEX,或者merge join都使用这个参数。有几个并行的排序会使用几倍的这个内存大小。
缓存大小和排序大小都影响内存使用,因此你不可能最大化一个而不影响另外一个。记住缓存大小在postmaster启动是分配,而排序大小由正在执行的排序操做的数量决定。一般,缓存大小比排序大小更重要。然而,可预见的使用ORDER BY ,CREATE INDEX或者merge joins的肯定查询能够被大的批量排序大小加速。
同时,不少操做系统限制了多少共享内存能够分配。增长这些限制须要操做系统相关的知识去从新编译或者从新配置内核。更多的信息能够在PostgreSQL管理员指南中找到。
做为调优的起点,若是只有一些大的会话,用15%的主存做为缓存大小,2-4%做为排序大小。若是有不少小的会话能够调的更小。你能够尝试增长他们去看是否有性能提高同时没有swap发生。若是shared buffer cache太大,你会浪费维护太多缓存的管理开销,而且占用其余进程和额外的内核磁盘缓存的RAM。
一个有价值的参数是effective_cache_size。调优者使用这个参数去估计内核磁盘缓存的大小。在不固定缓存大小的内核中,这个参数能够设置成未使用RAM的平均大小,由于这些内核使用未使用的RAM去缓存最近访问的磁盘页。在其余固定大小磁盘缓存的内核中,一般应该把你的内核缓存设置成10%RAM大小。
磁盘驱动的物理特性致使了不一样于文章中提到的其余存储区域的性能特色。其余的存储区域能够以相同速度访问任何字节。磁盘驱动有它本身的自旋盘和移动头,访问在磁头附近的数据比距离远的数据快的多。
移动磁头去盘面的另外磁柱须要花费一些时间。Unix开发者知道这个特性。当排序磁盘上的大文件,他们尝试把文件的各个条放在一块儿。例如,假设一个文件须要10个磁盘块。操做系统可能把1-5块放在一个磁柱上,6-10块放在另外磁柱上。若是这个文件须要从头读到未,只须要磁头移动两次。--一次获取1-5块的磁柱,一次获取6-10块。然而,若是文件不是顺序读,如块1,6,2,7,3,8,4,9,5,10;须要10次磁头移动。你能够看到,在磁盘上,顺序读比随机读快不少。这是为何若是一个表的大部份内容须要被读,PostgreSQL偏向于顺序扫描而不是索引扫描。这也凸显了缓存的价值。
磁头在数据库活动期间移动至关多。若是产生太多的读写请求,驱动会变得饱和,致使性能不佳。(vmstat和sar能够提供每一个磁盘活动量的信息)
一个磁盘饱和的解决方法是移动一些PostgreSQL的数据文件到其余磁盘。记着,移动文件到同一磁盘的其余文件系统没有帮助。全部在同一磁盘的文件系统使用同一个磁头。
经过磁盘驱动的数据库访问能够经过如下几个方法加速:
移动数据库、表、索引
表空间容许你在不一样的驱动上建立对象。
移动WAL
initdb -X 和符号链接能够用来移动pg_xlog目录到不一样的磁盘驱动。不像其余的写操做,PostgreSQL 写日志必须在事务完成前刷到磁盘。缓存不能用来推迟这些写操做。为写日志使用单独的磁盘能够容许磁头停留在当前日志的磁柱而没有移动延迟。(你可使用postgres -F 参数来阻止日志刷到磁盘,可是一个操做系统灾难须要从备份中恢复)
其余的选项包括使用磁盘阵列,经过多个磁盘驱动加速一个文件系统。镜像会下降数据库写速度,可是会加速数据库读,由于数据能够从每一个驱动中得到。许多站点使用RAID1+0或RAID0+1,由于它同时提供了性能和可靠的优点。RAID5对于6个或者更多驱动来讲是更快的。理论上,RAID 5将有一个由电池支持的高速缓存,所以写入能够以一种有效的方式刷新到磁盘,而不是在编写文件的时候减慢应用程序的速度。
现代磁盘驱动都有读和写缓存。读缓存保证最近请求的磁盘块在磁盘内存中可用。写缓存保存写请求直到它们能够有效的存储到盘面上。你可能意识到这可能产生问题--若是磁盘断电了,当它持有的写数据还没写到磁盘上怎么办?一些磁盘驱动和RAID控制器有后备电池写缓存来保证数据安全,且当电源彻底恢复时把数据写到盘面。然而,大部分驱动没有这种特性,所以它们是不可靠的。
幸运的是,在大多数驱动你能够关闭写缓存。SCSI驱动默认关闭写缓存。IDE设备写缓存一般是打开的,可是能够从操做系统命令关闭如hdparm -W0,sysctl hw.ata.wc=0或者scsimd。可是,一些IDE驱动虽然报告写缓存关闭了,可是仍在使用它,这是不可靠的。没有精确的测试很难判断哪一个驱动在撒谎。
由于PostgreSQL每一个事务提交时使用fsync()写WAL日志到磁盘,而且等待写完成。当使用写缓存时用户能看到巨大的性能提高。所以,为了性能和可靠性,若是PostgreSQL能使用有后备电池的写缓存是一个理想的方案。
SCSI驱动一般比IDE驱动贵不少。SCSI驱动有一个协议用来在操做系统和控制器间通讯,然而IDE驱动简单的多且同一时刻只能接受一个请求。有标记队列的SCSI驱动能够接受多个请求而且从新排列它们提升效率。这是为何当单用户或者单文件IO时SCSI和IDE驱动有类似的性能特性,可是当多个用户或者进程请求时SCSI比IDE性能更好。所以,SCSI更适合重负载数据库服务器。
实际上,SCSI或IDE是惟一的方法区分两种主要的驱动:企业驱动,为高性能和高可靠设计。我的电脑驱动,为最小耗费设计。这篇文章http://www.seagate.com/content/docs/pdf/whitepaper/D2c_More_than_Interface_ATA_vs_SCSI_042003.pdf,作了优秀的工做来描述在生产基于性能可靠性或者减少耗费的驱动。它是一个优秀的指导在选择基于这些特性的驱动。
一些操做系统支持多磁盘文件系统。在这种状况,可能很难知道哪一个文件系统表现最好。PostgreSQL一般在传统的Unix文件系统表现最好,像不少操做系统支持的BSD UFS/FFS等。UFS默认的8K块大小和PostgreSQL的页大小同样。你能够运行在日志和基于日志的文件系统,可是这些会在WAL的fsync执行期间引发额外的开销。老的基于SvR3的文件系统变的太碎片难以有好的性能。
由于有许多文件系统能够选择而且没有一个是最优的,Linux上的文件系统选择是特别困难的:ext2不是彻底的灾难安全的,ext3,XFS和JFS是基于日志的且Reiser是对小文件优化且记录日志。虽然ext2比日志文件系统块不少,可是当要求灾难恢复时ext2是不可选的。若是必须使用ext2,使用sync enabled挂载。一些人推荐使用ext3时用data=writeback挂载。
不推荐PostgreSQL使用NFS和其余远程文件系统。NFS和本地文件系统没有同样的文件系统特性,这些不一致可能引发数据可靠和灾难恢复问题。
PostgreSQL使用多进程模型,意为着每一个数据库链接拥有它本身的unix进程。所以,全部多CPU操做系统能够经过可用的CPU来加速多数据库链接。然而,若是只有一个数据库链接是活动的,它只能使用一个CPU。PostgreSQL没有使用多线程模型从而容许一个进程使用多个CPU。
当WAL文件充满时,一个检查点被执行来强制全部的脏缓存刷到磁盘,从而使日志文件能够循环。检查点也会在固定的时间间隔被执行,一般是5分钟。若是有不少的数据库写活动,WAL段会很块被充满,致使全部磁盘缓存被刷到磁盘引发系统过分的缓慢。
检查点应该每几分钟发生一次。若是在一分钟发生几回,性能会变差。在服务日志中查找"checkpoint_warning"消息来决定你的检查点是否执行太频繁。若是30秒内检查点执行超过一次,会出现这个消息。
减少检查点的频率包括增长在data/pg_xlog中WAL文件的数量。每一个文件是16 megabyte,因此它影响磁盘使用率。默认的配置使用了最小数量的日志文件。为了减少检查点频率,你须要增长这个参数:
checkpoint_segments=3
默认值是3。增长它直到检查点几分钟出现一次。另一个可能出现的消息是:
LOG:XLogWrite:new log file created - consider increasing WAL_FILES
这个消息暗示postgresql.conf中的wal_files参数须要增长。
幸运的是,PostgreSQL 不须要太多调优。大部分参数自动调整到最佳性能。缓存大小和排序大小是两个参数管理员可以控制去更好的利用可用内存。磁盘访问能够经过多个驱动加速。其余参数可能设置在share/postgresql.conf.sample。你能够copy到data/postgresql.conf去实验其余PostgreSQL更奇异的参数。