Couchbase 벤치 마크는 매우 느린 INSERT 및 GET (KeyValue 작업 사용)을 보여줍니다. 지속 된 MySQL 데이터보다 느림
Couchbase (Win에서 실행)를 Redis 및 MySql과 비교하기 위해 작은 벤치 마크 테스트를 수행했습니다 (편집 : 테스트에 Aerospike 추가).
3 개의 db / store에 100,000 개의 JSON "문서"를 삽입합니다.
- Redis (삽입 만하면됩니다. 다른 것은 없습니다)
- Couchbase (메모리 내 임시 버킷, JobId의 JSON 인덱스)
- MySql (단순 테이블, Id (int), 데이터 (MediumText), Id에 대한 인덱스)
- Aerospike (메모리 내 저장소)
JSON 파일은 약 1800 바이트 인 67 줄입니다.
끼워 넣다:
- Couchbase : 60-100 초 (편집 : 상당히 달라진 것 같습니다!)
- MySql : 30 초
- Redis : 8 초
- 에어로 스파이크 : 71 초
읽기 : 우리는 1000 번 읽고 있고, 우리는 이것을 10 번 읽고 평균을 봅니다.
- Couchbase : 1000 개 GET의 경우 600-700ms (Query API가 아닌 KeyValue 작업을 사용합니다. Query API를 사용하면 약 1500ms가 걸립니다.)
- MySql : 1000 GET의 경우 90-100ms
- Redis : 1000 개 GET의 경우 50-60ms
- Aerospike : 1000 GET의 경우 750ms
결론 : Couchbase가 가장 느리게 보이며 (INSERT 시간이 많이 달라 보임) Aerospike도 매우 느립니다. 둘 다 인 메모리 스토리지를 사용하고 있습니다 (Couchbase => Ephemeral 버킷, Aerospike => 스토리지 엔진 메모리).
질문 : Couchbase에서 인 메모리 쓰기 및 읽기가 일반 MySQL (SSD에서)을 사용하는 것보다 느린 이유는 무엇입니까?
암호
참고 : Task.WhenAll을 사용하거나 각 호출을 기다리는 것은 차이가 없습니다.
끼워 넣다
Couchbase :
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();
읽다
Couchbase :
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();
Couchbase 설정 :

과

및 버킷 내구성 :

노드 1 개 (클러스터 없음) 만 있고 내 컴퓨터에 로컬이며 Ryzen 3900x 12 코어, M.2 SSD, Win10, 32GB RAM을 실행합니다.
지금까지 만든 경우 내 벤치 마크 코드가있는 GitHub 저장소가 있습니다. https://github.com/tedekeroth/CouchbaseTests
답변
나는 CouchbaseTests를 가져 와서 비 Couchbase 비트를 주석 처리했습니다. jobcache 대신 컬렉션 (myCollection)에서 선택하도록 쿼리를 수정하고 Metrics 옵션을 제거했습니다. 그리고 JobId에 인덱스를 생성했습니다. 기본값에 mybucket_JobId 인덱스 생성 : myBucket.myScope.myCollection (JobId) 100,000 개의 문서를 19 초에 삽입하고 kv-fetch는 평균 146 usec의 문서를 가져오고 평균 965 usec의 JobId로 쿼리합니다.
Couchbase Q: 0 187
Couchbase Q: 1 176
Couchbase Q: 2 143
Couchbase Q: 3 147
Couchbase Q: 4 140
Couchbase Q: 5 138
Couchbase Q: 6 136
Couchbase Q: 7 139
Couchbase Q: 8 125
Couchbase Q: 9 129
average et: 146 ms per 1000 -> 146 usec / request
Couchbase Q: 0 1155
Couchbase Q: 1 1086
Couchbase Q: 2 1004
Couchbase Q: 3 901
Couchbase Q: 4 920
Couchbase Q: 5 929
Couchbase Q: 6 912
Couchbase Q: 7 911
Couchbase Q: 8 911
Couchbase Q: 9 927
average et: 965 ms per 1000 -> 965 usec / request. (coincidentally exactly the same as with the java api).
이것은 cbserver가 로컬에서 실행되는 Mac Book Pro의 7.0 빌드 3739에있었습니다.
################################################# ####################
kv api를 사용하는 Java sdk 용 작은 LoadDriver 응용 프로그램이 있습니다. 스레드가 4 개인 경우 평균 응답 시간은 54 마이크로 초이고 처리량은 73238 개 / 초입니다. localhost의 cb 서버에서 travel-sample 버킷을 사용합니다. [email protected] : 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
전체 조사를 수행하려면 이러한 비교를 직접 실행해야하지만 두 가지가 두드러집니다.
병렬 실행은 완전히 병렬이 아닙니다.
async
메서드는 첫 번째 대기까지 동 기적으로 실행되므로 첫 번째 대기InsertAsync/GetAsync
이전의 모든 코드는 병렬이 아닌 작업을 추가 할 때 순차적으로 실행됩니다.CouchbaseNetClient는 백그라운드에서 지연 연결 설정을 수행하며 시간 제한 섹션에서 해당 비용을 지불합니다. SSL 협상 등을 포함한 환경에 따라 이는 상당한 초기 대기 시간이 될 수 있습니다.
을 사용 Task.Run
하여 작업을 시작 하면 잠재적으로 첫 번째 문제를 해결할 수 있지만 기본 스레드 풀 크기를 미리 조정해야 할 수도 있습니다.
bucket.WaitUntilReadyAsync()
시간이 지정된 섹션 이전에 버킷에서 하나 이상의 작업 (포함 ) 을 수행하여 두 번째 문제를 해결할 수 있습니다 .
삽입물의 60 초는 여전히 비정상적으로 보입니다. 얼마나 많은 노드와 어떤 내구성 설정을 사용하고 있습니까?