<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yaroslav Demenskyi</title>
    <description>The latest articles on DEV Community by Yaroslav Demenskyi (@ydemenskyi30).</description>
    <link>https://dev.to/ydemenskyi30</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3130262%2F39ec96ea-0d9b-4e35-815f-ee350b132988.JPG</url>
      <title>DEV Community: Yaroslav Demenskyi</title>
      <link>https://dev.to/ydemenskyi30</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ydemenskyi30"/>
    <language>en</language>
    <item>
      <title>How I Got x311 Faster Analytics on 110M Rows</title>
      <dc:creator>Yaroslav Demenskyi</dc:creator>
      <pubDate>Tue, 06 May 2025 18:29:04 +0000</pubDate>
      <link>https://dev.to/ydemenskyi30/how-i-got-x116-faster-analytics-on-110m-rows-26db</link>
      <guid>https://dev.to/ydemenskyi30/how-i-got-x116-faster-analytics-on-110m-rows-26db</guid>
      <description>&lt;p&gt;Hey everyone! I recently got fed up with waiting minutes for simple analytics queries to finish, so I threw together &lt;a href="http://demo-docker-benchmarking-battle.vercel.app" rel="noopener noreferrer"&gt;a little demo&lt;/a&gt; to see how &lt;a href="https://www.singlestore.com/" rel="noopener noreferrer"&gt;SingleStore&lt;/a&gt;, &lt;a href="https://www.mysql.com/" rel="noopener noreferrer"&gt;MySQL&lt;/a&gt;, and &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt; stack up against each other on a &lt;strong&gt;110 million‑row&lt;/strong&gt; banking transactions dataset.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Spoiler:&lt;/em&gt; the results surprised me - and I think they’ll surprise you too.&lt;/p&gt;

&lt;p&gt;In this post I’ll walk you through:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The setup I used&lt;/li&gt;
&lt;li&gt;The queries I ran and what happened&lt;/li&gt;
&lt;li&gt;How to spin it up on your machine&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  My Setup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Docker Images:

&lt;ul&gt;
&lt;li&gt;SingleStore Free Dev: &lt;a href="https://github.com/singlestore-labs/singlestoredb-dev-image" rel="noopener noreferrer"&gt;&lt;code&gt;ghcr.io/singlestore-labs/singlestoredb-dev:latest&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;MySQL: &lt;code&gt;mysql:latest&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;PostgreSQL: &lt;code&gt;postgres:latest&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Platforms: &lt;strong&gt;three&lt;/strong&gt; &lt;code&gt;t2.large&lt;/code&gt; EC2 instances - one for each database&lt;/li&gt;

&lt;li&gt;Dataset: &lt;strong&gt;110 million&lt;/strong&gt; synthetic “banking transactions”&lt;/li&gt;

&lt;li&gt;Code: &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; + &lt;a href="https://orm.drizzle.team/" rel="noopener noreferrer"&gt;Drizzle ORM&lt;/a&gt; application (&lt;a href="https://github.com/singlestore-labs/demo-docker-benchmarking-battle" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;)&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Queries
&lt;/h2&gt;

&lt;p&gt;I tested three common analytics patterns:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sum of all successful transactions in the last 30 days&lt;/li&gt;
&lt;li&gt;Top transfer recipients by count&lt;/li&gt;
&lt;li&gt;Recent transactions joined with user and account info&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each query ran against all three databases, and I recorded both the absolute time and the relative speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Total Transaction Volume (30 days)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;SingleStore: 923 ms&lt;/li&gt;
&lt;li&gt;Postgres: 1m 3.3  s&lt;/li&gt;
&lt;li&gt;MySQL: &lt;strong&gt;timed out&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That meant &lt;strong&gt;SingleStore&lt;/strong&gt; was about &lt;strong&gt;x68 faster&lt;/strong&gt; than PostgreSQL - and MySQL couldn't finish in 5 minutes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzktfc1wzy1o61zr21mrm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzktfc1wzy1o61zr21mrm.png" alt="Query-1" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Top Transfer Recipients
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;SingleStore: 3.8  s&lt;/li&gt;
&lt;li&gt;Postgres: 1m 19.2  s&lt;/li&gt;
&lt;li&gt;MySQL: &lt;strong&gt;timed out&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here, &lt;strong&gt;SingleStore&lt;/strong&gt; was roughly &lt;strong&gt;x20 faster&lt;/strong&gt; than PostgreSQL - and MySQL couldn’t finish in 5 minutes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft61rlkg4cjykxkxulh9h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft61rlkg4cjykxkxulh9h.png" alt="Query-2" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Join Users, Accounts &amp;amp; Transactions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;SingleStore: 206 ms&lt;/li&gt;
&lt;li&gt;Postgres: 1m 4.1 s&lt;/li&gt;
&lt;li&gt;MySQL: &lt;strong&gt;timed out&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;SingleStore&lt;/strong&gt; handled the multi‑table join roughly &lt;strong&gt;x311 faster&lt;/strong&gt; than PostgreSQL - and MySQL couldn’t finish the query in 5 minutes again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujzd9q5kyii424p08nsn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujzd9q5kyii424p08nsn.png" alt="Query-3" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What the numbers tell us
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://portal.singlestore.com/intention/cloud?utm_source=yaroslav&amp;amp;utm_medium=devto&amp;amp;utm_campaign=general-technical&amp;amp;utm_content=database-benchmark-mysql-vs-postgresql-vs-singlestore-performance-in-docker-100m-records" rel="noopener noreferrer"&gt;SingleStore&lt;/a&gt; consistently outperformed both MySQL and PostgreSQL in query latency and sustained throughput under identical conditions. That makes it a strong candidate for real‑time analytics on operational data - whether you’re driving dashboards, powering machine‑learning features, or simply need to crunch large datasets at speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;To run this demo locally, just follow the instructions in the &lt;a href="https://github.com/singlestore-labs/demo-docker-benchmarking-battle?tab=readme-ov-file#demo-docker-benchmarking-battle" rel="noopener noreferrer"&gt;GitHub repository.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this benchmark, I ran each database engine straight “out of the box” - &lt;strong&gt;no extra tuning&lt;/strong&gt;, no custom extensions, just the default Docker images. You can check out the exact setup in my Docker Compose file &lt;a href="https://github.com/singlestore-labs/demo-docker-benchmarking-battle/blob/main/apps/db/docker-compose.yml" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All three containers lived side by side on identical AWS EC2 &lt;code&gt;t2.large&lt;/code&gt; instances. I generated one 110 million‑row synthetic banking‑transactions dataset and loaded it into each database exactly the same way. If you’re curious about the details, the scripts are all open source:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/singlestore-labs/demo-docker-benchmarking-battle/blob/main/apps/data-generator/generate.ts" rel="noopener noreferrer"&gt;Data generation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/singlestore-labs/demo-docker-benchmarking-battle/blob/main/apps/data-generator/load.ts" rel="noopener noreferrer"&gt;Data loading&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/singlestore-labs/demo-docker-benchmarking-battle/blob/main/apps/data-generator/indexes.ts" rel="noopener noreferrer"&gt;Index creation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For all my queries and connections, I relied on Drizzle ORM - no hand‑rolled code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/singlestore-labs/demo-docker-benchmarking-battle/tree/main/packages/mysql" rel="noopener noreferrer"&gt;MySQL code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/singlestore-labs/demo-docker-benchmarking-battle/tree/main/packages/postgres" rel="noopener noreferrer"&gt;PostgreSQL code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/singlestore-labs/demo-docker-benchmarking-battle/tree/main/packages/singlestore" rel="noopener noreferrer"&gt;SingleStore code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to see these performance gains on your own workloads &lt;a href="https://portal.singlestore.com/intention/cloud?utm_source=yaroslav&amp;amp;utm_medium=devto&amp;amp;utm_campaign=general-technical&amp;amp;utm_content=database-benchmark-mysql-vs-postgresql-vs-singlestore-performance-in-docker-100m-records" rel="noopener noreferrer"&gt;give SingleStore a try&lt;/a&gt; and let me know what you find.&lt;/p&gt;

&lt;p&gt;Also, if you spot anything I’ve overlooked or have ideas to squeeze even more performance out of the setup, please drop a comment - I’d love to learn from you.&lt;/p&gt;

&lt;p&gt;Thank you for your attention!&lt;/p&gt;

</description>
      <category>database</category>
      <category>performance</category>
      <category>singlestore</category>
      <category>benchmark</category>
    </item>
  </channel>
</rss>
