【发布时间】:2025-12-30 12:05:09
【问题描述】:
我做了一个小型基准测试来比较 Couchbase(在 Win 中运行)与 Redis 和 MySql(编辑:添加 Aerospike 进行测试)
我们正在将 100 000 个 JSON“文档”插入三个 db/stores:
- Redis(插入即可,没有别的)
- Couchbase(内存中的临时存储桶,JobId 上的 JSON 索引)
- MySql(简单表;Id (int)、Data (MediumText)、Id 上的索引)
- Aerospike(内存存储)
JSON 文件 67 行,约 1800 字节。
插入:
- Couchbase:60-100 秒(编辑:似乎变化很大!)
- MySql:30 秒
- Redis:8 秒
- 气动尖峰:71 秒
阅读: 我们正在阅读 1000 次,我们这样做了 10 次并查看平均值。
- Couchbase:1000 次 GET 需要 600-700 毫秒(使用 KeyValue 操作,而不是 Query API。使用 Query API,这大约需要 1500 毫秒)
- MySql:1000 次 GET 需要 90-100 毫秒
- Redis:1000 次 GET 需要 50-60 毫秒
- Aerospike:1000 次 GET 需要 750 毫秒
结论: Couchbase 似乎最慢(插入时间似乎变化很大),Aerospike 也很慢。这两个都使用内存存储(Couchbase => Ephemeral bucket,Aerospike => storage-engine memory)。
问题:为什么在 Couchbase 上的内存读写如此缓慢,甚至比使用普通 MySQL(在 SSD 上)还要慢?
代码
注意:使用 Task.WhenAll 或等待每次调用都没有区别。
插入
沙发床:
IBucket bucket = await cluster.BucketAsync("halo"); // <-- ephemeral
IScope scope = bucket.Scope("myScope");
var collection = scope.Collection("myCollection");
// EDIT: Added this to avoid measuring lazy loading:
JObject t = JObject.FromObject(_baseJsonObject);
t["JobId"] = 0;
t["CustomerName"] = $"{firstnames[rand.Next(0, firstnames.Count - 1)]} {lastnames[rand.Next(0, lastnames.Count - 1)]}";
await collection.InsertAsync("0", t);
await collection.RemoveAsync("0");
List<Task> inserTasks = new List<Task>();
sw.Start();
foreach (JObject temp in jsonObjects) // jsonObjects is pre-created so its not a factor in the test
{
inserTasks.Add(collection.InsertAsync(temp.GetValue("JobId").ToString(), temp));
}
await Task.WhenAll(inserTasks);
sw.Stop();
Console.WriteLine($"Adding {nbr} to Couchbase took {sw.ElapsedMilliseconds} ms");
Redis(使用 ServiceStack!)
sw.Restart();
using (var client = redisManager.GetClient())
{
foreach (JObject temp in jsonObjects)
{
client.Set($"jobId:{temp.GetValue("JobId")}", temp.ToString());
}
}
sw.Stop();
Console.WriteLine($"Adding {nbr} to Redis took {sw.ElapsedMilliseconds} ms");
sw.Reset();
Mysql:
MySql.Data.MySqlClient.MySqlConnection mySqlConnection = new MySql.Data.MySqlClient.MySqlConnection("Server=localhost;Database=test;port=3306;User Id=root;password=root;");
mySqlConnection.Open();
sw.Restart();
foreach (JObject temp in jsonObjects)
{
MySql.Data.MySqlClient.MySqlCommand cmd = new MySql.Data.MySqlClient.MySqlCommand($"INSERT INTO test (id, data) VALUES ('{temp.GetValue("JobId")}', @data)", mySqlConnection);
cmd.Parameters.AddWithValue("@data", temp.ToString());
cmd.ExecuteNonQuery();
}
sw.Stop();
Console.WriteLine($"Adding {nbr} to MySql took {sw.ElapsedMilliseconds} ms");
sw.Reset();
阅读
沙发床:
IBucket bucket = await cluster.BucketAsync("halo");
IScope scope = bucket.Scope("myScope");
var collection = scope.Collection("myCollection");
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1000; i++)
{
string key = $"{r.Next(1, 100000)}";
var result = await collection.GetAsync(key);
}
sw.Stop();
Console.WriteLine($"Couchbase Q: {q}\t{sw.ElapsedMilliseconds}");
Redis:
Stopwatch sw = Stopwatch.StartNew();
using (var client = redisManager.GetClient())
{
for (int i = 0; i < nbr; i++)
{
client.Get<string>($"jobId:{r.Next(1, 100000)}");
}
}
sw.Stop();
Console.WriteLine($"Redis Q: {q}\t{sw.ElapsedMilliseconds}");
MySQL:
MySqlConnection mySqlConnection = new MySql.Data.MySqlClient.MySqlConnection("Server=localhost;Database=test;port=3306;User Id=root;password=root;");
mySqlConnection.Open();
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < nbr; i++)
{
MySqlCommand cmd = new MySql.Data.MySqlClient.MySqlCommand($"SELECT data FROM test WHERE Id='{r.Next(1, 100000)}'", mySqlConnection);
using MySqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
}
}
sw.Stop();
Console.WriteLine($"MySql Q: {q} \t{sw.ElapsedMilliseconds} ms");
sw.Reset();
沙发底座设置:
和
和存储桶的耐用性:
我只有 1 个节点(无集群),它在我的机器上是本地的,运行 Ryzen 3900x 12 核、M.2 SSD、Win10、32 GB RAM。
如果你做到了这一点,这里有一个包含我的基准代码的 GitHub 存储库: https://github.com/tedekeroth/CouchbaseTests
【问题讨论】:
-
Redis 和 Mysql 代码有助于确保进行公平比较。例如,是否使用了 REDIS 批量 API?
-
不,mysql和redis都是顺序插入,甚至没有使用Task.WhenAll,而且速度仍然非常快。根据要求,我也会更新代码。
-
@Ted 获取另一个数据点进行比较,看看使用 cbc-pillowfight 工具 (docs.couchbase.com/sdk-api/couchbase-c-client-2.4.8/…) 运行类似测试的结果会很有趣,该工具将位于 Couchbase 的 bin 目录中安装。
-
对不起,我直到现在才看到这条评论,很奇怪,这里没有“ping”。是的,这可能很有趣,但不幸的是,我已经“继续前进”并寻找其他解决方案。我希望这对其他人有所帮助。
-
@Ted 很公平。只是想让任何偶然发现这一点的人都知道,您所看到的时间比我们期望从 Couchbase 看到的要慢得多。我对您在其他地方的发现感到非常困惑,即并行执行插入并不比串行快多少。如果您有机会回到这一点,看看调整 SDK NumKvConnections 参数是否有帮助会很有趣。这控制了SDK到每个Key-Value节点的连接数,默认为1。在这样的批量加载场景中,它可以帮助提高吞吐量。
标签: mysql redis couchbase benchmarking aerospike