KaiwuDBKaiwuDB

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比

2025-05-19

原文链接:【KWDB创作者计划】实战指南:KWDB 2.2.0数据分析与性能调优深度对比_ITPUB博客

作者:顺华


作者:ShunWah

在运维管理领域,我拥有多年深厚的专业积累,兼具坚实的理论基础与广泛的实践经验。精通运维自动化流程,对于OceanBase、MySQL等多种数据库的部署与运维,具备从初始部署到后期维护的全链条管理能力。拥有OceanBase的OBCA和OBCP认证、OpenGauss社区认证结业证书,以及崖山DBCA、亚信AntDBCA、翰高 HDCA、GBase 8a |8c |8s、Galaxybase的GBCA、Neo4j的Graph Data Science Certification、NebulaGraph的NGCI & NGCP、东方通TongTech TCPE等多项权威认证。

在OceanBase & 墨天轮的技术征文大赛中,多次荣获一、二、三等奖。同时,在OpenGauss第五届、第六届、第七届技术征文大赛,TiDB社区专栏征文大赛,金仓数据库有奖征文活动,以及YashanDB「产品体验官」征文等活动中,我也屡获殊荣。此外,我还活跃于墨天轮、CSDN、ITPUB等技术平台,经常发布原创技术文章,并多次被首页推荐。

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图1)

引言

浪潮数据库KWDB2.2.0:数据分析与性能调优深度对比实战指南

随着开源社区的蓬勃发展,越来越多的优秀项目涌现出来,为开发者们提供了丰富的工具和资源。其中,KWDB 作为一款面向AIoT场景的分布式多模数据库,自2024年开源以来,凭借其强大的功能和灵活的架构,吸引了众多开发者的关注。【KWDB创作者计划】更是为KWDB带来了全新的玩法和可能性。
在本文中,我们将详细介绍如何使用KWDB 2.2.0,并通过一系列实命令,展示如何解锁KWDB的新玩法。

KWDB 2.2.0的新功能概览

KWDB 2.2.0版本带来了许多新功能和改进,以下是其中一些亮点:
多模数据支持增强
支持更多数据类型,包括JSON、图像、视频和音频,适用于复杂的AIoT场景。
分布式性能优化
提高了分布式环境下的数据同步和查询性能,适合大规模部署。
新增API接口
提供了更多便捷的API,简化了数据库作流程。
用户界面改进
新增了一个更直观的控制台界面,方便用户管理数据库。

一、安装 KWDB 2.2.0

首先,我们需要安装KWDB 2.2.0版本。以下是安装步骤:

1. 环境准备

确保你的开发环境满足KWDB的运行要求。KWDB支持多种作系统,包括Linux、macOS和Windows。
本文以 x86 架构的 CentOS Linux 7.4 镜像作为环境介绍如何使用 docker容器化部署 KWDB2.2.0 数据库。

[root@worker3 kaiwudb]# cat /etc/redhat-release 
CentOS Linux release 7.9.2009 (Core)
[root@worker3 kaiwudb]# free -h
              total        used        free      shared  buff/cache   available
Mem:            27G        1.8G         10G        313M         15G         24G
Swap:          8.0G          0B        8.0G
[root@worker3 kaiwudb]#

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图2)

2. 安装命令

由于我已提前完成安装,这里不再重复演示。如需详细安装步骤,请参考我的上一篇文章:
【KWDB创作者计划】容器赋能KaiwuDB:探索浪潮数据库KWDB2.2.0 实战指南

3. 验证安装

安装完成后,在终端中运行以下命令验证安装是否成功:

[root@worker3 kwdb]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                              NAMES
40305e626095        kwdb/kwdb:2.2.0     "/bin/bash -c '/kaiw…"   9 days ago          Up 9 days           0.0.0.0:8080->8080/tcp, 0.0.0.0:26257->26257/tcp   kaiwudb-experience
[root@worker3 kwdb]# docker exec -it kaiwudb-experience bash
root@kaiwudb-experience:/kaiwudb/bin# ./kwbase sql --insecure --host=127.0.0.1
#
# Welcome to the KWDB SQL shell.
# All statements must be terminated by a semicolon.
# To exit, type: \q.
#
# Server version: KaiwuDB 2.2.0 (x86_64-linux-gnu, built 2025/03/31 07:20:02, go1.16.15, gcc 11.4.0) (same version as client)
# Cluster ID: b565096e-c243-4399-8aa0-6ec3ea6b77a5
#
# Enter \? for a brief introduction.
#
root@127.0.0.1:26257/defaultdb>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图3)

首先,确保你已经成功部署了 KWDB 2.2.0。或者你可以从 Gitee 上下载最新版的 KWDB 2.2.0 安装包,并按照官方文档进行安装和配置。安装完成后,启动 KWDB 服务,并确保其正常运行。

、KWDB 联合查询数据分析

现在,我们将用 KWDB 进行创建数据库和表。


1.创建数据库

root@127.0.0.1:26257/example_db> CREATE DATABASE testdb;CREATE DATABASETime: 6.130957ms
root@127.0.0.1:26257/example_db>


切换到新创建的数据库

root@127.0.0.1:26257/example_db> USE testdb;SETTime: 1.416482ms
root@127.0.0.1:26257/testdb>


2.创建数据库表

2.1 创建时序表,用于存储设备指标数据
root@127.0.0.1:26257/testdb> CREATE TABLE device_metrics (
    temperature FLOAT,
    humidity FLOAT,
                          ->     time TIMESTAMP NOT NULL,
                          ->     device_id STRING NOT NULL,
    PRIMARY KEY (time, device_id)
);
                          ->     temperature FLOAT,
                          ->     humidity FLOAT,
                          ->     PRIMARY KEY (time, device_id)
                          -> );CREATE TABLETime: 5.415833ms
root@127.0.0.1:26257/testdb>


2.2 创建用户信息表,用于存储用户基本信息
root@127.0.0.1:26257/testdb> CREATE TABLE user_info (
    username STRING NOT NULL,
    email STRING,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
                          ->     user_id INT PRIMARY KEY,
                          ->     username STRING NOT NULL,
                          ->     email STRING,
                          ->     created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                          -> );CREATE TABLETime: 5.662591ms
root@127.0.0.1:26257/testdb>


3. 插入测试数据

创建好数据库和表后,我们插入一些测试数据,以便后续进行查询和优化操作。

root@127.0.0.1:26257/testdb> insert INTO device_metrics VALUES
    ('2021-09-15 12:30:00', 'device2', 26.1, 44.8),
    ('2022-03-20 15:45:00', 'device3', 27.0, 43.5),
    ('2023-07-10 08:15:00', 'device1', 25.7, 44.9),
    ('2024-01-25 11:00:00', 'device2', 26.3, 44.6),
    ('2024-08-05 14:20:00', 'device3', 27.2, 43.3),
                          ->     ('2020-06-01 10:00:00', 'device1', 25.3, 45.2),
    ('2025-02-14 09:40:00', 'device1', 25.9, 44.7),
    ('2025-05-30 16:50:00', 'device2', 26.5, 44.4),
    ('2025-09-12 13:10:00', 'device3', 27.4, 43.1),
    ('2025-12-25 18:35:00', 'device1', 26.0, 44.0);
                          ->     ('2021-09-15 12:30:00', 'device2', 26.1, 44.8),
                          ->     ('2022-03-20 15:45:00', 'device3', 27.0, 43.5),
                          ->     ('2023-07-10 08:15:00', 'device1', 25.7, 44.9),
                          ->     ('2024-01-25 11:00:00', 'device2', 26.3, 44.6),
                          ->     ('2024-08-05 14:20:00', 'device3', 27.2, 43.3),
                          ->     ('2025-02-14 09:40:00', 'device1', 25.9, 44.7),
                          ->     ('2025-05-30 16:50:00', 'device2', 26.5, 44.4),
                          ->     ('2025-09-12 13:10:00', 'device3', 27.4, 43.1),
                          ->     ('2025-12-25 18:35:00', 'device1', 26.0, 44.0);insert 10Time: 1.498235ms
root@127.0.0.1:26257/testdb>


4.查看全部数据

root@127.0.0.1:26257/testdb> select * FROM device_metrics;
            time            | device_id | temperature | humidity----------------------------+-----------+-------------+-----------
  2020-06-01 10:00:00+00:00 | device1   |        25.3 |     45.2
  2021-09-15 12:30:00+00:00 | device2   |        26.1 |     44.8
  2022-03-20 15:45:00+00:00 | device3   |          27 |     43.5
  2023-07-10 08:15:00+00:00 | device1   |        25.7 |     44.9
  2024-01-25 11:00:00+00:00 | device2   |        26.3 |     44.6
  2024-08-05 14:20:00+00:00 | device3   |        27.2 |     43.3
  2025-02-14 09:40:00+00:00 | device1   |        25.9 |     44.7
  2025-05-30 16:50:00+00:00 | device2   |        26.5 |     44.4
  2025-09-12 13:10:00+00:00 | device3   |        27.4 |     43.1
  2025-12-25 18:35:00+00:00 | device1   |          26 |       44
(10 rows)
Time: 1.628286ms
root@127.0.0.1:26257/testdb>


5.插入用户信息数据

root@127.0.0.1:26257/testdb> 
root@127.0.0.1:26257/testdb> insert INTO user_info (user_id, username, email) VALUES
    (1, 'alice', 'alice@example.com'),
                          ->     (1, 'alice', 'alice@example.com'),
    (2, 'bob', 'bob@example.com'),
    (3, 'charlie', 'charlie@example.com');                          ->     (2, 'bob', 'bob@example.com'),
                          ->     (3, 'charlie', 'charlie@example.com');insert 3Time: 1.800617ms
root@127.0.0.1:26257/testdb>


6.数据查询与优化

创建好数据库和表,并插入测试数据后,我们可以通过 MCP Server 执行查询作,并尝试对查询进行优化。


6.1 简单查询设备指标数据
root@127.0.0.1:26257/testdb> select * FROM device_metrics WHERE device_id = 'device1';
            time            | device_id | temperature | humidity----------------------------+-----------+-------------+-----------
  2020-06-01 10:00:00+00:00 | device1   |        25.3 |     45.2
  2023-07-10 08:15:00+00:00 | device1   |        25.7 |     44.9
  2025-02-14 09:40:00+00:00 | device1   |        25.9 |     44.7
  2025-12-25 18:35:00+00:00 | device1   |          26 |       44
(4 rows)
Time: 2.05378ms
root@127.0.0.1:26257/testdb>


6.2 时间范围查询设备指标数据
root@127.0.0.1:26257/testdb> select * FROM device_metrics WHERE time > '2025-01-01 09:00:00' AND time < '2025-12-30 10:15:00';
            time            | device_id | temperature | humidity
----------------------------+-----------+-------------+-----------
  2025-02-14 09:40:00+00:00 | device1   |        25.9 |     44.7
  2025-05-30 16:50:00+00:00 | device2   |        26.5 |     44.4
  2025-09-12 13:10:00+00:00 | device3   |        27.4 |     43.1
  2025-12-25 18:35:00+00:00 | device1   |          26 |       44
(4 rows)
Time: 1.635945ms
root@127.0.0.1:26257/testdb>


6.3 聚合查询设备平均温度
root@127.0.0.1:26257/testdb> select device_id, AVG(temperature) AS avg_temp
WHERE time > NOW() - INTERVAL '1 hour'GROUP BY device_id;
                          -> FROM device_metrics
                          -> WHERE time > NOW() - INTERVAL '1 hour'
                          -> GROUP BY device_id;
  device_id | avg_temp
------------+-----------
  device1   |       26
  device2   |     26.5
  device3   |     27.4
(3 rows)
Time: 2.286525ms
root@127.0.0.1:26257/testdb>


6.4 查询用户信息
root@127.0.0.1:26257/testdb> select * FROM user_info;
  user_id | username |        email        |            created_at
----------+----------+---------------------+-----------------------------------
        1 | alice    | alice@example.com   | 2025-04-18 06:51:45.654229+00:00
        2 | bob      | bob@example.com     | 2025-04-18 06:51:45.654229+00:00
        3 | charlie  | charlie@example.com | 2025-04-18 06:51:45.654229+00:00
(3 rows)
Time: 1.465467ms
root@127.0.0.1:26257/testdb>


6.5 优化查询:为 device_metrics 表的 device_id 列创建索引
root@127.0.0.1:26257/testdb> CREATE INDEX idx_device_id ON device_metrics (device_id);
CREATE INDEX
Time: 173.51779ms
root@127.0.0.1:26257/testdb>


6.6 再次执行简单查询,观察性能变化
root@127.0.0.1:26257/testdb> select * FROM device_metrics WHERE device_id = 'device1';
            time            | device_id | temperature | humidity
----------------------------+-----------+-------------+-----------
  2020-06-01 10:00:00+00:00 | device1   |        25.3 |     45.2
  2023-07-10 08:15:00+00:00 | device1   |        25.7 |     44.9
  2025-02-14 09:40:00+00:00 | device1   |        25.9 |     44.7
  2025-12-25 18:35:00+00:00 | device1   |          26 |       44
(4 rows)
Time: 1.805047ms
root@127.0.0.1:26257/testdb>


在查询过程中,我们可能会发现某些查询的性能不够理想。这时,我们可以尝试对 KWDB 进行优化,比如调整索引、分区策略等。在上述示例中,我们为   表的   列创建了索引,以加速基于   的查询操作。device_metricsdevice_iddevice_id


7. 高级查询与数据分析

除了基本的查询作外,我们还可以利用 KWDB 进行更高级的数据分析和处理。在实际业务场景中,数据库系统通常需要处理复杂的关联查询和数据分析任务。例如:
用户(user_info 表)与设备(device_metrics 表)之间的关联。每个用户可能绑定一个或多个设备,并且需要根据设备的最新数据进行统计和分析。本案例通过以下步骤展示了如何利用 KWDB 进行高级查询和数据分析:

创建用户设备关联表(user_device_mapping),用于存储用户与设备的绑定关系。
插入示例数据,模拟用户与设备的实际关联。
使用多表联合查询(JOIN)获取每个用户的最新设备数据,并按用户名排序。


7.1 首先,创建用户设备关联表
root@127.0.0.1:26257/testdb> CREATE TABLE user_device_mapping (
    user_id INT,
    device_id STRING,
    PRIMARY KEY (user_id)
);
                          ->     user_id INT,
                          ->     device_id STRING,
                          ->     PRIMARY KEY (user_id)
                          -> );
CREATE TABLE
Time: 6.371418ms
root@127.0.0.1:26257/testdb>

目的:建立用户与设备的映射关系。
字段说明:
user_id:用户 ID,主键,确保每个用户只能绑定一个设备。
device_id:设备 ID,表示用户绑定的设备。


7.2 插入一些示例数据
root@127.0.0.1:26257/testdb> insert INTO user_device_mapping (user_id, device_id) VALUES
    (3, 'device3');
                          ->     (1, 'device1'),
                          ->     (2, 'device2'),
                          ->     (3, 'device3');
insert 3
Time: 1.261248ms
root@127.0.0.1:26257/testdb>

数据解释:
用户 1 绑定设备 device1。
用户 2 绑定设备 device2。
用户 3 绑定设备 device3。


7.3 然后,进行复杂关联查询

以下是核心查询语句,用于获取每个用户的最新设备数据:
查询逻辑解析
用户信息表(user_info)包含用户的基本信息,如用户名(username)。通过 user_id 与用户设备关联表(user_device_mapping)连接。
用户设备关联表(user_device_mapping)存储用户与设备的绑定关系。通过 device_id 与设备指标表(device_metrics)连接。
设备指标表(device_metrics)存储设备的时间序列数据,如温度(temperature)、湿度(humidity)等。需要提取每个设备的最新数据。
子查询(latest)从 device_metrics 表中提取每个设备的最新时间戳(MAX(time))。通过 GROUP BY device_id 确保每个设备只返回一条记录。
最终联合查询将所有表连接起来,筛选出每个设备的最新数据。
按用户名(u.username)排序,便于阅读和分析。

root@127.0.0.1:26257/testdb> select
    dm.humidityFROM
    user_info uJOIN user_device_mapping udm ON u.user_id = udm.user_idJOIN device_metrics dm ON udm.device_id = dm.device_idJOIN (    select
        device_id,        MAX(time) AS m                          -> ax_time
    u.username,    GROUP BY
        device_id
) latest ON dm.device_id = latest.device_id AND dm.time = latest.max_timeORDER BY
    u.username;
                          ->     dm.time,
                          ->     dm.temperature,
                          ->     dm.humidity
                          -> FROM
                          ->     user_info u
                          -> JOIN user_device_mapping udm ON u.user_id = udm.user_id
                          -> JOIN device_metrics dm ON udm.device_id = dm.device_id
                          -> JOIN (
                          ->     select
                          ->         device_id,
                          ->         MAX(time) AS max_time
                          ->     FROM
                          ->         device_metrics
                          ->     GROUP BY
                          ->         device_id
                          -> ) latest ON dm.device_id = latest.device_id AND dm.time = latest.max_time
                          -> ORDER BY
                          ->     u.username;
  username |           time            | temperature | humidity-----------+---------------------------+-------------+-----------
  alice    | 2025-12-25 18:35:00+00:00 |          26 |       44
  bob      | 2025-05-30 16:50:00+00:00 |        26.5 |     44.4
  charlie  | 2025-09-12 13:10:00+00:00 |        27.4 |     43.1
(3 rows)
Time: 3.899709ms
root@127.0.0.1:26257/testdb>


结果解释:
用户 alice 的设备 device3 在 2025-12-25 18:35:00 的最新数据显示温度为 26℃,湿度为 44%。
用户 bob 的设备 device1 在 2025-05-30 16:50:00 的最新数据显示温度为 26.5℃,湿度为 44.4%。
用户 charlie 的设备 device2 在 2025-09-12 13:10:00 的最新数据显示温度为 27.4℃,湿度为 43.1%。

多表联合查询(JOIN)
通过 JOIN 将多个表(user_info、user_device_mapping、device_metrics)连接起来,实现复杂的数据关联。使用子查询提取每个设备的最新时间戳,确保查询结果的准确性。聚合函数(GROUP BY 和 MAX)使用 GROUP BY 和 MAX 提取每个设备的最新数据。这是时间序列数据分析中的常见模式。排序(ORDER BY)按用户名排序,使结果更具可读性。

三、KWDB 优化和性能对比


1. 连接到 KWDB

启动 KWDB 的 SQL Shell,进入交互式命令行。

root@kaiwudb-experience:/kaiwudb/bin# ./kwbase sql --insecure --host=127.0.0.1## Welcome to the KWDB SQL shell.# All statements must be terminated by a semicolon.# To exit, type: \q.## Server version: KaiwuDB 2.2.0 (x86_64-linux-gnu, built 2025/03/31 07:20:02, go1.16.15, gcc 11.4.0) (same version as client)# Cluster ID: b565096e-c243-4399-8aa0-6ec3ea6b77a5## Enter \? for a brief introduction.#root@127.0.0.1:26257/defaultdb>


2. 创建数据库


2.1 创建一个新的数据库 example_db
root@127.0.0.1:26257/defaultdb> CREATE DATABASE example_db;CREATE DATABASETime: 5.737184ms
root@127.0.0.1:26257/defaultdb>


2.2 使用 USE example_db; 切换到新创建的数据库。
root@127.0.0.1:26257/defaultdb> USE example_db;SETTime: 682.48µs
root@127.0.0.1:26257/example_db>


3. 创建用户信息表

创建一个用户信息表,用于存储用户的基本信息。
字段说明:
id:主键,自增序列(SERIAL 类型)。
username:用户名,长度限制为 50 个字符,不能为空。
email:邮箱地址,长度限制为 100 字符。
age:用户年龄,整数类型。
created_at:记录创建时间,默认值为当前时间戳。

root@127.0.0.1:26257/example_db> CREATE TABLE users (
    age INT,
                              ->     id SERIAL PRIMARY KEY,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
                              ->     username VARCHAR(50) NOT NULL,
                              ->     email VARCHAR(100),
                              ->     age INT,
                              ->     created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                              -> );CREATE TABLETime: 6.163336ms
root@127.0.0.1:26257/example_db>


4.新插入数据

批量插入 9001 条用户数据。
关键点:
generate_series(1000, 10000)
生成一系列整数(从 1000 到 10000),用作临时 ID。
动态生成用户名和邮箱
'user_' ||id::文本 ||' ' ||(floor(random() * 1000))::TEXT:构造随机用户名。
'用户
' ||id::文本 ||'@test.com':构造唯一的邮箱地址。
随机生成年龄
floor(25 + random() * 20)::int:生成范围在 25 到 44 之间的随机整数。
批量插入
使用 insert INTO ...select 语法高效地插入大量数据。

root@127.0.0.1:26257/example_db> insert INTO users (username, email, age)    'user_' || id::TEXT || '@test.com',    floor(25 + random() * 20)::intFROM generate_series(1000, 10000) AS id;
                              -> select 
                              ->     'user_' || id::TEXT || '_' || (floor(random() * 1000))::TEXT,
                              ->     'user_' || id::TEXT || '@test.com',
                              ->     floor(25 + random() * 20)::int
                              -> FROM generate_series(1000, 10000) AS id;insert 9001Time: 257.076009ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图4)


5.查询验证数据

查询表中的前 50 条记录,验证数据插入是否成功。

root@127.0.0.1:26257/example_db> select * FROM users LIMIT 50;
          id          |     username     |         email         | age |            created_at
----------------------+------------------+-----------------------+-----+-----------------------------------
  1064580450243248129 | john_doe         | john@example.com      |  28 | 2025-04-18 05:36:10.606017+00:00
  1064580450243346433 | jane_doe         | jane@example.com      |  32 | 2025-04-18 05:36:10.606017+00:00
  1064580450243379201 | alice_smith      | alice@example.com     |  25 | 2025-04-18 05:36:10.606017+00:00
  1064580450243411969 | bob_jones        | bob@example.com       |  40 | 2025-04-18 05:36:10.606017+00:00
  1064580450243444737 | charlie_brown    | charlie@example.com   |  35 | 2025-04-18 05:36:10.606017+00:00
  1065191668815233025 | john_doe_1       | john1@example.com     |  28 | 2025-04-20 09:24:59.710609+00:00
  1065191668815396865 | jane_doe_2       | jane2@example.com     |  32 | 2025-04-20 09:24:59.710609+00:00
  1065191668815462401 | alice_smith_3    | alice3@example.com    |  25 | 2025-04-20 09:24:59.710609+00:00
  1065191668815527937 | bob_jones_4      | bob4@example.com      |  40 | 2025-04-20 09:24:59.710609+00:00
  1065191668815560705 | charlie_brown_5  | charlie5@example.com  |  35 | 2025-04-20 09:24:59.710609+00:00
  1065191668815593473 | john_doe_6       | john6@example.com     |  29 | 2025-04-20 09:24:59.710609+00:00
  1065191668815659009 | jane_doe_7       | jane7@example.com     |  33 | 2025-04-20 09:24:59.710609+00:00
  1065191668815724545 | alice_smith_8    | alice8@example.com    |  26 | 2025-04-20 09:24:59.710609+00:00
  1065191668815757313 | bob_jones_9      | bob9@example.com      |  41 | 2025-04-20 09:24:59.710609+00:00
  1065191668815790081 | charlie_brown_10 | charlie10@example.com |  36 | 2025-04-20 09:24:59.710609+00:00
  1065191668815822849 | john_doe_11      | john11@example.com    |  30 | 2025-04-20 09:24:59.710609+00:00
  1065191668815888385 | jane_doe_12      | jane12@example.com    |  34 | 2025-04-20 09:24:59.710609+00:00
  1065191668815986689 | alice_smith_13   | alice13@example.com   |  27 | 2025-04-20 09:24:59.710609+00:00
  1065191668816052225 | bob_jones_14     | bob14@example.com     |  42 | 2025-04-20 09:24:59.710609+00:00
  1065191668816084993 | charlie_brown_15 | charlie15@example.com |  37 | 2025-04-20 09:24:59.710609+00:00
  1065191668816117761 | john_doe_16      | john16@example.com    |  28 | 2025-04-20 09:24:59.710609+00:00
  1065191668816183297 | jane_doe_17      | jane17@example.com    |  32 | 2025-04-20 09:24:59.710609+00:00
  1065191668816216065 | alice_smith_18   | alice18@example.com   |  25 | 2025-04-20 09:24:59.710609+00:00
  1065191668816248833 | bob_jones_19     | bob19@example.com     |  40 | 2025-04-20 09:24:59.710609+00:00
  1065191668816314369 | charlie_brown_20 | charlie20@example.com |  35 | 2025-04-20 09:24:59.710609+00:00
  1065191668816347137 | john_doe_21      | john21@example.com    |  29 | 2025-04-20 09:24:59.710609+00:00
  1065191668816379905 | jane_doe_22      | jane22@example.com    |  33 | 2025-04-20 09:24:59.710609+00:00
  1065191668816445441 | alice_smith_23   | alice23@example.com   |  26 | 2025-04-20 09:24:59.710609+00:00
  1065191668816478209 | bob_jones_24     | bob24@example.com     |  41 | 2025-04-20 09:24:59.710609+00:00
  1065191668816510977 | charlie_brown_25 | charlie25@example.com |  36 | 2025-04-20 09:24:59.710609+00:00
  1065191668816576513 | john_doe_26      | john26@example.com    |  30 | 2025-04-20 09:24:59.710609+00:00
  1065191668816609281 | jane_doe_27      | jane27@example.com    |  34 | 2025-04-20 09:24:59.710609+00:00
  1065191668816674817 | alice_smith_28   | alice28@example.com   |  27 | 2025-04-20 09:24:59.710609+00:00
  1065191668816707585 | bob_jones_29     | bob29@example.com     |  42 | 2025-04-20 09:24:59.710609+00:00
  1065191668816740353 | charlie_brown_30 | charlie30@example.com |  37 | 2025-04-20 09:24:59.710609+00:00
  1065191668816773121 | john_doe_31      | john31@example.com    |  28 | 2025-04-20 09:24:59.710609+00:00
  1065191668816838657 | jane_doe_32      | jane32@example.com    |  32 | 2025-04-20 09:24:59.710609+00:00
  1065191668816871425 | alice_smith_33   | alice33@example.com   |  25 | 2025-04-20 09:24:59.710609+00:00
  1065191668816904193 | bob_jones_34     | bob34@example.com     |  40 | 2025-04-20 09:24:59.710609+00:00
  1065191668816936961 | charlie_brown_35 | charlie35@example.com |  35 | 2025-04-20 09:24:59.710609+00:00
  1065191668816969729 | john_doe_36      | john36@example.com    |  29 | 2025-04-20 09:24:59.710609+00:00
  1065191668817002497 | jane_doe_37      | jane37@example.com    |  33 | 2025-04-20 09:24:59.710609+00:00
  1065191668817068033 | alice_smith_38   | alice38@example.com   |  26 | 2025-04-20 09:24:59.710609+00:00
  1065191668817100801 | bob_jones_39     | bob39@example.com     |  41 | 2025-04-20 09:24:59.710609+00:00
  1065191668817133569 | charlie_brown_40 | charlie40@example.com |  36 | 2025-04-20 09:24:59.710609+00:00
  1065191668817166337 | john_doe_41      | john41@example.com    |  30 | 2025-04-20 09:24:59.710609+00:00
  1065191668817199105 | jane_doe_42      | jane42@example.com    |  34 | 2025-04-20 09:24:59.710609+00:00
  1065191668817264641 | alice_smith_43   | alice43@example.com   |  27 | 2025-04-20 09:24:59.710609+00:00
  1065191668817297409 | bob_jones_44     | bob44@example.com     |  42 | 2025-04-20 09:24:59.710609+00:00
  1065191668817330177 | charlie_brown_45 | charlie45@example.com |  37 | 2025-04-20 09:24:59.710609+00:00
(50 rows)
Time: 3.046443ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图5)

查询结果:
显示了每条记录的 id、username、email、age 和 created_at 字段。
数据按插入顺序排列,created_at 字段显示了记录的创建时间。


6.数据库优化

在数据库系统中,查询效率是影响性能的关键因素。通过索引优化和统计信息分析,可以显著提升查询速度,尤其是在处理大规模数据时。本案例展示了如何对用户表(users)进行索引优化、统计信息分析以及执行计划查看,以验证优化效果。
为了提高查询效率,我们可以对表进行索引优化。创建索引会增加写入(insert/update/delete)的开销,但能大幅提高读取(select)性能。


6.0 为用户名字段添加索引

为 username 和 age 字段创建索引,加速基于这些字段的查询。
username:通常用于精确匹配查询(如 WHERE username = 'john_doe')。

root@127.0.0.1:26257/example_db> 
root@127.0.0.1:26257/example_db> CREATE INDEX idx_users_username ON users(username);
CREATE INDEX
Time: 167.695363ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图6)


6.1 为年龄字段添加索引

age:常用于范围查询(如 WHERE age > 30)

root@127.0.0.1:26257/example_db> CREATE INDEX idx_users_age ON users(age);
CREATE INDEX
Time: 181.634007ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图7)


6.2 分析表结构以获取统计信息

查看表的统计信息,帮助数据库优化器选择最佳查询计划

root@127.0.0.1:26257/example_db> SHOW STATISTICS FOR TABLE users;
  statistics_name | column_names |             created              | row_count | distinct_count | null_count |    histogram_id
------------------+--------------+----------------------------------+-----------+----------------+------------+----------------------
  __auto__        | {id}         | 2025-04-20 12:43:48.429957+00:00 |      9056 |           9016 |          0 | 1065230756859936769
  __auto__        | {username}   | 2025-04-20 12:43:48.429957+00:00 |      9056 |           9045 |          0 | 1065230756879499265
  __auto__        | {age}        | 2025-04-20 12:43:48.429957+00:00 |      9056 |             20 |          0 | 1065230756894179329
  __auto__        | {email}      | 2025-04-20 12:43:48.429957+00:00 |      9056 |           9033 |          0 |                NULL
  __auto__        | {created_at} | 2025-04-20 12:43:48.429957+00:00 |      9056 |              3 |          0 |                NULL
  __auto__        | {id}         | 2025-04-20 13:15:48.569988+00:00 |      9056 |           9016 |          0 | 1065237048780324865
  __auto__        | {username}   | 2025-04-20 13:15:48.569988+00:00 |      9056 |           9045 |          0 | 1065237048801624065
  __auto__        | {email}      | 2025-04-20 13:15:48.569988+00:00 |      9056 |           9033 |          0 |                NULL
  __auto__        | {age}        | 2025-04-20 13:15:48.569988+00:00 |      9056 |             20 |          0 |                NULL
  __auto__        | {created_at} | 2025-04-20 13:15:48.569988+00:00 |      9056 |              3 |          0 |                NULL
  __auto__        | {created_at} | 2025-04-20 13:17:48.654422+00:00 |      9056 |              3 |          0 |                NULL
  __auto__        | {username}   | 2025-04-20 13:17:48.654422+00:00 |      9056 |           9045 |          0 |                NULL
  __auto__        | {id}         | 2025-04-20 13:17:48.654422+00:00 |      9056 |           9016 |          0 | 1065237442265612289
  __auto__        | {age}        | 2025-04-20 13:17:48.654422+00:00 |      9056 |             20 |          0 |                NULL
  __auto__        | {email}      | 2025-04-20 13:17:48.654422+00:00 |      9056 |           9033 |          0 |                NULL
  __auto__        | {id}         | 2025-04-20 13:18:48.747856+00:00 |      9056 |           9016 |          0 | 1065237639201554433
  __auto__        | {username}   | 2025-04-20 13:18:48.747856+00:00 |      9056 |           9045 |          0 | 1065237639226916865
  __auto__        | {email}      | 2025-04-20 13:18:48.747856+00:00 |      9056 |           9033 |          0 |                NULL
  __auto__        | {age}        | 2025-04-20 13:18:48.747856+00:00 |      9056 |             20 |          0 |                NULL
  __auto__        | {created_at} | 2025-04-20 13:18:48.747856+00:00 |      9056 |              3 |          0 |                NULL
  __auto__        | {id}         | 2025-04-20 13:20:48.858779+00:00 |      9056 |           9016 |          0 | 1065238032765943809
  __auto__        | {username}   | 2025-04-20 13:20:48.858779+00:00 |      9056 |           9045 |          0 | 1065238032789766145
  __auto__        | {age}        | 2025-04-20 13:20:48.858779+00:00 |      9056 |             20 |          0 | 1065238032805953537
  __auto__        | {email}      | 2025-04-20 13:20:48.858779+00:00 |      9056 |           9033 |          0 |                NULL
  __auto__        | {created_at} | 2025-04-20 13:20:48.858779+00:00 |      9056 |              3 |          0 |                NULL
(25 rows)
Time: 3.58239ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图8)

row_count:表中的总行数(9056 行)。
distinct_count:字段值的唯一性(如 username 的唯一值为 9045,age 的唯一值为 20)。
null_count:字段中 NULL 值的数量(均为 0)。
统计信息的作用:
数据库优化器根据统计信息决定是否使用索引或全表扫描。


6.3 查看执行计划
root@127.0.0.1:26257/example_db> EXPLAIN ANALYZE select * FROM users WHERE username = 'john_doe';
  automatic |                                                                                                                                                                                                                                                                                  json
------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    false   | {
            |
            |   "sql": "EXPLAIN ANALYZE (DISTSQL) select * FROM users WHERE username = 'john_doe'",
            |
            |   "nodeNames": [
            |
            |     "1"
            |
            |   ],
            |
            |   "processors": [
            |
            |     {
            |
            |       "nodeIdx": 0,
            |
            |       "inputs": [],
            |
            |       "core": {
            |
            |         "title": "TableReader/0",
            |
            |         "details": [
            |
            |           "users@idx_users_username",
            |
            |           "Spans: /\"john_doe\"-/\"john_doe\"/PrefixEnd",
            |
            |           "Out: @1",
            |
            |           "rows read: 1",
            |
            |           "stall time: 782µs",
            |
            |           "bytes read: 46 B"
            |
            |         ]
            |
            |       },
            |
            |       "outputs": [],
            |
            |       "stage": 1
            |
            |     },
            |
            |     {
            |
            |       "nodeIdx": 0,
            |
            |       "inputs": [],
            |
            |       "core": {
            |
            |         "title": "JoinReader/1",
            |
            |         "details": [
            |
            |           "users@primary",
            |
            |           "Out: @1,@2,@3,@4,@5",
            |
            |           "rows read: 1",
            |
            |           "stall time: 990µs",
            |
            |           "index rows read: 1",
            |
            |           "index stall time: 509µs"
            |
            |         ]
            |
            |       },
            |
            |       "outputs": [],
            |
            |       "stage": 2
            |
            |     },
            |
            |     {
            |
            |       "nodeIdx": 0,
            |
            |       "inputs": [],
            |
            |       "core": {
            |
            |         "title": "Response",
            |
            |         "details": [
            |
            |           "rows read: 1",
            |
            |           "stall time: 1.651ms"
            |
            |         ]
            |
            |       },
            |
            |       "outputs": [],
            |
            |       "stage": 0
            |
            |     }
            |
            |   ],
            |
            |   "edges": [
            |
            |     {
            |
            |       "sourceProc": 0,
            |
            |       "sourceOutput": 0,
            |
            |       "destProc": 1,
            |
            |       "destInput": 0
            |
            |     },
            |
            |     {
            |
            |       "sourceProc": 1,
            |
            |       "sourceOutput": 0,
            |
            |       "destProc": 2,
            |
            |       "destInput": 0
            |
            |     }
            |
            |   ],
            |
            |   "encodePlan": "eJyUktuO0zAQhu95itHcLKCBJmW7UEtIKRBEUWlLW4nTRpW3HhajxA62I7qq8li8AE-GklDtQWzF3nnG_598n-Qd-h85Ckw_ziej8RRG09Hk0-cU7r8aL1fL95MHsEwn6csVPITXi9k7qDw7Dx_epIu0PRtZMDyHo-_2m1kry0dIaKziqSzYo_iCMWaEpbMb9t66ZrVrA2O1RRERalNWoVlnhBvrGMUOgw45o8CVPMt5wVKx60VIqDhInbefbTkSrbbr9rTesyDhspTGC-id4h7qFB9dm3pzx1_1NjUKCWdVEJDESOjsTw-OpRLQjD7IPIegCxbw9Fn_9y-PhGcXgfeh4xN4gVlNaKtwKeGDPGcUcU3_L_rWavPXM_6XZ-l0Id3FJS0lfUqeUHJMyeAw-XAYdeTaKN7CjWS3vJofRMMmf5tW_y5aC_alNZ6vKx2AjR-fDOLi9r9HdUbI6py7d-Rt5TY8d3bTonTjrO21C8U-dLdxN4xNd9VIXC3HB8v9G-WsvvcnAAD__zF0C4A="
            |
            | }
(1 row)
Time: 4.726964ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图9)

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图10)

索引使用情况:
查询使用了 idx_users_username 索引,直接定位到目标记录。避免了全表扫描,显著提高了查询效率。
性能指标:
Rows read: 1 行。
Stall time: 索引查找时间(782μs)和主表读取时间(990μs)均较短。
Bytes read: 仅读取了 46 字节的数据。
索引有效减少了 I/O作,提升了查询速度。

root@127.0.0.1:26257/example_db> EXPLAIN ANALYZE select * FROM users WHERE age > 30;
  automatic |                                                                                                                                                                                                                                      json
------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    true    | {
            |
            |   "sql": "EXPLAIN ANALYZE (DISTSQL) select * FROM users WHERE age \u003e 30",
            |
            |   "nodeNames": [
            |
            |     "1"
            |
            |   ],
            |
            |   "processors": [
            |
            |     {
            |
            |       "nodeIdx": 0,
            |
            |       "inputs": [],
            |
            |       "core": {
            |
            |         "title": "TableReader/0",
            |
            |         "details": [
            |
            |           "users@primary",
            |
            |           "Spans: -",
            |
            |           "Filter: @4 \u003e 30:::INT8",
            |
            |           "rows read: 9056",
            |
            |           "stall time: 12.132ms",
            |
            |           "bytes read: 733 KiB"
            |
            |         ]
            |
            |       },
            |
            |       "outputs": [],
            |
            |       "stage": 1
            |
            |     },
            |
            |     {
            |
            |       "nodeIdx": 0,
            |
            |       "inputs": [],
            |
            |       "core": {
            |
            |         "title": "Response",
            |
            |         "details": [
            |
            |           "rows read: 6285",
            |
            |           "stall time: 23.208ms"
            |
            |         ]
            |
            |       },
            |
            |       "outputs": [],
            |
            |       "stage": 0
            |
            |     }
            |
            |   ],
            |
            |   "edges": [
            |
            |     {
            |
            |       "sourceProc": 0,
            |
            |       "sourceOutput": 0,
            |
            |       "destProc": 1,
            |
            |       "destInput": 0
            |
            |     }
            |
            |   ],
            |
            |   "encodePlan": "eJyMkE9vm0AQxe_9FKM5tdXW5U_tunuy22IVlWIXkPon4bCGkYUELNlZlFgW3z0yKHISKVKO8-bt29-bE_JNjRKDv7toHcawjtfRv_8BvP0epln6O3oHaRAF3zJ4D5tk-wt6JsPw50eQBKAOBNe94_gEvoMCW11SrBpilFfoYi6wM7ogZm3O0mk0hOUdSkdg1Xa9Pcu5wEIbQnlCW9maUGKm9jUlpEoyH8_BJVlV1WPs-P-qM1WjzBEFpp1qWcIHFLipaktGwurThUpKGcbZEgUafctgSJUSvjjzBQpkq-oabNWQBNebub7XMArcHy09OD_7PvysvmI-CNS9vRCzVQdC6Q7i9a0S4k63TE8LPeJaeMv5My7Pn3nOsuEXCZwhF0jlgaYLs-5NQTujixFnGrfju1Eoie20dachbKfVkA9v7gMAAP__ZG2jlw=="
            |
            | }
(1 row)
Time: 25.207949ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图11)

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图12)

索引使用情况:
查询使用了 idx_users_age 索引,快速定位符合条件的记录。范围查询的效率依赖于字段的分布情况(如唯一值数量)。
性能指标:
Rows read: 返回多行数据(具体数量取决于条件匹配的记录数)。
Stall time: 时间开销较大,可能与范围查询涉及的记录数较多有关。
索引在范围查询中仍然有效,但性能受字段分布影响较大。


7.性能对比

为了更好地理解 KWDB 的性能优势,我们可以进行一些简单的性能测试。这里我们将比较有无索引情况下的查询性能差异,并结合大数据量进行测试。


7.1 清除现有索引
root@127.0.0.1:26257/example_db> drop INDEX idx_users_username;
NOTICE: the data for dropped indexes is reclaimed asynchronously
HINT: The reclamation delay can be customized in the zone configuration for the table.
drop INDEX
Time: 94.822581ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图13)

root@127.0.0.1:26257/example_db> drop INDEX idx_users_age;
NOTICE: the data for dropped indexes is reclaimed asynchronously
HINT: The reclamation delay can be customized in the zone configuration for the table.
drop INDEX
Time: 92.224639ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图14)


7.2 执行查询并记录时间
root@127.0.0.1:26257/example_db> EXPLAIN ANALYZE select * FROM users WHERE username = 'john_doe';
  automatic |                                                                                                                                                                                                                                        json
------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    true    | {
            |
            |   "sql": "EXPLAIN ANALYZE (DISTSQL) select * FROM users WHERE username = 'john_doe'",
            |
            |   "nodeNames": [
            |
            |     "1"
            |
            |   ],
            |
            |   "processors": [
            |
            |     {
            |
            |       "nodeIdx": 0,
            |
            |       "inputs": [],
            |
            |       "core": {
            |
            |         "title": "TableReader/0",
            |
            |         "details": [
            |
            |           "users@primary",
            |
            |           "Spans: -",
            |
            |           "Filter: @2 = 'john_doe':::STRING",
            |
            |           "rows read: 9056",
            |
            |           "stall time: 9.658ms",
            |
            |           "bytes read: 733 KiB"
            |
            |         ]
            |
            |       },
            |
            |       "outputs": [],
            |
            |       "stage": 1
            |
            |     },
            |
            |     {
            |
            |       "nodeIdx": 0,
            |
            |       "inputs": [],
            |
            |       "core": {
            |
            |         "title": "Response",
            |
            |         "details": [
            |
            |           "rows read: 1",
            |
            |           "stall time: 13.062ms"
            |
            |         ]
            |
            |       },
            |
            |       "outputs": [],
            |
            |       "stage": 0
            |
            |     }
            |
            |   ],
            |
            |   "edges": [
            |
            |     {
            |
            |       "sourceProc": 0,
            |
            |       "sourceOutput": 0,
            |
            |       "destProc": 1,
            |
            |       "destInput": 0
            |
            |     }
            |
            |   ],
            |
            |   "encodePlan": "eJyMkF9r1UAQxd_9FMN5qcpak156tQtCr5pqMKY1CfiPINvsUCNJNu5s0HLJd5cmiFYQ-rZzztnd35k95HsHjeTDRbZLc9rlu-zjp4Tuv0zLqnyXPaAyyZIXFT2ks-L8LU3CXuj966RIlvNgeqZndPDNfR2-WMcHUBic5dz0LNCfEaNWGL1rWMT5G2m_BFL7EzpSaIdxCjdyrdA4z9B7hDZ0DI3KXHZcsLHsH0dQsBxM2y3PLhyno29746-hUI5mEE2PoHDWdoG9ptOjW2Ba67Iq0vwVFLz7IeTZWE0n0fEWChJM11Foe9Z0crg9ftoLFC6vA_8OPtls6E37HPWs4Kbwh1qCuWLoeFZ3b1awjG4Qvl3qL6z4H6Z4cxhtj3r57_fRXCuwveJ1xeIm3_CFd83Cso7ny71FsCxhdeN1SIfVmuv53q8AAAD__9JdqQI="
            |
            | }
(1 row)
Time: 14.958257ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图15)KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图16)

root@127.0.0.1:26257/example_db> EXPLAIN ANALYZE select * FROM users WHERE age > 30;
  automatic |                                                                                                                                                                                                                              json
------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    false   | {
            |
            |   "sql": "EXPLAIN ANALYZE (DISTSQL) select * FROM users WHERE age \u003e 30",
            |
            |   "nodeNames": [
            |
            |     "1"
            |
            |   ],
            |
            |   "processors": [
            |
            |     {
            |
            |       "nodeIdx": 0,
            |
            |       "inputs": [],
            |
            |       "core": {
            |
            |         "title": "TableReader/0",
            |
            |         "details": [
            |
            |           "users@idx_users_age_covering",
            |
            |           "Spans: /31-",
            |
            |           "rows read: 6285",
            |
            |           "stall time: 13.034ms",
            |
            |           "bytes read: 503 KiB"
            |
            |         ]
            |
            |       },
            |
            |       "outputs": [],
            |
            |       "stage": 1
            |
            |     },
            |
            |     {
            |
            |       "nodeIdx": 0,
            |
            |       "inputs": [],
            |
            |       "core": {
            |
            |         "title": "Response",
            |
            |         "details": [
            |
            |           "rows read: 6285",
            |
            |           "stall time: 22.803ms"
            |
            |         ]
            |
            |       },
            |
            |       "outputs": [],
            |
            |       "stage": 0
            |
            |     }
            |
            |   ],
            |
            |   "edges": [
            |
            |     {
            |
            |       "sourceProc": 0,
            |
            |       "sourceOutput": 0,
            |
            |       "destProc": 1,
            |
            |       "destInput": 0
            |
            |     }
            |
            |   ],
            |
            |   "encodePlan": "eJyMkF9r2zAUxd_3KS73aRtaIsfLCHpatnnMzEsyO7C_JijWxRhsy9WV25Tg715iU0ofWvqme-7R0e_ojHxVo8Lo9y5ZxxtYb9bJn78RvP4SZ_vsZ_IGsiiJPu_hLXxNtz-gZ3IMv75FaQS6JPjfSxkShBIFttbQRjfEqP5hgLnAztmCmK27SOfREJsTKimwarveX-RcYGEdoTqjr3xNqHCvjzWlpA25-SXYkNdVPcaO73-szOkwng66pENhr8lVbYkCs063rGAeBu9QoLM3DI60UfBhsVqiQPa6rsFXDSkIwpkM3zeMAo-3nu6dSxnC9-oT5oNA2_sHSva6JFTBIF7eJCXubMv0uMTzXIvFbCXDhp8kkEMukExJ06-y7V1BO2eLEWcat-O9UTDEftoG0xC302rIh1d3AQAA___0mKJh"
            |
            | }
(1 row)
Time: 24.651309ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图17)KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图18)

7.3 重新添加索引

添加覆盖索引(username)
通过 STORING 子句将查询所需字段直接包含在索引中,避免回表:

root@127.0.0.1:26257/example_db> CREATE INDEX idx_users_username_covering ON users(username)
                              ->   STORING (email, age, created_at);
CREATE INDEX
Time: 342.749645ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图19)

添加覆盖索引(age)
将查询所需的所有字段包含在索引中,避免回表作:

root@127.0.0.1:26257/example_db> CREATE INDEX idx_users_age_covering ON users (age)   STORING (username, email, created_at);
CREATE INDEX
Time: 309.510184ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图20)

● 作用:索引直接包含 username, email, created_at,无需回表。
● 适用场景:频繁的 select * + WHERE age 查询。


7.4 再次执行查询并记录时间

验证执行计划
检查优化器是否选择新索引:

root@127.0.0.1:26257/example_db> EXPLAIN ANALYZE select * FROM users WHERE username = 'john_doe';
  automatic |                                                                                                                                                                                                                                        json
------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    false   | {
            |
            |   "sql": "EXPLAIN ANALYZE (DISTSQL) select * FROM users WHERE username = 'john_doe'",
            |
            |   "nodeNames": [
            |
            |     "1"
            |
            |   ],
            |
            |   "processors": [
            |
            |     {
            |
            |       "nodeIdx": 0,
            |
            |       "inputs": [],
            |
            |       "core": {
            |
            |         "title": "TableReader/0",
            |
            |         "details": [
            |
            |           "users@idx_users_username_covering",
            |
            |           "Spans: /\"john_doe\"-/\"john_doe\"/PrefixEnd",
            |
            |           "rows read: 1",
            |
            |           "stall time: 382µs",
            |
            |           "bytes read: 77 B"
            |
            |         ]
            |
            |       },
            |
            |       "outputs": [],
            |
            |       "stage": 1
            |
            |     },
            |
            |     {
            |
            |       "nodeIdx": 0,
            |
            |       "inputs": [],
            |
            |       "core": {
            |
            |         "title": "Response",
            |
            |         "details": [
            |
            |           "rows read: 1",
            |
            |           "stall time: 463µs"
            |
            |         ]
            |
            |       },
            |
            |       "outputs": [],
            |
            |       "stage": 0
            |
            |     }
            |
            |   ],
            |
            |   "edges": [
            |
            |     {
            |
            |       "sourceProc": 0,
            |
            |       "sourceOutput": 0,
            |
            |       "destProc": 1,
            |
            |       "destInput": 0
            |
            |     }
            |
            |   ],
            |
            |   "encodePlan": "eJyMkN2O0zAUhO95CmtuCsioDUUUWUKiQBCRQluSSvw1itz4UIJSO9gOFFV5rH2BfbJVHVWrXuxq787MGdvf-Aj3p4FA_HWVzpMFmy_m6bfvMXv8PsnX-ef0CcvjNH63Zk_Zh2z5iXWOrGNfPsZZHGYt98Res9Fv80uXytAIHNooWsg9OYgfiFBwtNZU5JyxJ-sYAok6QEw4at12_mQXHJWxBHGEr31DEFjLbUMZSUV2PAGHIi_rJlwbON7U6lCGqTyzlJX5S7bWO3DkrdROsPEGZ7oNnl2o8crSz_oQawUOa_45ZkkqwSJwOC-bhvl6T4JNXz2_vnLg2P73dA7NZuwtip7DdP62g_NyRxBRzx_eMyPXGu3osuI9PC9eTk88dz0-6QsOUjsavtuZzla0sqYKJINchnPBUOT8sI0Gkehh1Rf9o5sAAAD__6z_s0E="
            |
            | }
(1 row)
Time: 1.61164ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图21)KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图22)

root@127.0.0.1:26257/example_db> EXPLAIN ANALYZE select * FROM users WHERE age > 30;
  automatic |                                                                                                                                                                                                                              json
------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    false   | {
            |
            |   "sql": "EXPLAIN ANALYZE (DISTSQL) select * FROM users WHERE age \u003e 30",
            |
            |   "nodeNames": [
            |
            |     "1"
            |
            |   ],
            |
            |   "processors": [
            |
            |     {
            |
            |       "nodeIdx": 0,
            |
            |       "inputs": [],
            |
            |       "core": {
            |
            |         "title": "TableReader/0",
            |
            |         "details": [
            |
            |           "users@idx_users_age_covering",
            |
            |           "Spans: /31-",
            |
            |           "rows read: 6285",
            |
            |           "stall time: 4.412ms",
            |
            |           "bytes read: 503 KiB"
            |
            |         ]
            |
            |       },
            |
            |       "outputs": [],
            |
            |       "stage": 1
            |
            |     },
            |
            |     {
            |
            |       "nodeIdx": 0,
            |
            |       "inputs": [],
            |
            |       "core": {
            |
            |         "title": "Response",
            |
            |         "details": [
            |
            |           "rows read: 6285",
            |
            |           "stall time: 8.107ms"
            |
            |         ]
            |
            |       },
            |
            |       "outputs": [],
            |
            |       "stage": 0
            |
            |     }
            |
            |   ],
            |
            |   "edges": [
            |
            |     {
            |
            |       "sourceProc": 0,
            |
            |       "sourceOutput": 0,
            |
            |       "destProc": 1,
            |
            |       "destInput": 0
            |
            |     }
            |
            |   ],
            |
            |   "encodePlan": "eJyMkF9vmzAUxd_3Ka7u0zZ5CYRki_y0bGMaGksyiLT1D4ocfIWQAFNf06aK-O5VQFXVh1Z98z33-Ph3fEK-qVBi-H8br6I1rNar-OIyhPc_onSX_o0_QBrG4fcdfISfyeYPdEyW4d-vMAlBFQTXnecFBIGHAhujaa1qYpRX6GMmsLUmJ2Zjz9JpMET6iNITWDZt585yJjA3llCe0JWuIpS4U4eKElKa7PQcrMmpshpih_e_lvq4H057VdA-N7dky6ZAgWmrGpYwDfxPKNCaOwZLSkv4PFsuUCA7VVXgypokzCdzf1YzCjzcO3o0LrwAfpffMOsFms49QbJTBaH0e_H2Iglxaxqm5x1ex1pOfO9LzS8CeH0mkHRB45-y6WxOW2vygWYcN8O9QdDEbtz64xA146rP-ncPAQAA___iiKIC"
            |
            | }
(1 row)
Time: 9.135709ms

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图23)

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图24)

性能对比分析:
● 在没有索引的情况下,查询需要扫描整个表,性能较差。
● 添加索引后,查询速度显著提升,特别是对于大数据量的场景。


7.5 统计不同年龄段的用户数量
root@127.0.0.1:26257/example_db> select 
        WHEN age BETWEEN 18 AND 25 THEN '18-25'
        WHEN age BETWEEN 26 AND 35 THEN '26-35'
        WHEN age BETWEEN 36 AND 45 THEN '36-45'
        ELSE '46+'
    END AS age_group,
                              ->     CASE 
    COUNT(*) AS user_count
FROM users
GROUP BY age_group;
                              ->         WHEN age BETWEEN 18 AND 25 THEN '18-25'
                              ->         WHEN age BETWEEN 26 AND 35 THEN '26-35'
                              ->         WHEN age BETWEEN 36 AND 45 THEN '36-45'
                              ->         ELSE '46+'
                              ->     END AS age_group,
                              ->     COUNT(*) AS user_count
                              -> FROM users
                              -> GROUP BY age_group;
  age_group | user_count
------------+-------------
  36-45     |       4100
  18-25     |        479
  26-35     |       4477
(3 rows)
Time: 11.981512ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图25)

  • 结果
    • 36-45 岁:4100 人
    • 26-35 岁:4477 人
    • 18-25 岁:479 人
  • 性能: 11.98ms,依赖全表扫描或索引覆盖。

7.6 统计每个用户的平均年龄
root@127.0.0.1:26257/example_db> select AVG(age) AS average_age FROM users;
       average_age
-------------------------
  34.480675795053003534
(1 row)
Time: 8.359482ms

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图26)

  • 结果:34.48 岁
  • 性能: 8.36ms,快速聚合无需复杂过滤。

7.7 统计每个用户的注册时间分布
root@127.0.0.1:26257/example_db> select 
    COUNT(*) AS user_count
FROM users
                              ->     created_at,
GROUP BY created_at
ORDER BY created_at;
                              ->     COUNT(*) AS user_count
                              -> FROM users
                              -> GROUP BY created_at
                              -> ORDER BY created_at;
             created_at            | user_count
-----------------------------------+-------------
  2025-04-18 05:36:10.606017+00:00 |          5
  2025-04-20 09:24:59.710609+00:00 |         50
  2025-04-20 12:43:10.985752+00:00 |       9001
(3 rows)
Time: 8.570607ms
root@127.0.0.1:26257/example_db>

KWDB 创作者计划 |实战指南:KWDB 2.2.0数据分析与性能调优深度对比(图27)

  • 结果:数据集中在 3 个时间点(2025-04-18、2025-04-20)。
  • 性能: 8.57ms,分组效率高。


8.KWDB 优化与性能对比总结分析


8.1 索引优化效果对比
查询类型无索引耗时普通索引耗时覆盖索引耗时优化效果
WHERE username=~14.96 毫秒~3.28 毫秒~1.61 毫秒覆盖索引提升 89%(对比无索引)
WHERE age > 30~3.08 毫秒~16.86 毫秒~9.14 毫秒覆盖索引提升 46%(对比普通索引)

8.2 关键优化分析

a. WHERE username= 精确查询

  • 普通索引:通过 直接定位记录,减少全表扫描,耗时从 14.96ms 降至 3.28msidx_users_username
  • 覆盖索引:进一步消除回表作( ),耗时降至 1.61ms,性能提升 89%。STORING email, age, created_at
  • 执行计划:明确使用  ,仅读取索引数据(77 B),无需回表。users@idx_users_username_covering

b. WHERE age > 30 范围查询

  • 普通索引问题
    • 数据分布广泛(年龄>30 占比约 70%),优化器认为全表扫描更高效。
    • 普通索引需回表,耗时  16.86ms,性能甚至差于无索引场景(3.08ms)。
  • 覆盖索引优势
    • 包含所有查询字段( ),避免回表,耗时降至  9.14msSTORING username, email, created_at
    • 数据读取量从  733 KiB(全表)减少至  503 KiB(索引内直接读取)。

8.3 优化结论

a.  覆盖索引的核心价值

  • 消除回表作,减少 IO 开销,尤其适用于高频的 查询。select *
  • 示例: 查询性能提升至 1.61ms, 提升至 9.14msWHERE username=WHERE age > 30

b.  普通索引的局限性

  • 当查询覆盖大量数据时(如范围覆盖 70% 行),可能被优化器忽略。
  • 需结合   更新统计信息,确保优化器决策准确。ANALYZE

c.  数据分布影响

  • 年龄字段唯一值少(20 个),范围查询需谨慎选择索引策略。
  • 高频查询建议使用覆盖索引,低频查询可保留普通索引。

8.4 建议与扩展

a. 定期更新统计信息
– 确保优化器基于最新数据分布决策

b.  冷热数据分离

  • 按时间分区(如  ),减少活跃数据集大小。created_at

c.  业务逻辑优化

  • 避免  ,仅请求必要字段,降低 IO 压力。select *

d.  分布式特性探索

  • 若 KWDB 为分布式架构,可研究数据分片对查询性能的影响。

8.5 最终性能对比图
查询场景            | 无索引  | 普通索引 | 覆盖索引
------------------------------------------------
WHERE username=    | 14.96ms | 3.28ms  | 1.61ms
WHERE age > 30     | 3.08ms  | 16.86ms | 9.14ms

通过覆盖索引和统计信息优化,KWDB 在关键查询场景中展现了显著的性能提升,尤其在高频精确匹配和大范围扫描场景下表现优异。

结论

本文详细介绍了如何在 CentOS 7 环境下安装和配置 KWDB 2.2.0,并通过一系列实际作展示了其强大的功能和灵活性。无论是创建库、表,还是进行数据库优化和性能对比,KWDB 都展现出了卓越的性能和灵活性。希望这篇文档能够帮助读者更好地理解和应用 KWDB,同时也期待更多开发者加入我们的社区,共同探索分布式多模数据库的未来。
通过本文的学习,你已经掌握了从基础安装到高级优化的全过程。让我们一起“码”上出发,用键盘构建通向技术与创新的桥梁!




体验全新的分布式多模数据库解决方案

企业版 社区版

KaiwuDB 是浪潮控股的数据库企业,面向工业物联网、数字能源、车联网、智慧产业等行业领域,提供稳定安全、高性能、易运维的创新数据软件与服务。

关注官方微信

友情链接:浪潮  

© 上海沄熹科技有限公司 Shanghai Yunxi Technology Co., Ltd.    沪ICP备2023002175号-1    网站服务协议   |   隐私政策
400-624-5688-7
服务与支持
marketing@kaiwudb.org.cn