如何针对更新(软件和硬件)的大量 I/O 优化数据库

Nie*_*ian 23 postgresql performance update hardware

情况 我有一个 postgresql 9.2 数据库,它一直都在大量更新。因此系统受 I/O 限制,我目前正在考虑进行另一次升级,我只需要一些关于从哪里开始改进的指导。

以下是过去 3 个月情况的图片:

在此处输入图片说明

如您所见,更新操作占磁盘利用率的大部分。这是另一张更详细的 3 小时窗口中情况的图:

在此处输入图片说明

如您所见,峰值写入速率约为 20MB/s

软件 服务器运行 ubuntu 12.04 和 postgresql 9.2。更新类型通常在由 ID 标识的单个行上进行小更新。例如UPDATE cars SET price=some_price, updated_at = some_time_stamp WHERE id = some_id。我已经尽可能多地删除和优化了索引,并且服务器配置(linux 内核和 postgres conf)也非常优化。

硬件 硬件是一个专用服务器,带有 32GB ECC ram、RAID 10 阵列中的 4 个 600GB 15.000 rpm SAS 磁盘,由带有 BBU 的 LSI RAID 控制器和英特尔至强 E3-1245 四核处理器控制。

问题

  • 对于这种口径(读/写)的系统,图表所看到的性能是否合理?
  • 因此,我应该专注于进行硬件升级还是深入研究软件(内核调整、confs、查询等)?
  • 如果进行硬件升级,磁盘数量是性能的关键吗?

- - - - - - - - - - - - - - - 更新 - - - - - - - - - - ----------------

我现在用四个 intel 520 SSD 而不是旧的 15k SAS 磁盘升级了我的数据库服务器。我正在使用相同的突袭控制器。事情已经有了很大的改善,正如您从下面看到的,峰值 I/O 性能提高了大约 6-10 倍 - 这太棒了! 在此处输入图片说明 但是,根据答案和新 SSD 的 I/O 功能,我期待更像是 20-50 倍的改进。所以这里有另一个问题。

新问题 我当前的配置中是否存在限制我系统的 I/O 性能的东西(瓶颈在哪里)?

我的配置:

/etc/postgresql/9.2/main/postgresql.conf

data_directory = '/var/lib/postgresql/9.2/main'
hba_file = '/etc/postgresql/9.2/main/pg_hba.conf'
ident_file = '/etc/postgresql/9.2/main/pg_ident.conf'
external_pid_file = '/var/run/postgresql/9.2-main.pid'
listen_addresses = '192.168.0.4, localhost'
port = 5432
unix_socket_directory = '/var/run/postgresql'
wal_level = hot_standby
synchronous_commit = on
checkpoint_timeout = 10min
archive_mode = on
archive_command = 'rsync -a %p postgres@192.168.0.2:/var/lib/postgresql/9.2/wals/%f </dev/null'
max_wal_senders = 1
wal_keep_segments = 32
hot_standby = on
log_line_prefix = '%t '
datestyle = 'iso, mdy'
lc_messages = 'en_US.UTF-8'
lc_monetary = 'en_US.UTF-8'
lc_numeric = 'en_US.UTF-8'
lc_time = 'en_US.UTF-8'
default_text_search_config = 'pg_catalog.english'
default_statistics_target = 100
maintenance_work_mem = 1920MB
checkpoint_completion_target = 0.7
effective_cache_size = 22GB
work_mem = 160MB
wal_buffers = 16MB
checkpoint_segments = 32
shared_buffers = 7680MB
max_connections = 400 
Run Code Online (Sandbox Code Playgroud)

/etc/sysctl.conf

# sysctl config
#net.ipv4.ip_forward=1
net.ipv4.conf.all.rp_filter=1
net.ipv4.icmp_echo_ignore_broadcasts=1
# ipv6 settings (no autoconfiguration)
net.ipv6.conf.default.autoconf=0
net.ipv6.conf.default.accept_dad=0
net.ipv6.conf.default.accept_ra=0
net.ipv6.conf.default.accept_ra_defrtr=0
net.ipv6.conf.default.accept_ra_rtr_pref=0
net.ipv6.conf.default.accept_ra_pinfo=0
net.ipv6.conf.default.accept_source_route=0
net.ipv6.conf.default.accept_redirects=0
net.ipv6.conf.default.forwarding=0
net.ipv6.conf.all.autoconf=0
net.ipv6.conf.all.accept_dad=0
net.ipv6.conf.all.accept_ra=0
net.ipv6.conf.all.accept_ra_defrtr=0
net.ipv6.conf.all.accept_ra_rtr_pref=0
net.ipv6.conf.all.accept_ra_pinfo=0
net.ipv6.conf.all.accept_source_route=0
net.ipv6.conf.all.accept_redirects=0
net.ipv6.conf.all.forwarding=0
# Updated according to postgresql tuning
vm.dirty_ratio = 10
vm.dirty_background_ratio = 1
vm.swappiness = 0
vm.overcommit_memory = 2
kernel.sched_autogroup_enabled = 0
kernel.sched_migration_cost = 50000000
Run Code Online (Sandbox Code Playgroud)

/etc/sysctl.d/30-postgresql-shm.conf

# Shared memory settings for PostgreSQL
# Note that if another program uses shared memory as well, you will have to
# coordinate the size settings between the two.
# Maximum size of shared memory segment in bytes
#kernel.shmmax = 33554432
# Maximum total size of shared memory in pages (normally 4096 bytes)
#kernel.shmall = 2097152
kernel.shmmax = 8589934592
kernel.shmall = 17179869184
# Updated according to postgresql tuning
Run Code Online (Sandbox Code Playgroud)

输出 MegaCli64 -LDInfo -LAll -aAll

Adapter 0 -- Virtual Drive Information:
Virtual Drive: 0 (Target Id: 0)
Name                :
RAID Level          : Primary-1, Secondary-0, RAID Level Qualifier-0
Size                : 446.125 GB
Sector Size         : 512
Is VD emulated      : No
Mirror Data         : 446.125 GB
State               : Optimal
Strip Size          : 64 KB
Number Of Drives per span:2
Span Depth          : 2
Default Cache Policy: WriteBack, ReadAhead, Direct, Write Cache OK if Bad BBU
Current Cache Policy: WriteBack, ReadAhead, Direct, Write Cache OK if Bad BBU
Default Access Policy: Read/Write
Current Access Policy: Read/Write
Disk Cache Policy   : Disk's Default
Encryption Type     : None
Is VD Cached: No
Run Code Online (Sandbox Code Playgroud)

Tom*_*Tom 11

如果进行硬件升级,磁盘数量是性能的关键吗?

是的,因为硬盘 - 甚至是 SAS - 都有一个需要时间移动的磁头。

想要 HGH 升级?

杀死 SAS 光盘,转到 SATA。插入SATA SSD - 企业级,如三星843T。

结果?每个驱动器可以执行大约 60.000(即 60000)IOPS。

这就是 SSD 是数据库空间中的杀手并且比任何 SAS 驱动器便宜得多的原因。物理旋转磁盘无法跟上磁盘的 IOPS 能力。

您的 SAS 磁盘是一个普通的选择(太大而无法获得大量 IOPS)对于更高使用率的数据库(更小的磁盘意味着更多的 IOPS),但最终 SSD 是这里的游戏规则改变者。

关于软件/内核。任何体面的数据库都会执行大量 IOPS 并刷新缓冲区。为了保证基本的 ACID 条件,需要写入日志文件。您可以做的唯一内核调整会使您的事务完整性无效-部分您可以逃脱。写回模式下的 Raid 控制器会这样做 - 即使没有刷新也确认写入已刷新 - 但它可以这样做,因为假设 BBU 在断电的那一天是安全的。你在内核中做的任何事情 - 更好地知道你可以忍受负面影响。

最后,数据库需要 IOPS,您可能会惊讶地发现,与这里的其他设置相比,您的设置是多么微小。我见过有 100 多个磁盘的数据库只是为了获得他们需要的 IOPS。但实际上,今天,您购买 SSD 并选择它们的尺寸 - 它们在 IOPS 功能方面如此出色,用 SAS 驱动器对抗这场游戏是没有意义的。

是的,您的 IOPS 数字对于硬件来说看起来不错。在我所期望的范围内。


kgr*_*ttn 6

如果您负担得起,请将 pg_xlog 放在单独的 RAID 1 对驱动器上,该驱动器位于其自己的控制器上,并为回写配置了由电池供电的 RAM。即使您需要对 pg_xlog 使用旋转锈蚀,而其他所有内容都在 SSD 上,也是如此。

如果您使用 SSD,请确保它具有超级电容器或其他方式来在断电时保留所有缓存数据。

一般来说,更多的心轴意味着更多的 I/O 带宽。

  • @NielsKristian 当我说在大多数系统中事务日志是磁盘上写入最多的内容时,我认为我是对的。此外,写入它基本上与写入数据并行。使用 HDD 不能同时完成这两个操作,因为磁头位于 pg_xlog 或数据文件夹中。(严重简化警报!)将两个任务分开将 IO 负担分摊到两个独立的磁盘/阵列上。 (2认同)
  • 除了@dezso 所说的之外,硬盘驱动器也可以用于 WAL 专用存储,因为访问几乎完全是顺序的,因此查找时间最短。 (2认同)