欢迎参与 8 月 1 日中午 11 点的线上分享,了解 GreptimeDB 联合处理指标和日志的最新方案! 👉🏻 点击加入

Skip to content
On this page
性能报告
2025-3-7

写入性能跃升 67.5%,存储成本锐减 50%|GreptimeDB v0.12 日志场景性能测试发布

GreptimeDB v0.12 在读写性能、资源占用方面得到了极大的优化,写入吞吐最高提高了 67.5%,写入过程的 CPU 占用降低至 40%。

测试结论

  • 相比初次引入日志相关功能的 GreptimeDB v0.9,v0.12 在读写性能、资源占用方面得到了极大的优化,写入吞吐最高提高了 67.5%, 写入过程的 CPU 占用降低至 40%。
  • 在日志写入场景下,无论结构化数据还是非结构化数据,GreptimeDB 都具备极高的写入吞吐,约为 **ClickHouse 的 111%,Elasticsearch 的 470%,**且使用低成本的对象存储时写入性能无明显下降。
  • 在日志查询场景下,GreptimeDB 与 ClickHouse 和 Elasticsearch 各有适用场景,但是均维持在相同量级。得益于 GreptimeDB 的各级缓存优化,在数据位于对象存储时仍能维持查询性能不退化,从而获得更好的成本/性能平衡。
  • 得益于 GreptimeDB 的列式存储和压缩算法,GreptimeDB 提供了三者中最优的数据压缩率,持久化数据大小仅为 ClickHouse 的 50% 和 Elasticsearch 的 12.7%,能够进一步降低数据长期持有的成本。

测试场景

测试数据和流程

我们选用 nginx access log 作为写入数据,一行数据的样例如下:

plaintext
129.37.245.88 - meln1ks [01/Aug/2024:14:22:47 +0800] "PATCH /observability/metrics/production HTTP/1.0" 501 33085

我们使用 Vector 这个开源可观测数据 pipeline 来生成并写入上面的数据。整体测试的流程如图:

(图 1: 测试流程图)
(图 1: 测试流程图)

针对不同的查询和存储需求,我们分别测试了结构化数据模型和非结构化数据模型两种写入查询模式的表现:

  • 结构化数据模型:通过 Vector 对写入的日志数据的字段进行切割,并将不同字段写入到表中的不同列当中。在查询时分别针对不同的列进行数据过滤。
  • 非结构化数据模型:除解析出时间戳字段外,将日志文本整体作为一个 message 字段存储,并启用全文索引。查询时使用关键字匹配方式检索。

软硬件说明

硬件平台

服务器型号AWS c5d.2xlarge, 8 vCPU 16GiB Memory
操作系统Ubuntu24.04 LTS

服务器型号

数据库版本
GreptimeDBv0.12
ClickHouse24.9.1.219
Elasticsearch8.15.0

注:各数据库的具体配置文件见附录

读写性能测试

写入表现

数据库结构化模型平均 TPS非结构化模型平均 TPS
GreptimeDB (v0.9)12722695238
GreptimeDB(v0.12)185535159502
GreptimeDB (v0.12, S3)182272154209
ClickHouse166667136612
Elasticsearch3940128058
(图 2:写入吞吐对比)
(图 2:写入吞吐对比)
  • GreptimeDB v0.12 的写入性能得到了大幅的优化,相较 GreptimeDB v0.9 ,结构化模型下提升了 45.8%,非结构化模型下提升了 67.5%。
  • GreptimeDB 的写入性能相对 ClickHouse 小幅领先,但两者都大大优于 Elasticsearch。在结构化模型下,GreptimeDB 的写入吞吐是 Elasticsearch 的 4.7 倍;在非结构化模型下,GreptimeDB 的写入吞吐是 Elasticsearch 的 5.7 倍。
  • 在使用 AWS S3 作为底层存储时,GreptimeDB 的写入吞吐仅降低 1~2%,却可以极大地降低成本。

查询表现

我们将查询场景分为 6 个,同时覆盖了比较典型的日志使用场景:

  1. COUNT 统计查询:统计全表数据行数;
  2. 关键词匹配查询:匹配日志中的 user、method、endpoint、version、code 分别为特定值;
  3. 区间统计查询:使用时间范围统计约一半(5,000 万行)数据行数的查询;
  4. 中间时间范围查询:取时间中间范围一分钟,并查询 1000 行数据;
  5. 最近时间范围查询:取最近时间范围一分钟,并查询 1000 行数据;
  6. 关键词匹配 + 区间查询:查询特定时间范围内的字段匹配结果。

注:

结构化数据

查询类别和耗时(毫秒)GreptimeDBGreptimeDB on S3ClickHouseElasticsearch
Count Query664610
Keyword Matching22.824.752134
Time range512.3653.941316
Middle Time Range18.615.75632
Recent Time Range16.111.813325
Keyword Matching+Range Query1943.25288
(图 3:结构化数据查询耗时)
(图 3:结构化数据查询耗时)

以上数据可以看出:

  • GreptimeDB 和 ClickHouse 在结构化数据的查询性能上各有优劣,但总的来说三者性能差距不大
  • 在指定扫描时间段较大时,GreptimeDB 和 ClickHouse 的性能下降较为明显,但是能够在几百毫秒内完成查询。
  • 得益于 GreptimeDB 的多级缓存设计,在使用 S3 存储数据时 GreptimeDB 的查询性能并未出现明显降低。

非结构化数据

查询类别和耗时(毫秒)GreptimeDBGreptimeDB on S3ClickHouseElasticsearch
Count query6689
Keyword matching254724782080161
Time range1166133057210
Middle Time Range22.432.25126
Recent Time Range13.513.860622
Keyworld Matching and Range Query331.8350.21610122
(图 4:结构化数据查询耗时)
(图 4:结构化数据查询耗时)
  • 相比 GreptimeDB v0.9,v0.12 在大部分非结构化查询的性能都得到了提升
  • 相比结构化数据模型,GreptimeDB 和 ClickHouse 在非结构化模型下的查询性能都出现了退化,并落后于 Elasticsearch。

资源占用和压缩率

资源占用

限制写入速度为 2 万行每秒的前提下,分别观察 GreptimeDB/ClickHouse/Elasticsearch 的 CPU 和内存占用:

数据库结构化数据模型结构化数据模型非结构化数据模型非结构化数据模型
参数CPU(%)Memory(MB)CPU(%)Memory(MB)
GreptimeDB (v0.9)33.2433716.79462
GreptimeDB (v0.12)13.240810.29624
ClickHouse9.5661126.77732
Elasticsearch40.22988347.549320
  • 在限制写入吞吐为 2 万行每秒的场景下,ClickHouse 的 CPU 占用率最低,GreptimeDB 略高于 ClickHouse,但是相比 v0.9 版本有较大优化(在结构化模型下从 33.24% 降低到 13.2%,在非结构化模型下从 16.79% 降低到 10.29%)。
  • GreptimeDB 的内存占用在三者中最低,而 Elasticsearch 的内存占用比 GreptimeDB/ClickHouse 高出一个数量级。
  • GreptimeDB 和 ClickHouse 都是类似于 LSM Tree 的数据结构,因此内存波动较大。

压缩率

测试原始数据文件大小约为 10GB。在所有数据写入完毕后,我们统计各个数据库产品的持久化目录大小,从而可以计算得到如下压缩率:

数据库结构化数据模型结构化数据模型非结构化数据模型非结构化数据模型
参数数据大小(GB)压缩比数据大小(GB)压缩比
GreptimeDB1.313%3.333%
ClickHouse (压缩前)7.626%15.551%
ClickHouse (压缩后)2.626%5.151%
Elasticsearch(压缩前)14.6102%19172%
Elasticsearch(压缩后)10.2102%17.2172%

从以上数据可以得出:

  • GreptimeDB v0.12 保持了一直以来的压缩率优势,在结构化数据模型下,持久化文件大小约为原文件大小的 13%,而在非结构化模型下约为 33%。
  • 由于结构化数据模型将文本切分为不同的列,针对这些列可以自适应选择合适的编码和压缩策略,因此结构化数据模型的压缩率要远远优于非结构化模型。

注:ClickHouse 和 Elasticsearch 都会在后台持续对文件进行压缩,因此表格中分别记录了压缩前后的数据大小。

附录

软件配置

  • GreptimeDB 本地存储配置使用默认配置

  • GreptimeDB 在 S3 上的配置文件如下:

toml
[storage]
type = "S3"
bucket = "<bucket_name>"
root = "log_benchmark"
access_key_id = "<ACCESS_KEY>"
secret_access_key = "<SECRET_KEY>"
endpoint = "<S3_ENDPOINT>"
region = "<S3_REGION>"
cache_path = "<CACHE_PATH>"
cache_capacity = "20G"

[[region_engine]]
[region_engine.mito]
enable_experimental_write_cache = true
experimental_write_cache_size = "20G"

Vector 解析日志配置文件

toml
[transforms.parse_logs]
type = "remap"
inputs = ["demo_logs"]
source = '''
. = parse_regex!(.message, r'^(?P<ip>\S+) - (?P<user>\S+) \[(?P<timestamp>[^\]]+)\] "(?P<method>\S+) (?P<path>\S+) (?P<http_version>\S+)" (?P<status>\d+) (?P<bytes>\d+)$')

# Convert timestamp to a standard format
.timestamp = parse_timestamp!(.timestamp, format: "%d/%b/%Y:%H:%M:%S %z")

# Convert status and bytes to integers
.status = to_int!(.status)
.bytes = to_int!(.bytes)
'''

建表语句

结构化数据模型

GreptimeDB
sql
--启用了 append 模式,并且将 user、path 和 status 设置为 Tag 类型(即主键)
CREATE TABLE IF NOT EXISTS `test_table` (
    `bytes` Int64 NULL,
    `http_version` STRING NULL,
    `ip` STRING NULL,
    `method` STRING NULL,
    `path` STRING NULL,
    `status` SMALLINT UNSIGNED NULL,
    `user` STRING NULL,
    `timestamp` TIMESTAMP(3) NOT NULL,
    PRIMARY KEY (`user`, `path`, `status`),
    TIME INDEX (`timestamp`)
)
ENGINE=mito
WITH(
    append_mode = 'true'
);
ClickHouse
sql
--使用默认 MergeTree 引擎,定义同样的 sorting key。
CREATE TABLE IF NOT EXISTS test_table
(
    bytes UInt64 NOT NULL,
    http_version String NOT NULL,
    ip String NOT NULL,
    method String NOT NULL,
    path String NOT NULL,
    status UInt8 NOT NULL,
    user String NOT NULL,
    timestamp String NOT NULL,
)
ENGINE = MergeTree()
ORDER BY (user, path, status);
Elasticsearch
json
{
  "vector-2024.08.19": {
    "mappings": {
      "properties": {
        "bytes": {
          "type": "long"
        },
        "http_version": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "ip": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "method": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "path": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "status": {
          "type": "long"
        },
        "timestamp": {
          "type": "date"
        },
        "user": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }
}

非结构化数据模型

GreptimeDB
sql
--message 列启用 FULLTEXT 选项,开启全文索引
CREATE TABLE IF NOT EXISTS `test_table` (
    `message` STRING NULL FULLTEXT WITH(analyzer = 'English', case_sensitive = 'false'),
    `timestamp` TIMESTAMP(3) NOT NULL,
    TIME INDEX (`timestamp`)
)
ENGINE=mito
WITH(
    append_mode = 'true'
);
ClickHouse
sql
SET allow_experimental_full_text_index = true;
CREATE TABLE IF NOT EXISTS test_table
(
    message String,
    timestamp String,
    INDEX inv_idx(message) TYPE full_text(0) GRANULARITY 1
)
ENGINE = MergeTree()
ORDER BY tuple();
Elasticsearch
json
{
  "vector-2024.08.19": {
    "mappings": {
      "properties": {
        "message": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "service": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "source_type": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "timestamp": {
          "type": "date"
        }
      }
    }
  }
}

关于 Greptime

Greptime 格睿科技专注于为可观测、物联网及车联网等领域提供实时、高效的数据存储和分析服务,帮助客户挖掘数据的深层价值。目前基于云原生的时序数据库 GreptimeDB 已经衍生出多款适合不同用户的解决方案,更多信息或 demo 展示请联系下方小助手(微信号:greptime)。

欢迎对开源感兴趣的朋友们参与贡献和讨论,从带有 good first issue 标签的 issue 开始你的开源之旅吧~期待在开源社群里遇见你!添加小助手微信即可加入“技术交流群”与志同道合的朋友们面对面交流哦~

Star us on GitHub Now: https://github.com/GreptimeTeam/greptimedb

官网:https://greptime.cn/

文档:https://docs.greptime.cn/

Twitter: https://twitter.com/Greptime

Slack: https://greptime.com/slack

LinkedIn: https://www.linkedin.com/company/greptime/

加入我们的社区

获取 Greptime 最新更新,并与其他用户讨论。