【发布时间】:2026-02-06 01:05:01
【问题描述】:
我刚刚开始尝试使用 Cassandra,我正在使用 C# 和 DataStax driver (v 3.0.8)。我想做一些性能测试,看看 Cassandra 处理时间序列数据的速度有多快。
结果令人震惊,因为它需要很长时间才能完成SELECT。所以我想我做错了什么。
我已在本地计算机上设置 Cassandra 并创建了一个表:
CREATE KEYSPACE dm WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'} AND durable_writes = true;
CREATE TABLE dm.daily_data_by_day (
symbol text,
value_type int,
as_of_day date,
revision_timestamp_utc timestamp,
value decimal,
PRIMARY KEY ((symbol, value_type), as_of_day, revision_timestamp_utc)
) WITH CLUSTERING ORDER BY (as_of_day ASC, revision_timestamp_utc ASC)
AND bloom_filter_fp_chance = 0.01
AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
AND comment = ''
AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
AND crc_check_chance = 1.0
AND dclocal_read_repair_chance = 0.1
AND default_time_to_live = 0
AND gc_grace_seconds = 864000
AND max_index_interval = 2048
AND memtable_flush_period_in_ms = 0
AND min_index_interval = 128
AND read_repair_chance = 0.0
AND speculative_retry = '99PERCENTILE';
我已经用大约 1500 万行填充了这张表,分为大约 10000 个分区,每个分区最多包含 10000 行。
这是我正在运行的测试(更新 on request by phact):
[Test]
public void SelectPerformance()
{
_cluster = Cluster.Builder().AddContactPoint("127.0.0.1").Build();
_stopwatch = new Stopwatch();
var items = new[]
{
// 20 different items...
};
foreach (var item in items)
{
var watch = Stopwatch.StartNew();
var rows = ExecuteQuery(item.Symbol, item.FieldType, item.StartDate, item.EndDate);
watch.Stop();
Console.WriteLine($"{watch.ElapsedMilliseconds}\t{rows.Length}");
}
Console.WriteLine($"Average Execute: {_stopwatch.ElapsedMilliseconds/items.Length}");
_cluster.Dispose();
}
private Row[] ExecuteQuery(string symbol, int fieldType, LocalDate startDate, LocalDate endDate)
{
using (var session = _cluster.Connect("dm"))
{
var ps = session.Prepare(
@"SELECT
symbol,
value_type,
as_of_day,
revision_timestamp_utc,
value
FROM
daily_data_by_day
WHERE
symbol = ? AND
value_type = ? AND
as_of_day >= ? AND as_of_day < ?");
var statement = ps.Bind(symbol, fieldType, startDate, endDate);
statement.EnableTracing();
_stopwatch.Start();
var rowSet = session.Execute(statement);
_stopwatch.Stop();
return rowSet.ToArray();
}
}
秒表告诉我 session.Execute() 需要 20-30 毫秒来执行(更新:在更改代码以创建集群后,我只需要大约 15 毫秒)。所以我启用了一些跟踪并得到以下结果:
activity | source_elapsed
--------------------------------------------------------------------------------------------
Parsing SELECT symbol, value_type, as_of_day, revision_timestamp_utc,...; | 47
Preparing statement | 98
Executing single-partition query on daily_data_by_day | 922
Acquiring sstable references | 939
Skipped 0/5 non-slice-intersecting sstables, included 0 due to tombstones | 978
Bloom filter allows skipping sstable 74 | 1003
Bloom filter allows skipping sstable 75 | 1015
Bloom filter allows skipping sstable 72 | 1024
Bloom filter allows skipping sstable 73 | 1032
Key cache hit for sstable 63 | 1043
Merged data from memtables and 5 sstables | 1329
Read 100 live and 0 tombstone cells | 1353
如果我正确理解此跟踪,Cassandra 执行我的查询所用的时间不到 1.4 毫秒。那么 DataStax 驱动程序剩下的时间在做什么呢?
(作为参考,我对本地 SQL Server 实例进行了相同的性能测试,结果从 C# 执行相同的查询大约需要 1-2 毫秒。)
更新:
我试图做一些分析,这对于你不拥有的异步代码来说并不容易......
我的结论是大部分时间都花在解析响应上。每个响应包含 2000 - 3000 行,每个响应的解析大约需要 9 毫秒。反序列化花费大部分时间,大约 6.5 毫秒,十进制最差,每个字段大约 3 毫秒。其他字段(文本、整数、日期和时间戳)每个字段大约需要 0.5 毫秒。
看看我测量的时间,我应该怀疑这一点:响应中的行越多,花费的时间越长,而且几乎是线性的。
【问题讨论】:
-
您是否在本地 cassandra 环境中执行过这些测试?只有一个节点?我想分析你的代码。
-
@k0ner 这一切都是在我的本地机器上完成的,只有一个节点。它用于评估 Cassandra,学习如何使用它并查看它的性能。
-
您是否尝试过分析您的代码?
-
@k0ner 不,我还没到那一步。
-
@TorbjörnKalin 您的初始代码,除了不遵循建议(例如在您的应用程序中重用
Session实例/重用准备语句/ ...)之外,仅测量单个执行的延迟多次同步查询。相反,您应该并行执行多个查询(通过异步方法或使用多个任务和调度程序)并分析延迟如何表现以及吞吐量是多少。这里有一个例子:github.com/riptano/csharp-driver-sut