---
title: 基于鲲鹏服务器的达梦数据库调优参考实践-官方技术文章-鲲鹏社区
description: 本参考实践基于鲲鹏920新型号服务器部署达梦数据库，为进一步发挥硬件潜能、提升数据库整体性能，针对该场景开展调优工作，以充分释放鲲鹏的极致算力、优化用户使用体验。
keywords: 基于鲲鹏服务,器的达梦数据,库调优参考实,官方技术文章,鲲鹏社区,非商用声明,方案概述,背景
url: https://www.hikunpeng.com/developer/techArticles/20260626-6?envFlag=1
section: (其他)
---

# 基于鲲鹏服务器的达梦数据库调优参考实践-官方技术文章-鲲鹏社区

URL: https://www.hikunpeng.com/developer/techArticles/20260626-6?envFlag=1
描述: 本参考实践基于鲲鹏920新型号服务器部署达梦数据库，为进一步发挥硬件潜能、提升数据库整体性能，针对该场景开展调优工作，以充分释放鲲鹏的极致算力、优化用户使用体验。
关键词: 基于鲲鹏服务,器的达梦数据,库调优参考实,官方技术文章,鲲鹏社区,非商用声明,方案概述,背景

官方技术文章 [了解详情](https://www.hikunpeng.com/zh/developer/techArticles)

基于鲲鹏服务器的达梦数据库调优参考实践

基于鲲鹏服务器的达梦数据库调优参考实践

达梦数据库鲲鹏处理器数据库计算商业SMECE

发表于 2026/06/30

0

# 1 非商用声明

该文档提供的内容为参考实践，仅供用户参考使用，可参考实践文档构建自己的软件，按需进行安全、可靠性加固。

# 2 方案概述

## 2.1 背景

达梦数据库是使用率占比较高一款国产数据库，为了充分发挥达梦数据库在鲲鹏服务器上的性能，本参考实践基于鲲鹏服务器新型号对达梦数据库进行调优，并基于KAOT工具做了自动调优。

## 2.2 方案简介

本文以鲲鹏920新型号为计算底座，提供达梦数据库在鲲鹏平台上的性能调优参考指导和实践。

本参考实践部署方案是裸机部署达梦数据库，涉及到的软硬件信息如下表所示：

表1软硬件信息

| 类别 | 名称 |
| --- | ---|
| CPU型号 | Kunpeng 920 7270Z 64C@2.9GHz * 2 |
| 内存 | 16 * 32G DDR5 4800 MT/s |
| 硬盘 | 2 * NVME 硬盘 |
| 网络 | 25G网卡 |
| 操作系统 | 麒麟V10 SP3 |
| 数据库 | 达梦V8 |

## 2.3 调优方式实施

为兼顾调优效率与深度，本实践提供两种并行的实施方式供用户选择：

方式一：一键自动调优（推荐) 。为大幅简化调优流程，我们提供了自研的达梦数据库自动调优工具。该工具已将与鲲鹏硬件及达梦数据库相关的系统调优项、数据库配置文件调优项集成在工具里。用户只需运行该工具，即可实现一键式、全栈式的性能配置优化，快速提升系统及数据库性能，适用于快速部署与通用性能提升场景。

具体使用说明参考"通算一体机性能综合调优参考实践（鲲鹏自动调优工具(KAOT)简介及使用说明)"：工具说明链接 [了解详情](https://www.hikunpeng.com/zh/developer/techArticles/20251222-1)，也可参考数据库场景的调优指导：数据库场景使用链接 [了解详情](https://www.hikunpeng.com/zh/developer/techArticles/20260311-1)。

方式二：分步手动调优。 如果您希望对每一项优化进行深度理解和控制，或需要根据业务负载进行专项调优，则可以遵循本参考实践后续章节提供的手动调优指南。该指南将详细拆解每一项优化措施的原理、操作命令、参数配置及验证方法，适合测试人员、现场实施人员和技术支持人员深度优化使用。

无论选择哪种路径，其优化的核心维度均围绕以下方面展开，具体实践细节详见第3章。

# 3 调优参考实践

本章按照系统优化、数据库配置文件优化、BIOS优化、数据库对象设计优化（可选）的顺序展开。其中，系统侧优化（如绑核等）通常只需调整运行环境与启动参数；数据库配置文件优化（如事务合并提交、内存缓冲区配置等）需要重启达梦数据库；BIOS优化（如SMT超线程、CPU高性能模式、CPU预取等）则需要重启服务器；数据库对象设计优化（如聚簇索引、创表时不加外键、填充因子修改）需重新构建数据库表或索引。

表1 调优手段总览

| 序号 | 归类 | 调优手段 | 说明 |
| --- | --- | --- | ---|
| 1 | 系统优化 | 绑核与NUMA亲和 | 将进程与内存约束在同一NUMA或同一socket，减少跨NUMA访问内存；鲲鹏多NUMA场景下可优先验证。 |
| 2 | 网卡中断绑核 | 处理网卡中断的CPU核和网卡不在一个NUMA时，会触发跨NUMA访问内存，通过绑核可减少跨NUMA的内存访问所带来的额外开销，提升网络处理性能。 |  |
| 3 | 磁盘IO调度策略调整 | none调度策略是采用多队列块层调度器，它本质上不做任何排序，直接将I/O请求转发给设备驱动。 |  |
| 4 | 策略性抑制swap交换内存使用 | 抑制swap交换内存使用可以保障数据库的访问性能，避免把数据库的缓冲区内存淘汰到磁盘上。 |  |
| 5 | 数据库配置优化 | 事务合并提交优化 | 通过将多个独立事务的提交动作合并为一次磁盘写入，提升高并发下的写入吞吐。 |
| 6 | 内存缓冲区优化 | 调整达梦数据库内存缓存区参数，优化缓存命中率。 |  |
| 7 | 磁盘I/O优化 | 调整达梦数据库I/O与并发线程配置，提升数据读写性能与系统并发处理能力。 |  |
| 8 | 线程配置优化 | 调整达梦数据库工作线程与任务线程配置，提升系统并发处理能力与并行执行效率。 |  |
| 9 | BIOS优化 | SMT超线程 | 每个物理核分为两个逻辑核，提升性能。 |
| 10 | CPU高性能模式 | 设置CPU运行固定运行在标称频率，无动态调频，最大化CPU性能。 |  |
| 11 | CPU预取 | 使能硬件预取功能，提升内存访问效率。 |  |
| 12 | 数据库对象设计优化（可选） | 聚簇索引 | 将普通表改为聚簇索引表，通常需要重建整张表。 |
| 13 | 创表时不加外键 | 在创表的时候，不指定外键，实现数据更新的加速。 |  |
| 14 | 填充因子修改 | 创表时，适当减小填充因子到80%。 |  |

## 3.1 系统优化

### 3.1.1 绑核与NUMA亲和

1. 优化思路

NUMA架构下，处理器访问本地内存快于访问远端节点内存，跨NUMA会带来额外延迟与调度开销。鲲鹏服务器常见多socket/多NUMA，若达梦进程在不同NUMA间迁移，易出现跨访问内存、缓存失效与尾延迟抖动等现象。

亲和性（Affinity）是进程要在某个给定的CPU上尽量长时间地运行而不被迁移到其他处理器的倾向性。在多核运行的机器上，每个核本身自己会有缓存，缓存着进程使用的信息，而进程可能会被OS调度到其他核上，CPU Cache命中率就低了，当绑定核后，程序就会一直在指定的核跑，不会由操作系统调度到其他核上。这样能够大大提高CPU Cache的命中率，提高性能。

绑核的原则是优先将进程使用的CPU约束在同一NUMA；若所需核数超过单个NUMA，则尽量约束在同一颗CPU（同一socket）上。虚拟化场景下，还可结合平台的CPU独占、vNUMA/NUMA调度等能力，使vCPU与本地内存对齐。

2. 优化示例

步骤1查看NUMA拓扑与CPU编号

需先安装工具：

```
yum install numactl
```

执行以下命令查看NUMA拓扑：

```
numactl --hardware
```

如下所示代表NUMA node0对应的cpu编号是0-63，CPU型号是7270Z（开启超线程），故一个NUMA有64个逻辑核：

```
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
```

步骤2查看NUMA节点内存

实际应用场景需考虑业务应用需使用的内存，执行以下命令可查看不同NUMA节点的内存大小：

```
numactl --hardware
```

如下所示代表NUMA node0对应的内存大小是128461MB，其中空闲内存109524MB：

```
node 0 size: 128461 MB
node 0 free: 109524 MB
```

步骤3绑核

（1）裸机场景绑核

裸机场景可以使用numactl工具进行绑核，如下将达梦进程绑定到NUMA 3节点的CPU和内存上：

```
numactl --cpunodebind=3 --membind=3 /home/dmdba/dmdbms/bin/dmserver path=/home/dmdba/dm8/data/DAMENG/dm.ini
```

也可以绑定到具体的CPU核心，但要注意绑定的CPU核心和内存尽量在同一NUMA节点上，实际需要使用的CPU资源可视业务情况而定：

```
numactl --physcpubind=224-255 --membind=3 /home/dmdba/dmdbms/bin/dmserver path=/home/dmdba/dm8/data/DAMENG/dm.ini
```

（2）虚机场景绑核

以虚拟机绑核为例，我们将虚机绑定到16-23号cpu，内存使用8G，内存绑定到NUMA node0上，需在物理机上执行以下命令修改虚拟机配置：

```
virsh edit <vm_name>
```

配置示例如下：

```
<domain type='kvm'>
  <!-- ... 其他配置，如name,memory,vcpu等 ... -->
  <name>vm1</name>
  <memory unit='KiB'>8388608</memory>
  <currentMemory unit='KiB'>8388608</currentMemory>
  <vcpu placement='static'>8</vcpu>

  <!-- 1.CPU绑核 -->
  <cputune>
    <vcpupin vcpu='0' cpuset='16'/>
    <vcpupin vcpu='1' cpuset='17'/>
    <vcpupin vcpu='2' cpuset='18'/>
    <vcpupin vcpu='3' cpuset='19'/>
    <vcpupin vcpu='4' cpuset='20'/>
    <vcpupin vcpu='5' cpuset='21'/>
    <vcpupin vcpu='6' cpuset='22'/>
    <vcpupin vcpu='7' cpuset='23'/>
  </cputune>

  <!-- 2.内存绑定 -->
  <numatune>
    <memnode cellid='0' mode='strict' nodeset='0'/>
  </numatune>

  <!-- 3.CPU模式与虚拟NUMA拓扑 -->
  <cpu mode='host-passthrough' check='none'>
    <numa>
      <cell id='0' cpus='0-7' memory='8388608' unit='KiB'/>
    </numa>
  </cpu>

  <!-- ... 其他配置，如devices等 ... -->
</domain>
```

修改成功后，需执行以下命令重启虚拟机使得配置生效：

```
virsh shutdown <vm_name>
virsh start <vm_name>
```

其他场景的绑核指导可参考基于容器CPU绑核与虚机QoS控制的参考实践，保障关键业务性能和稳定性-技术干货-鲲鹏社区 [了解详情](https://www.hikunpeng.com/zh/developer/techArticles/20260312-1)。

### 3.1.2 网卡中断绑核

1. 优化思路

当网卡收到大量请求时，会产生大量的中断，通知内核有新的数据包，然后内核调用中断处理程序响应，把数据包从网卡拷贝到内存。当网卡只存在一个队列时，同一时间数据包的拷贝只能由某一个core处理，无法发挥多核优势，因此引入了网卡多队列机制，这样同一时间不同core可以分别从不同网卡队列中取数据包。

在网卡开启多队列时，操作系统通过Irqbalance服务来网卡队列中的网络数据包交由哪个CPU core处理，但是当处理中断的CPU core和网卡不在一个NUMA时，会触发跨NUMA访问内存。因此，我们可以将处理网卡中断的CPU core设置在网卡所在的NUMA上，从而减少跨NUMA的内存访问所带来的额外开销，提升网络处理性能。

图1 自动绑定：中断绑定随机，出现跨NUMA访问内存

图2 NUMA绑定：中断绑定到指定核，避免跨NUMA访问内存

2. 优化示例

步骤1停止irqbalance服务。

```
systemctl stop irqbalance.service
```

步骤2irqbalance服务开机自启（可选）。

```
systemctl disable irqbalance.service
```

步骤3查看irqbalance服务状态是否已，若状态为inactive即为。

```
systemctl status irqbalance.service
```

步骤4网卡中断绑核。

执行以下命令查看UP状态的网卡：

```
ip link show | grep "UP mode"
```

以网卡enp65s0f1为例，如下是网卡中断绑核流程：

执行以下命令查看中断数量：

```
ethtool -l enp65s0f1 | grep Combined
```

执行以下命令查看网卡所在NUMA，建议网卡中断绑定的CPU与网卡在同一个NUMA：

```
cat /sys/class/net/enp65s0f1/device/numa_node
```

执行以下命令查看NUMA节点对应的CPU：

```
numactl --hardware
```

执行以下命令查看的网卡的总线信息：

```
ethtool -i enp65s0f1 | grep bus-info
```

根据以下内容创建irq.sh脚本，并将脚本中第十行修改为上述命令查询到的网卡总线信息，然后执行以下命令进行网卡中断绑核：

```
sh irq.sh bind enp65s0f1 64 '160-191'
```

注：此处的enp65s0f1为网卡名称，64为中断数量，'160-191' 为要用于绑定网卡中断的CPU编号，与网卡在同一个NUMA。

```
#!/bin/bashs
# chkconfig: - 50 50
# description: auto irq

# 使用举例：
# sh irq.sh                               默认将192.168网卡队列深度设置为48并绑定到网卡所在cpu前48core
# sh irq.sh check eth1                    读取网卡绑核信息
# sh irq.sh bind enp65s0f1 64 '160-191'  完整参数，将eth1队列深度修改为64，并循环绑定到160-191'32个核上，其中cpu支持范围参数，如'1-3,6,7-9'

bus_info=""

#获取网卡所在cpu
function get_default_cpu(){
    eth_numa_node=`cat /sys/class/net/${eth}/device/numa_node`
    numa_nodes=`lscpu | grep node\(s | awk '{print $NF}'`
    cpus=`lscpu | grep CPU\(s | head -1 | awk '{print $NF}'`
    sockets=`lscpu | grep Socket\(s | awk '{print $NF}'`
    cpus_per_socket=`lscpu | grep Core\(s | awk '{print $NF}'`
    numa_per_socket=$((${numa_nodes} / ${sockets}))
    eth_socket=$((${eth_numa_node} / ${numa_per_socket}))

    first_cpu=$[$[$[${cpus_per_socket}*${eth_socket}]]]
    last_cpu=$[$[${cpus_per_socket}*$[${eth_socket}+1]]-1]
    cpurange="${first_cpu}-${last_cpu}"
}

#根据参数获取cpu队列
function get_cpu_list(){
    IFS_bak=$IFS
    IFS=','
    cpurange=($1)
    IFS=${IFS_bak}
    cpulist_arr=()
    n=0
    for i in ${cpurange[@]};do
        start=`echo $i | awk -F'-' '{print $1}'`
        stop=`echo $i | awk -F'-' '{print $NF}'`
        for x in `seq $start $stop`;do
            cpulist_arr[$n]=$x
            let n++
        done
    done
}

#中断绑核
function bind(){
    echo ${cnt}
    ethtool -L ${eth} combined ${cnt}
    #irq=`cat /proc/interrupts| grep ${eth} | awk -F ':' '{print $1}'`
    irq=`cat /proc/interrupts| grep "$bus_info" | awk -F ':' '{print $1}'`
    i=0
    for irq_i in $irq
    do
        if [ $i -ge ${#cpulist_arr[*]} ]; then
            i=0
        fi
        echo ${cpulist_arr[${i}]} "->" $irq_i
        echo ${cpulist_arr[${i}]}  > /proc/irq/$irq_i/smp_affinity_list
        let i++
    done
}

#读取网卡绑定cpu信息
function check(){
    ethtool -l $eth
    #irq=`cat /proc/interrupts | grep ${eth} | awk -F ':' '{print $1}'`
    irq=`cat /proc/interrupts| grep "$bus_info" | awk -F ':' '{print $1}'`
    for irq_i in $irq
    do
        cat /proc/irq/$irq_i/smp_affinity_list
    done
}

[[ $2 ]] && eth=$2 || eth=`ifconfig | grep -B 1 "192.168" | head -1 | awk -F":" '{print $1}'`
echo "$eth"
[[ $3 ]] && cnt=$3 || cnt=48
[[ $4 ]] && cpurange=$4 || get_default_cpu
get_cpu_list $cpurange
[[ $1 ]] && $1 || bind
```

### 3.1.3 磁盘IO调度策略调整

1. 优化思路

磁盘调度策略根据不同场景设置，在固态硬盘场景下，建议使用none，deadline次之。在固态硬盘场景下，空调度（none）通过消除请求重排与调度开销，充分利用SSD无寻道延迟的特性，显著降低延迟并节约CPU资源。

2. 优化示例

执行以下命令查询磁盘：

```
lsblk
```

以NVMe盘nvme0n1为例，执行以下命令修改：

```
echo none > /sys/block/nvme0n1/queue/scheduler
```

### 3.1.4 策略性抑制swap交换内存使用

1. 优化思路

调整内核参数，系统仍保留swap但几乎不使用（除非内存耗尽）。抑制swap交换内存使用可以保障数据库的访问性能，避免把数据库的缓冲区内存淘汰到磁盘上。 如果服务器内存比较小，内存不足时仍可少量使用swap缓冲，避免出现内存溢出的问题。

2. 优化示例

步骤1编辑sysctl配置文件：

```
sudo vim /etc/sysctl.conf
```

步骤2在文件末尾添加参数：

```
vm.swappiness=0
```

步骤3通过以下命令（或重启系统）使配置生效并持久化：

```
sudo sysctl -p
```

## 3.2 数据库配置优化

### 3.2.1 事务合并提交优化

1. 优化思路

事务合并提交是一种数据库I/O优化策略，它允许数据库在一次磁盘操作中提交多个事务，而不是为每一个事务单独执行一次磁盘I/O操作。

通过将多个独立事务的提交动作合并为一次磁盘写入，从而将原本高频、零碎的写入操作转化为低频、批量的大块写入，从而提升高并发下的写入吞吐。

表1事务合并提交配置参数

| 参数类别 | 参数名 | 含义 | 建议值 |
| --- | --- | --- | ---|
| 事务合并 | COMMIT_BATCH | 事务提交时合并刷盘的重做日志批次大小（单位为日志块个数） | 批次越大，每个事务需要等待的时间可能越长，导致事务提交的延迟增加，建议根据实际业务场景设置。 |
| COMMIT_BATCH_TIMEOUT | 事务提交时等待合并刷盘的最大超时时间（单位：毫秒） | 防止因并发过小导致事务提交的时间过长，建议根据实际业务场景设置。 |  |

2. 优化示例

修改达梦dm.ini配置文件（默认位于达梦数据库初始化路径下的DAMENG文件夹里），找到COMMIT_BATCH和COMMIT_BATCH_TIMEOUT字段并修改，如下所示：

```
COMMIT_BATCH                    = 32                    #Transaction commit redo log batch flush
COMMIT_BATCH_TIMEOUT   = 5                     #Transaction commit redo log batch flush wait time
```

修改完成后需重启数据库，才能使配置生效。

### 3.2.2 内存缓冲区优化

1. 优化思路

调整达梦数据库内存缓存区参数，优化缓存命中率。可以配置的参数有内存池参数、数据缓冲区参数和RECYCLE缓冲区参数。

表1内存缓冲区配置参数

| 参数类别 | 参数名 | 含义 | 建议值 |
| --- | --- | --- | ---|
| 内存池 | MAX_OS_MEMORY | 数据库可占用的最大操作系统内存百分比 | 建议设置为90，预留10%给操作系统。 |
| MEMORY_POOL | 共享内存池初始大小（单位：MB） | 建议设置为可用内存的25%，可适当增大初始值。 |  |
| MEMORY_TARGET | 共享内存池扩展后收缩回的目标大小（单位：MB） | 建议与MEMORY_POOL保持一致。 |  |
| 缓冲区 | BUFFER | 系统缓冲区大小（MB） | 建议设置为可用内存的50%，预留足够的系统缓冲区空间。 |
| BUFFER_POOLS | 缓冲区池数量 | 建议略高于可用CPU核数，且为质数。 |  |

2. 优化示例

以内存大小为512G、CPU核数为64个逻辑核为例，修改达梦dm.ini配置文件（默认位于达梦数据库初始化路径下的DAMENG文件夹里），找到对应的字段并修改，如下所示：

```
MAX_OS_MEMORY                   = 90                   #Maximum Percent Of OS Memory
MEMORY_POOL                        = 128000               #Memory Pool Size In Megabyte
MEMORY_TARGET                     = 128000               #Memory Share Pool Target Size In Megabyte
BUFFER                                     = 256000               #Initial System Buffer Size In Megabytes
BUFFER_POOLS                       = 67                   #number of buffer pools
```

修改完成后需重启数据库，才能使配置生效。

### 3.2.3 磁盘I/O优化

1. 优化思路

调整达梦数据库I/O与并发线程配置，提升数据读写性能与系统并发处理能力。通过合理设置DIRECT_IO和IO_THR_GROUPS参数，优化磁盘I/O通道利用率，实现与CPU资源的高效匹配。

表1I/O与并发线程配置参数

| 参数类别 | 参数名 | 含义 | 建议值 |
| --- | --- | --- | ---|
| IO | DIRECT_IO | 是否启用直接I/O（绕过操作系统缓存） | 建议设置为1，提升I/O性能。 |
| IO_THR_GROUPS | I/O线程组数量，控制并发I/O处理能力 | 建议与实际可用CPU核数保持一致。 |  |

2. 优化示例

以CPU核数为64个逻辑核为例，修改达梦dm.ini配置文件（默认位于达梦数据库初始化路径下的DAMENG文件夹里），找到DIRECT_IO和IO_THR_GROUPS字段并修改，如下所示：

```
DIRECT_IO                       = 1                     #Flag For Io Mode(Non-Windows Only), 0: Using File System Cache; 1: Without Using File System Cache
IO_THR_GROUPS            = 64                    #The Number Of Io Thread Groups(Non-Windows Only)
```

修改完成后需重启数据库，才能使配置生效。

### 3.2.4 线程配置优化

1. 优化思路

调整达梦数据库工作线程与任务线程配置，提升系统并发处理能力与并行执行效率。通过合理设置WORKER_THREADS和TASK_THREADS参数，实现与CPU资源的高效匹配，避免线程不足导致的请求排队或线程过多导致的资源争抢。

表1工作线程与任务线程配置参数

| 参数类别 | 参数名 | 含义 | 建议值 |
| --- | --- | --- | ---|
| thread | WORKER_THREADS | 工作线程数 | 建议与实际可用CPU核数保持一致。 |
| TASK_THREADS | 任务线程数 | 建议与实际可用CPU核数保持一致。 |  |

2. 优化示例

以CPU核数为64个逻辑核为例，修改达梦dm.ini配置文件（默认位于达梦数据库初始化路径下的DAMENG文件夹里），找到WORKER_THREADS和TASK_THREADS字段并修改，如下所示：

```

WORKER_THREADS                  = 64                    #Number Of Worker Threads
TASK_THREADS                         = 64                    #Number Of Task Threads
```

修改完成后需重启数据库，才能使配置生效。

## 3.3 BIOS优化

### 3.3.1 SMT超线程

1. 优化思路

开启SMT超线程，每个物理核分为两个逻辑核，提升整机性能。

注意：该调优项仅适用于鲲鹏920新型号服务器，对于其他鲲鹏服务器暂不支持该配置。

2. 优化示例

1）服务器重启，进入BIOS，依次选择“BIOS->Advanced->Power And Performance Configuration->CPU PM Control”。

2）设置“SMT2”选项为“Enabled”，按F10保存BIOS配置。

### 3.3.2 CPU高性能模式

1. 优化思路

CPU性能模式通常指将CPU频率固定在最高值，以最大化其性能的设置，开启CPU性能模式，无动态调频，固定在标称频率，可以提升事务处理性能。

说明：Power Policy会受Performance Profile联动配置的影响，即Performance Profile配置后，可能导致Power Policy发生变化，但支持手动修改，配置BIOS时注意保存前检查配置是否符合预期。

2. 优化示例

1）服务器重启，进入BIOS，依次选择“BIOS->Advanced->Power And Performance Configuration”。

2）设置“Power Policy”选项为“Performance”，按F10保存BIOS配置。

### 3.3.3 CPU预取

1. 优化思路

CPU将内存中的数据读到CPU的高速缓存时，会根据局部性原理，除了读取本次要访问的数据，还会预取本次数据的周边数据到Cache中，如果预取的数据是下次要访问的数据，那么性能会提升，如果预取的数据不是下次要访问的数据，那么会浪费内存带宽。

对于数据比较集中的场景，预取的命中率高，适合打开CPU预取，反之对于数据不集中的场景则需要CPU预取。

2. 优化示例

1）服务器重启，进入BIOS，依次选择“BIOS->Advanced->Power And Performance Configuration->CPU PM Control”。

2）设置CPU Prefetching为Enabled。

## 3.4 数据库对象设计优化（可选）

### 3.4.1 聚簇索引

1. 优化思路

聚簇索引是将表数据按照索引键的顺序物理存储在磁盘上的一种索引结构，它决定了表中行的物理排列次序。

聚簇索引会使得键值相邻的数据行在物理页上也相邻，从而将随机 I/O 转化为顺序 I/O，大幅提升检索性能。

基于此，优化思路是：在实际业务中，可以在创表的时候创建聚簇索引来提升性能。

2. 优化示例

说明：优化以BenchmarkSQL为例，可扩展到实际业务。

（1）进入BenchmarkSQL安装目录后，修改runDatabaseBuild.sh：

```
vim run/sql.common/indexCreates.sql
```

（2）修改后内容如下：

```
alter table bmsql_warehouse add constraint bmsql_warehouse_pkey
  cluster primary key (w_id);
alter table bmsql_district add constraint bmsql_district_pkey
  cluster primary key (d_w_id, d_id);
alter table bmsql_customer add constraint bmsql_customer_pkey
  cluster primary key (c_w_id, c_d_id, c_id);
create index bmsql_customer_idx1
  on  bmsql_customer (c_w_id, c_d_id, c_last, c_first);
alter table bmsql_oorder add constraint bmsql_oorder_pkey
  cluster primary key (o_w_id, o_d_id, o_id);
create unique index bmsql_oorder_idx1
  on  bmsql_oorder (o_w_id, o_d_id, o_carrier_id, o_id);
alter table bmsql_new_order add constraint bmsql_new_order_pkey
  cluster primary key (no_w_id, no_d_id, no_o_id);
alter table bmsql_order_line add constraint bmsql_order_line_pkey
  cluster primary key (ol_w_id, ol_d_id, ol_o_id, ol_number);
alter table bmsql_stock add constraint bmsql_stock_pkey
  cluster primary key (s_w_id, s_i_id);
alter table bmsql_item add constraint bmsql_item_pkey
  cluster primary key (i_id);
```

### 3.4.2 创表时不加外键

1. 优化思路

数据外键是一种在关系数据库中用来建立表之间关联的约束，它允许一个表（从表）中的一个或多个字段引用另一个表（主表）的主键字段。

数据外键会增加数据修改时的性能开销，需要额外校验，开发者会选择在应用层自己维护数据完整性，去除数据库外键的优势在于提升性能、简化开发、方便分布式和分库分表，可以有效降低CPU、I/O资源消耗。

基于此，优化思路是：在实际业务中，可以在创表的时候，不指定外键，实现数据更新的加速。

2. 优化示例

说明：优化以BenchmarkSQL为例，可扩展到实际业务。

（1）进入BenchmarkSQL安装目录后，修改runDatabaseBuild.sh：

```
vim run/runDatabaseBuild.sh
```

（2）修改后内容如下：

```
#!/bin/sh

if [ $# -lt 1 ] ; then
    echo "usage: $(basename $0) PROPS [OPT VAL [...]]" >&2
    exit 2
fi

PROPS="$1"
shift
if [ ! -f "${PROPS}" ] ; then
    echo "${PROPS}: no such file or directory" >&2
    exit 1
fi
DB="$(grep '^db=' $PROPS | sed -e 's/^db=//')"

BEFORE_LOAD="tableCreates"
AFTER_LOAD="indexCreates extraHistID buildFinish"

for step in ${BEFORE_LOAD} ; do
    ./runSQL.sh "${PROPS}" $step
done

./runLoader.sh "${PROPS}" $*

for step in ${AFTER_LOAD} ; do
    ./runSQL.sh "${PROPS}" $step
done
```

### 3.4.3 填充因子修改

1. 优化思路

数据库填充因子是一个介于0到100%的百分比值，它决定了创建或重建索引时，数据页被填充的程度，以便为将来的数据插入和更新预留空间。

在插入和更新操作频繁的场景下，减小填充因子，可以减少由于索引页分裂而导致的I/O开销。填充因子越小，每个数据页可以容纳的数据越少，从而有更多的空间来容纳新的数据，从而提升插入、更新以及写入性能。

基于此，优化思路是：创表时，适当减小FILLFACTOR到80。

2. 优化示例

说明：优化以BenchmarkSQL为例，可扩展到实际业务。

（1）进入BenchmarkSQL安装目录后，修改taleCreates.sql：

```
vim run/sql.common/taleCreates.sql
```

（2）修改后内容如下：

```
create table bmsql_config (
  cfg_name    varchar(30) primary key,
  cfg_value   varchar(50)
);

create table bmsql_warehouse (
  w_id        integer   not null,
  w_ytd       decimal(12,2),
  w_tax       decimal(4,4),
  w_name      varchar(10),
  w_street_1  varchar(20),
  w_street_2  varchar(20),
  w_city      varchar(20),
  w_state     char(2),
  w_zip       char(9)
)STORAGE(FILLFACTOR 80);

create table bmsql_district (
  d_w_id       integer       not null,
  d_id         integer       not null,
  d_ytd        decimal(12,2),
  d_tax        decimal(4,4),
  d_next_o_id  integer,
  d_name       varchar(10),
  d_street_1   varchar(20),
  d_street_2   varchar(20),
  d_city       varchar(20),
  d_state      char(2),
  d_zip        char(9)
)STORAGE(FILLFACTOR 80);

create table bmsql_customer (
  c_w_id         integer        not null,
  c_d_id         integer        not null,
  c_id           integer        not null,
  c_discount     decimal(4,4),
  c_credit       char(2),
  c_last         varchar(16),
  c_first        varchar(16),
  c_credit_lim   decimal(12,2),
  c_balance      decimal(12,2),
  c_ytd_payment  decimal(12,2),
  c_payment_cnt  integer,
  c_delivery_cnt integer,
  c_street_1     varchar(20),
  c_street_2     varchar(20),
  c_city         varchar(20),
  c_state        char(2),
  c_zip          char(9),
  c_phone        char(16),
  c_since        timestamp,
  c_middle       char(2),
  c_data         varchar(500)
)STORAGE(FILLFACTOR 80);

create sequence bmsql_hist_id_seq;

create table bmsql_history (
  hist_id  integer,
  h_c_id   integer,
  h_c_d_id integer,
  h_c_w_id integer,
  h_d_id   integer,
  h_w_id   integer,
  h_date   timestamp,
  h_amount decimal(6,2),
  h_data   varchar(24)
)STORAGE(FILLFACTOR 80);

create table bmsql_new_order (
  no_w_id  integer   not null,
  no_d_id  integer   not null,
  no_o_id  integer   not null
)STORAGE(FILLFACTOR 80);

create table bmsql_oorder (
  o_w_id       integer      not null,
  o_d_id       integer      not null,
  o_id         integer      not null,
  o_c_id       integer,
  o_carrier_id integer,
  o_ol_cnt     integer,
  o_all_local  integer,
  o_entry_d    timestamp
)STORAGE(FILLFACTOR 80);

create table bmsql_order_line (
  ol_w_id         integer   not null,
  ol_d_id         integer   not null,
  ol_o_id         integer   not null,
  ol_number       integer   not null,
  ol_i_id         integer   not null,
  ol_delivery_d   timestamp,
  ol_amount       decimal(6,2),
  ol_supply_w_id  integer,
  ol_quantity     integer,
  ol_dist_info    char(24)
)STORAGE(FILLFACTOR 80);

create table bmsql_item (
  i_id     integer      not null,
  i_name   varchar(24),
  i_price  decimal(5,2),
  i_data   varchar(50),
  i_im_id  integer
);

create table bmsql_stock (
  s_w_id       integer       not null,
  s_i_id       integer       not null,
  s_quantity   integer,
  s_ytd        integer,
  s_order_cnt  integer,
  s_remote_cnt integer,
  s_data       varchar(50),
  s_dist_01    char(24),
  s_dist_02    char(24),
  s_dist_03    char(24),
  s_dist_04    char(24),
  s_dist_05    char(24),
  s_dist_06    char(24),
  s_dist_07    char(24),
  s_dist_08    char(24),
  s_dist_09    char(24),
  s_dist_10    char(24)
)STORAGE(FILLFACTOR 80);
```

本页内容
