본문 바로가기
SingleStoreDB/엔지니어링

SingleStore vs MySQL vs PostgreSQL, 100M+ 레코드, 도커에서 누가 더 빠를까?

by 에이플랫폼 [Team SingleStore Korea] 2025. 5. 27.

안녕하세요 에이플랫폼 입니다.

오늘은 Docker 환경에서 SingleStore, Mysql, PostgreSQL을 밴치마킹 해보겠습니다.

현실적인 핀테크 스타일의 워크로드를 생성하고, 각 플랫폼이 과도한 조인, 롤링 윈도우 합계 및 핫 분석 쿼리를 어떻게 처리하는지 측정해보겠습니다.

현실적이고 동등한 입장을 유지하기 위해 테스트 중인 세 가지 플랫폼 모두에서 사용할 수 있는 프로젝트와 워크로드를 만들었습니다.

구축한 벤치마크 프로젝트는 Turborepo를 기반으로 하며 여러 애플리케이션과 패키지를 포함합니다.

프로젝트에는 아래의 내용이 포함됩니다.


응용 프로그램

  • ./apps/db  Docker 컨테이너를 실행하기 위한 애플리케이션입니다.
  • ./apps/data-generator Node.js 데이터를 생성하여 데이터베이스에 로드하고 인덱스를 생성하기 위한 응용 프로그램입니다.
  • ./apps/client Next.js 클라이언트를 시작하고 쿼리를 실행하는 응용 프로그램 입니다.

패키지

  • ./packages/singlestore SingleStore 이미지에 연결된 Drizzle 인스턴스
  • ./packages/mysql MySQL 이미지에 연결된 Drizzle 인스턴스
  • ./packages/postgres PostgreSQL 이미지에 연결된 Drizzle 인스턴스

Docker 이미지

  • SingleStore. ghcr.io/singlestore-labs/singlestoredb-dev:latest
  • MySQL. mysql:latest
  • Postgres. postgres:latest

이번 글의 밴치마크는 SingleStore Git hub의 docker-benchmarking-battle 저장소를 복제하고, README.md 를 따라 프로젝트를 로컬에서 실행할 수 있습니다.


밴치마킹에 사용한 데이터 스키마와 시나리오를 소개하겠습니다.

데이터 스키마

세 데이터베이스 모두 정확히 동일한 스키마와 데이터 볼륨을 공유합니다.

1개의 CSV 파일당 100만 개의 레코드가 포함되어 있습니다.

users 데이터 예시 (1,000,000 row, 1 csv)

1,Lew_McKenzie@gmail.com,Wallace Paucek,2025-05-23 05:27:13,2025-05-23 05:27:13
2,Kariane_Ebert@yahoo.com,Vivian Howell,2025-05-23 05:27:13,2025-05-23 05:27:13
3,Maximillia.Kassulke@gmail.com,Candace Jaskolski,2025-05-23 05:27:13,2025-05-23 05:27:13
...
999998,Demarco50@gmail.com,Mindy Gleichner,2025-05-23 05:27:13,2025-05-23 05:27:13
999999,Collin.Carroll@hotmail.com,Marie Ziemann,2025-05-23 05:27:13,2025-05-23 05:27:13
1000000,Bernadette_Barrows@hotmail.com,Patti Cartwright,2025-05-23 05:27:13,2025-05-23 05:27:13

accounts 데이터 예시

1,66579,854.43,2025-05-23 05:27:13,2025-05-23 05:27:13
2,37791,808.57,2025-05-23 05:27:13,2025-05-23 05:27:13
3,640582,315.94,2025-05-23 05:27:13,2025-05-23 05:27:13
...
9999998,385103,989.82,2025-05-23 05:27:13,2025-05-23 05:27:13
9999999,70981,632.24,2025-05-23 05:27:13,2025-05-23 05:27:13
10000000,290693,944.65,2025-05-23 05:27:13,2025-05-23 05:27:1

transactions 데이터 예시

1,9362328,6721922,1,3,412.51,2025-05-23 05:27:13
2,1914157,8069260,2,1,267.82,2025-05-23 05:27:13
3,6074342,1461115,1,2,429.78,2025-05-23 05:27:13
...
99999998,5199513,2180298,1,2,286.39,2025-05-23 05:27:13
99999999,2458298,3270926,2,2,645.69,2025-05-23 05:27:13
100000000,9600327,7657710,1,3,823.70,2025-05-23 05:27:13

 

밴치마크 시나리오

1. Total transaction volume (last 30 days)

첫번째로, 전체 시스템에서 지난 30일 이내에 이루어진 모든 성공한 트랜잭션의 합계를 계산하고,  transactions 및 transaction_statuses테이블을 조인하고, status = "success" 및 createdAt > NOW() - 30 days를 필터링합니다.

 

이러한 유형의 쿼리는 동적 시간 창에 대한 합계를 자주 계산해야 하는 재무 대시보드 및 수익 보고 도구에서 사용할 수 있습니다.

TypeScript를 사용하면 쿼리는 다음과 같습니다.

// ./packages/singlestore/transaction/get-sum.ts

export async function getTransactionsSum() 
{
  const cutoffDate = subDays(new Date(), 30);

  const result = await singlestore
    .select({ sum: sum(transactionsTable.amount) })
    .from(transactionsTable)
    .innerJoin(transactionStatusesTable, eq(transactionStatusesTable.id, transactionsTable.statusId))
    .where(and(gt(transactionsTable.createdAt, cutoffDate), eq(transactionStatusesTable.name, "success")));

  return result;
}

아래의 결과는 SingleStore공식 블로그에 올라온 결과 입니다.

2. Top transfer recipients

다음으로, 각 계정이 송금 받은 횟수를 계산하여 성공적인 송금의 가장 일반적인 수신자를 찾는 또 다른 쿼리를 살펴보고 transactions, transaction_types 및 transaction_statuses 테이블을 조인합니다 .

type = "transfer" 및 status = "success"에 대한 필터는 각 'accountIdTo'가 전송을 받은 횟수를 계산한 다음 transferCount를 기준으로 정렬됩니다.

 

이러한 유형의 쿼리는 핀테크 앱에서 VIP 수신자, 사기 패턴 또는 빈번한 비즈니스 수취인을 감지하는 데 유용할 수 있습니다.

TypeScript로 끓일 때 결과 쿼리는 다음과 같습니다.

// ./packages/singlestore/account/list-top-recipients.ts

export type ListTopRecipientsParams = {
  limit?: number;
};

export async function listTopRecipients(params: ListTopRecipientsParams) {
  const { limit = 10 } = params;

  const result = await singlestore
    .select({
      accountIdTo: transactionsTable.accountIdTo,
      transferCount: count(transactionsTable.id).as("transferCount"),
    })
    .from(transactionsTable)
    .innerJoin(transactionTypesTable, eq(transactionTypesTable.id, transactionsTable.typeId))
    .innerJoin(transactionStatusesTable, eq(transactionStatusesTable.id, transactionsTable.statusId))
    .where(and(eq(transactionTypesTable.name, "transfer"), eq(transactionStatusesTable.name, "success")))
    .groupBy(transactionsTable.accountIdTo)
    .orderBy(desc(sql`transferCount`))
    .limit(limit);

  return result;
}

아래의 결과는 SingleStore공식 블로그에 올라온 결과 입니다.

3. Total transaction volume (last 30 days)

마지막으로, 지난 7일 동안의 최근 트랜잭션을 검색하고 다중 테이블 조인을 사용하여 연결된 사용자 및 계정 정보를 포함하는 쿼리를 실행합니다.

사용자, 계정, 트랜잭션 및 transaction_types 테이블을 조인하여 사용자 이름, 계정 ID, 금액 및 트랜잭션 유형을 포함하여 지난 7일 동안의 트랜잭션을 검색합니다.

 

이 유형의 쿼리는 실시간 활동 피드 또는 최근 거래 페이지를 복제하며, 이는 뱅킹 앱에서 일반적이며 SingleStore의 스위트 스폿입니다.

쿼리를 TypeScript로 구문 분석하면 결과 코드는 다음과 같습니다.

// ./packages/singlestore/transaction/list-recent-with-info.ts

export async function listRecentTransactionsWithInfo() {
  const cutoffDate = subDays(new Date(), 7);

  const result = await singlestore
    .select({
      userId: usersTable.id,
      name: usersTable.name,
      accountId: accountsTable.id,
      amount: transactionsTable.amount,
      type: transactionTypesTable.name,
      createdAt: transactionsTable.createdAt,
    })
    .from(usersTable)
    .innerJoin(accountsTable, eq(accountsTable.userId, usersTable.id))
    .innerJoin(transactionsTable, eq(transactionsTable.accountIdFrom, accountsTable.id))
    .innerJoin(transactionTypesTable, eq(transactionTypesTable.id, transactionsTable.typeId))
    .where(gte(transactionsTable.createdAt, cutoffDate))
    .orderBy(desc(transactionsTable.createdAt))
    .limit(100);

  return result;
}

아래의 결과는 SingleStore공식 블로그에 올라온 결과 입니다.

직접 실행해보기

SingleStore Github: https://github.com/singlestore-labs/demo-docker-benchmarking-battle

 

GitHub - singlestore-labs/demo-docker-benchmarking-battle

Contribute to singlestore-labs/demo-docker-benchmarking-battle development by creating an account on GitHub.

github.com

위의 깃허브 주소에서 레포지토리를 복제후 ReadMe를 따라서 직접 로컬에서 실행해 보실 수 있습니다.

 

그리고 여기에서 직접 라이브 데모를 실행해 볼 수 있습니다.

https://demo-docker-benchmarking-battle.vercel.app/


이번 벤치마크 테스트 결과를 통해 SingleStore탁월한 성능확장성을 갖춘 데이터베이스임을 다시 한번 확인할 수 있었습니다.

대량의 데이터빠르게 처리하고, 효율적인 운영을 원하는 기업이라면 SingleStore최고의 선택이 될 것입니다.

앞으로도 더욱 강력한 기능최적화된 성능을 제공할 SingleStore의 발전을 기대해주세요!