我做了一个小的基准测试来比较couchbase(在win中运行)与redis和mysql(编辑:添加了aerospeike进行测试)
我们正在将100000个json“文档”插入三个数据库/存储:
redis(只需插入,没有其他内容)
couchbase(内存中的临时存储桶,jobid上的json索引)
mysql(简单表;id(int)、数据(mediumtext)、id上的索引)
aerospike(内存存储)
json文件是67行,大约1800字节。
插入:
沙发床:60-100秒(编辑:似乎变化很大!)
mysql:30秒
redis:8秒
飞镖:71秒
阅读:我们阅读了1000次,我们做了10次,看看平均值。
couchbase:600-700毫秒用于1000个get(使用keyvalue操作,而不是查询api)。使用查询api,这大约需要1500毫秒)
mysql:90-100毫秒1000次
redis:50-60ms,1000次
aerospike:750ms,1000次
结论:couchbase似乎是最慢的(插入时间似乎变化很大),aerospeck也非常慢。这两个都使用内存存储(couchbase=>ephemeral bucket,aerospeike=>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
2条答案
按热度按时间x8goxv8g1#
我做了你的沙发床测试,把非沙发床的部分注解掉了。修复了从集合(mycollection)而不是jobcache中选择的查询,并删除了metrics选项。并在jobid上创建了一个索引。在上创建索引mybucket\u jobiddefault:mybucket.myscope.mycollection (jobid)它在19秒内插入100000个文档,kv平均获取146usec的文档,按jobid查询平均965usec。
这是在MacBookPro上的7.0Build3739上,cbserver在本地运行。
######################################################################
我有一个用于javasdk的小型loaddriver应用程序,它使用kvapi。它有4个线程,平均响应时间为54微秒,吞吐量为73238个请求/秒。它使用localhost上cb服务器上的travel样本桶。git@github.com:mikereiche/loaddriver.git
运行:秒:10,线程:4,超时:40000us,阈值:8000us请求/秒:0(最大值),强制gc间隔:0ms计数:729873,请求/秒:72987,最大值:2796us平均值:54us,聚合rq/秒:73238
对于查询api,我得到了以下速度慢了18倍的结果。
运行:秒:10,线程:4,超时:40000us,阈值:8000us请求/秒:0(最大值),强制gc间隔:0ms计数:41378,请求/秒:4137,最大值:12032us平均值:965us,聚合rq/秒:4144
woobm2wo2#
我必须亲自进行这样的比较才能做一个全面的调查,但有两件事很突出。
你的并行执行不是完全并行的。
async
方法同步运行到第一个等待,因此InsertAsync/GetAsync
在添加任务时,第一个等待是按顺序运行的,而不是并行运行的。couchbasenetclient在后台进行一些延迟连接设置,而您在timed部分要为此付出代价。取决于环境,包括ssl协商等,这可能是一个重要的初始延迟。
您可以通过使用
Task.Run
但您可能需要预先调整默认线程池大小。您可以通过对bucket执行至少一个操作(包括
bucket.WaitUntilReadyAsync()
)在定时部分之前。60秒的插入仍然看起来不正常。您使用了多少个节点和什么耐久性设置?