<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Wirekite Benchmarks]]></title><description><![CDATA[Everything Wirekite. And how it can help you get the data where you want it to be, and fast.]]></description><link>https://benchmarks.wirekite.io</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1740293635194/2c293aff-4b44-4821-8d94-bbd1c2c199e8.png</url><title>Wirekite Benchmarks</title><link>https://benchmarks.wirekite.io</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 15 Apr 2026 18:42:22 GMT</lastBuildDate><atom:link href="https://benchmarks.wirekite.io/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Oracle to Google AlloyDB PostgreSQL - 1B rows]]></title><description><![CDATA[Google AlloyDB is a cluster-packaged cloud-hosted PostgreSQL-compatible database engine that uses Google’s cloud storage for its storage world. A more in-depth overview of AlloyDB can be found here.
For our benchmark, we used a single-node “cluster”,...]]></description><link>https://benchmarks.wirekite.io/oracle-to-google-alloydb-postgresql-1b-rows</link><guid isPermaLink="true">https://benchmarks.wirekite.io/oracle-to-google-alloydb-postgresql-1b-rows</guid><category><![CDATA[Benchmark]]></category><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Mon, 11 Aug 2025 19:45:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754954603175/2704883b-7558-4327-b1ae-be1d5743b9ac.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Google AlloyDB is a cluster-packaged cloud-hosted PostgreSQL-compatible database engine that uses Google’s cloud storage for its storage world. A more in-depth overview of AlloyDB can be found <a target="_blank" href="https://cloud.google.com/alloydb/docs/overview">here</a>.</p>
<p>For our benchmark, we used a single-node “cluster”, with the node’s compute instance specified as a Google N2-Standard-64 host. We used the same type of compute instance - N2-Standard-64 - on the Oracle extraction side.</p>
<p>After adding support for “local” file loading to the Wirekite PostgreSQL data loader - this change was needed to load any PostgreSQL managed-cloud target - we were able to use it without additional changes to load to AlloyDB.</p>
<h1 id="heading-benchmark-details">Benchmark Details</h1>
<p>This is a pure “how fast can Wirekite load AlloyDB” benchmark. We used our 1 billion row “firenibble” table, extracted from Oracle and loaded to AlloyDB, as the basis for this benchmark.</p>
<h2 id="heading-table">Table</h2>
<p>We used our standard firenibble table, with the Oracle table definition shown below.</p>
<p>The table has 16 columns, one of them is a numeric primary key, few columns are numbers of various shapes and sizes, few strings and few dates. This makes the table pretty simple to be absorbed by most databases.</p>
<p>The table also has 1 billion rows.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> app_db.firenibble (
    f0    <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>)    <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
    f1    <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>),
    f2    <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>),
    f3    <span class="hljs-built_in">int</span>,
    f4    <span class="hljs-built_in">float</span>,
    f5    <span class="hljs-built_in">float</span>,
    f6    <span class="hljs-built_in">float</span>,
    f7    <span class="hljs-built_in">float</span>,
    f8    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    f9    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    f10    <span class="hljs-built_in">date</span>,
    f11    <span class="hljs-built_in">date</span>,
    f12    <span class="hljs-built_in">date</span>,
    f13    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    f14    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    f15    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    PRIMARY <span class="hljs-keyword">KEY</span> (f0)
);
</code></pre>
<p>The 1 billion rows.</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">select</span> <span class="hljs-keyword">count</span>(*) <span class="hljs-keyword">from</span> app_db.firenibble;

  COUNT(*)
<span class="hljs-comment">----------</span>
1000000000

1 row selected.

SQL&gt;
</code></pre>
<h2 id="heading-oracle">Oracle</h2>
<p>Our Oracle environment is a GCP N2-standard-64 host in the us-central1 region. The host OS is Linux RHEL8 (Redhat) and Oracle is Oracle version 19c.</p>
<h2 id="heading-benchmark-run">Benchmark Run</h2>
<p>For AlloyDB, we created a single AlloyDB node configured as an N2-Standard-64 host. The cluster and node are in the GCP us-central1 region - same as our Oracle world - to minimize network lag.</p>
<p>We ran with 64 extraction threads.</p>
<p>One observation is in test runs against AlloyDB, we reached 100% CPU utilization, but at 64 threads, we only reached 75% CPU utilization. We believe we saturated the network between our Oracle compute instance and the AlloyDB node at about 48 threads.</p>
<p>And this was the result. It took <strong>24 minutes 35 secs</strong> to move 1 billion rows from Oracle to AlloyDB. The Oracle extract alone took <strong>21 min 25 secs</strong>, so the load to AlloyDB lagged about 2 min 50 secs behind the extract from Oracle. The transfer rate works out to <strong>677,966 rows per second</strong>.</p>
<p>Here’s the confirmation queries run on AlloyDB:</p>
<pre><code class="lang-sql">wirekite=&gt; <span class="hljs-keyword">select</span> <span class="hljs-keyword">now</span>();
             now
<span class="hljs-comment">------------------------------</span>
 2025-08-10 20:10:29.26418+00
(1 row)

wirekite=&gt; <span class="hljs-keyword">select</span> <span class="hljs-keyword">sum</span>(mark::<span class="hljs-built_in">int</span>) <span class="hljs-keyword">from</span> wirekite_progress <span class="hljs-keyword">where</span> mark::<span class="hljs-built_in">int</span> &lt;&gt; <span class="hljs-number">0</span>;
    sum
<span class="hljs-comment">------------</span>
 1000000000
(1 row)

wirekite=&gt; <span class="hljs-keyword">select</span> <span class="hljs-keyword">count</span>(*) <span class="hljs-keyword">from</span> firenibble;
   count
<span class="hljs-comment">------------</span>
 1000000000
(1 row)
</code></pre>
]]></content:encoded></item><item><title><![CDATA[PostgreSQL to Snowflake - 1B rows - 89x Faster]]></title><description><![CDATA[So we did our first benchmark and we are thrilled to share the results. We chose to compare our benchmark with Airbyte since that is one of the most recognized data migration enterprise software out there.
This was inspired from a benchmark that Airb...]]></description><link>https://benchmarks.wirekite.io/postgres-to-snowflake-1b-rows-89-x-faster</link><guid isPermaLink="true">https://benchmarks.wirekite.io/postgres-to-snowflake-1b-rows-89-x-faster</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Sun, 08 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742361687647/2d806a63-e3a8-4177-a816-ef292dd77da4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So we did our first benchmark and we are thrilled to share the results. We chose to compare our benchmark with Airbyte since that is one of the most recognized data migration enterprise software out there.</p>
<p>This was inspired from a benchmark that Airbyte published - <a target="_blank" href="https://airbyte.com/blog/postgres-replication-performance-benchmark-airbyte-vs-fivetran">https://airbyte.com/blog/postgres-replication-performance-benchmark-airbyte-vs-fivetran</a>.</p>
<h1 id="heading-benchmark-details">Benchmark Details</h1>
<h2 id="heading-table">Table</h2>
<p>As you can see we used the same table that Airbyte used. It has a numeric primary key column, some number columns, some string columns and some date columns. This fits nicely with most databases.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> firenibble
(
    f0 <span class="hljs-built_in">BIGINT</span> PRIMARY <span class="hljs-keyword">KEY</span> <span class="hljs-keyword">GENERATED</span> <span class="hljs-keyword">ALWAYS</span> <span class="hljs-keyword">AS</span> <span class="hljs-keyword">IDENTITY</span>,
    f1 <span class="hljs-built_in">BIGINT</span>,
    f2 <span class="hljs-built_in">BIGINT</span>,
    f3 <span class="hljs-built_in">INTEGER</span>,
    f4 <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span>,
    f5 <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span>,
    f6 <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span>,
    f7 <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span>,
    f8 <span class="hljs-built_in">VARCHAR</span> <span class="hljs-keyword">COLLATE</span> pg_catalog.<span class="hljs-string">"default"</span>,
    f9 <span class="hljs-built_in">VARCHAR</span> <span class="hljs-keyword">COLLATE</span> pg_catalog.<span class="hljs-string">"default"</span>,
    f10 <span class="hljs-built_in">DATE</span>,
    f11 <span class="hljs-built_in">DATE</span>,
    f12 <span class="hljs-built_in">DATE</span>,
    f13 <span class="hljs-built_in">VARCHAR</span> <span class="hljs-keyword">COLLATE</span> pg_catalog.<span class="hljs-string">"default"</span>,
    f14 <span class="hljs-built_in">VARCHAR</span> <span class="hljs-keyword">COLLATE</span> pg_catalog.<span class="hljs-string">"default"</span>,
    f15 <span class="hljs-built_in">VARCHAR</span> <span class="hljs-keyword">COLLATE</span> pg_catalog.<span class="hljs-string">"default"</span>
) <span class="hljs-keyword">tablespace</span> <span class="hljs-keyword">benchmark</span> ;
</code></pre>
<p>And here’s the 1 billion rows. The query to do a count takes a very long time.</p>
<pre><code class="lang-sql">wirekite=<span class="hljs-comment"># select count(*) from firenibble;</span>
   count
<span class="hljs-comment">------------</span>
 1000000000
(1 row)
</code></pre>
<h2 id="heading-machine-configurations">Machine Configurations</h2>
<p>For Postgres we created an <strong>n2-standard-64</strong> GCP instance with all the standard configurations - 64 CPU’s and 256 GB RAM in the us-central region.</p>
<p>For Snowflake we created a <strong>Large</strong> size warehouse with <strong>Standard Type</strong> also in the us-central1 region to minimize the network distance.</p>
<h2 id="heading-airbyte-run">Airbyte Run</h2>
<p>We created the firenibble table with various sizes to get the sense of how airbyte functions. We did Full Refresh Overwrite and made sure the table did not exist in the target.</p>
<p>We tried a bunch of runs. Some failed for various reasons. It is frustrating when we saw the run failed at 975 million rows.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741911316614/225a1d6d-04c1-40bd-b89f-e7806d85e814.png" alt class="image--center mx-auto" /></p>
<p>But then it succeeded !!</p>
<p>1 billion rows migrated in <strong>12 hours 6 minutes and 29 seconds</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741913449147/1dcc31a2-3d1c-4d35-a569-cad6a192137e.png" alt class="image--center mx-auto" /></p>
<p>Execution logs and details as reported by Airbyte.</p>
<pre><code class="lang-c"><span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-08</span> <span class="hljs-number">19</span>:<span class="hljs-number">21</span>:<span class="hljs-number">20</span> info sync summary: {
  <span class="hljs-string">"status"</span> : <span class="hljs-string">"completed"</span>,
  <span class="hljs-string">"recordsSynced"</span> : <span class="hljs-number">1000000000</span>,
  <span class="hljs-string">"bytesSynced"</span> : <span class="hljs-number">439710415164</span>,
  <span class="hljs-string">"startTime"</span> : <span class="hljs-number">1741418118670</span>,
  <span class="hljs-string">"endTime"</span> : <span class="hljs-number">1741461680232</span>,
  <span class="hljs-string">"totalStats"</span> : {
    <span class="hljs-string">"bytesCommitted"</span> : <span class="hljs-number">439710415164</span>,
    <span class="hljs-string">"bytesEmitted"</span> : <span class="hljs-number">439710415164</span>,
    <span class="hljs-string">"destinationStateMessagesEmitted"</span> : <span class="hljs-number">100000</span>,
    <span class="hljs-string">"destinationWriteEndTime"</span> : <span class="hljs-number">1741461680072</span>,
    <span class="hljs-string">"destinationWriteStartTime"</span> : <span class="hljs-number">1741418118737</span>,
    <span class="hljs-string">"meanSecondsBeforeSourceStateMessageEmitted"</span> : <span class="hljs-number">3</span>,
    <span class="hljs-string">"maxSecondsBeforeSourceStateMessageEmitted"</span> : <span class="hljs-number">100000</span>,
    <span class="hljs-string">"maxSecondsBetweenStateMessageEmittedandCommitted"</span> : <span class="hljs-number">68</span>,
    <span class="hljs-string">"meanSecondsBetweenStateMessageEmittedandCommitted"</span> : <span class="hljs-number">48</span>,
    <span class="hljs-string">"recordsEmitted"</span> : <span class="hljs-number">1000000000</span>,
    <span class="hljs-string">"recordsCommitted"</span> : <span class="hljs-number">1000000000</span>,
    <span class="hljs-string">"recordsFilteredOut"</span> : <span class="hljs-number">0</span>,
    <span class="hljs-string">"bytesFilteredOut"</span> : <span class="hljs-number">0</span>,
    <span class="hljs-string">"replicationEndTime"</span> : <span class="hljs-number">1741461680087</span>,
    <span class="hljs-string">"replicationStartTime"</span> : <span class="hljs-number">1741418118670</span>,
    <span class="hljs-string">"sourceReadEndTime"</span> : <span class="hljs-number">1741460800423</span>,
    <span class="hljs-string">"sourceReadStartTime"</span> : <span class="hljs-number">1741418118738</span>,
    <span class="hljs-string">"sourceStateMessagesEmitted"</span> : <span class="hljs-number">100000</span>
  }
</code></pre>
<h2 id="heading-wirekite-run">Wirekite Run</h2>
<p>Same Postgres instance. Same Snowflake instance. Same table. Same data.</p>
<p>1 billion rows were migrated in <strong>8 minutes 9 seconds</strong>.</p>
<pre><code class="lang-c"><span class="hljs-meta"># cat wirekite.log | grep -E <span class="hljs-meta-string">'START|FINISH|ELAPSED'</span></span>
START: Fri Mar <span class="hljs-number">14</span> <span class="hljs-number">03</span>:<span class="hljs-number">54</span>:<span class="hljs-number">04</span> UTC <span class="hljs-number">2025</span>
FINISH: Fri Mar <span class="hljs-number">14</span> <span class="hljs-number">04</span>:<span class="hljs-number">02</span>:<span class="hljs-number">13</span> UTC <span class="hljs-number">2025</span>
ELAPSED: <span class="hljs-number">0</span> hrs <span class="hljs-number">8</span> min <span class="hljs-number">9</span> sec
</code></pre>
<p>And here’s the table in Snowflake.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741926214257/173a6a99-29ee-4bd6-9fae-6b3d15b55971.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Oracle to Snowflake - 10 million ops (inserts + updates + deletes) - 6 mins 7 secs]]></title><description><![CDATA[So we set up a Change Data Capture replication pipeline from Oracle to Snowflake and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark
Benchmark Details
The most impor...]]></description><link>https://benchmarks.wirekite.io/oracle-to-snowflake-10-million-ops-inserts-updates-deletes-6-mins-7-secs</link><guid isPermaLink="true">https://benchmarks.wirekite.io/oracle-to-snowflake-10-million-ops-inserts-updates-deletes-6-mins-7-secs</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Sun, 08 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747850673038/06660bc9-5352-4f29-a0c8-9fd63169c0b0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So we set up a Change Data Capture replication pipeline from Oracle to Snowflake and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark</p>
<h2 id="heading-benchmark-details">Benchmark Details</h2>
<p>The most important decision here was to determine how to do a replication benchmark, specifically what constitutes a typical load profile of an OLTP database. We realized that a typical OLTP database has the following characteristics</p>
<ul>
<li><p>It has multiple tables.</p>
</li>
<li><p>It has some inserts.</p>
</li>
<li><p>It has somewhat more updates.</p>
</li>
<li><p>It has some deletes.</p>
</li>
<li><p>It has small transactions with lot of commits, mostly single row operations and commits.</p>
</li>
</ul>
<p>Given the above characteristics we decided on doing the following for the benchmark.</p>
<ul>
<li><p>We will have 10 tables.</p>
</li>
<li><p>We will have 2 million single row inserts.</p>
</li>
<li><p>We will have 6 million single row updates.</p>
</li>
<li><p>We will have 2 million single row deletes.</p>
</li>
<li><p>We will have auto commit on, causing all the above operations to have corresponding commit.</p>
</li>
</ul>
<h3 id="heading-table-structure">Table Structure</h3>
<p>We will have 10 tables called firenibble 1 to 10.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> app_db.firenibble1 (
  f0 <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  f1 <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>) ,
  f2 <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>) ,
  f3 <span class="hljs-built_in">int</span> ,
  f4 <span class="hljs-built_in">float</span> ,
  f5 <span class="hljs-built_in">float</span> ,
  f6 <span class="hljs-built_in">float</span> ,
  f7 <span class="hljs-built_in">float</span> ,
  f8 <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>) ,
  f9 <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>) ,
  f10 <span class="hljs-built_in">date</span> ,
  f11 <span class="hljs-built_in">date</span> ,
  f12 <span class="hljs-built_in">date</span> ,
  f13 <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>) ,
  f14 <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>) ,
  f15 <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>) ,
  primary <span class="hljs-keyword">key</span> (f0)
);
</code></pre>
<h2 id="heading-insert">Insert</h2>
<p>Insert will essentially be new primary key insert.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h2 id="heading-update">Update</h2>
<p>Update will be updating of two columns on a primary key value.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">update</span> firenibble1 <span class="hljs-keyword">set</span> f2 = <span class="hljs-number">280396830734761092</span>, f9 = <span class="hljs-string">'n6ChQjN9dfxIl6nc6SNgIzSahfeXfAef'</span> <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h2 id="heading-delete">Delete</h2>
<p>Delete will be essentially a primary key delete.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">delete</span> <span class="hljs-keyword">from</span> firenibble1 <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h3 id="heading-dml-operations-sequence">DML Operations Sequence</h3>
<p>Then came the question of how do we order the load so that we can rerun the load over and over again and never have to clean up the previous load. So we decided that the load will be such that we will start with 0 rows in all 10 tables, do a bunch of inserts, do a bunch of updates, do a bunch of deletes and end up with 0 rows in all tables. This kept the load and the tables rather clean.</p>
<p>So the exact sequence will look like this. I know we could have been more granular mixing the inserts, updates and deletes even more, and as we do more benchmarks we might try that strategy but for starters this looked pretty good. Also we wanted to see how our replication performed with large number of insert only, update only and delete only loads. Also note that there is no relationships between the load and the archive logs, in the sense there is no alter system switch logfile happening anywhere causing the inserts, updates and deletes to cross binary log boundaries.</p>
<ol>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes</p>
</li>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes.</p>
</li>
</ol>
<p>We will also makes sure that all inserts, updates and deletes happen on 10 tables in a sequence so that the operations are granularily staggered over all tables and not contiguous on one table and the next. Which means, the inserts look like this (and so does the updates and deletes).</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble2 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble3 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble4 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble5 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble6 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble7 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble8 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble9 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble10 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h3 id="heading-benchmark-sequence">Benchmark Sequence</h3>
<p>A choice we had was to make was do one of the following</p>
<ol>
<li><p>Have the wirekite replication running. Run the load and wait for the last event of the load to appear on the target. Measure the time between when the load started and the last event appeared.</p>
</li>
<li><p>Run the load and note down the binlog number and position at which the load started and wait for the load to finish. Now start the wirekite replication from the starting binlog number and position and wait for the last event of the load to appear on the target. Measure the time between when the wirekite replication started and the last event appeared on the target.</p>
</li>
</ol>
<p>We decided to go with option 2. The primary reason being that in option 1 wirekite replication was waiting for the events to finish successfully on the database, and essentially we were not only benchmarking wirekite, but also the database, with the boundaries between the two completely blurred. So we preferred the pre-loaded database with the changes, so that we are only benchmarking wirekite and nothing else.</p>
<h2 id="heading-machine-configuration">Machine Configuration</h2>
<p>For Oracle we created an <strong>n2-standard-16</strong> GCP instance with all the standard configurations - 8 CPU’s and 64 GB RAM in the us-central region. We installed Ubuntu version 24 and Oracle version 19. Our archive log size was 330 MB.</p>
<p>For Snowflake we created a <strong>Large</strong> Size Warehouse with <strong>Standard Type</strong> also in the us-central1 region to minimize the network distance.</p>
<p>We have been using the same configurations for all our benchmarks so that we are comparing apples and apples.</p>
<h2 id="heading-oracle-run">Oracle Run</h2>
<p>We wanted to mention this a bit to talk about the uphill challenge that was getting oracle to be up and running and importing data into it.</p>
<p>First it was the installation which we thought we could do using the command line. But once we started playing with response files we realized it was almost impossible to get the right response file. There are hundreds of options that go in oracle response file which makes it impossible to find the right combination. We kept on running into errors.</p>
<p>So we decided to use the GUI. Getting X11 forwarding working took some time (that DISPLAY variable) but we were able to do it. But then Oracle GUI would show up with buttons missing from it - <a target="_blank" href="https://forums.oracle.com/ords/apexds/post/19c-runinstaller-shows-blank-screen-for-15-minutes-9680">https://forums.oracle.com/ords/apexds/post/19c-runinstaller-shows-blank-screen-for-15-minutes-9680</a>.</p>
<p>We realized that some given environment variable has to be set to make sure the GUI runs as intended. Once we did that we got the right GUI and got Oracle installed.</p>
<p>And then came the challenge of configuring the database with sensible values so that you can actually load a reasonable amount of data in it. We had to configure</p>
<ul>
<li><p>Configure and start the LISTENER. Understand LISTENER.ORA and TNSNAMES.ORA.</p>
</li>
<li><p>Figure out the differences between PFILE and SPFILE and the workings of SCOPE.</p>
</li>
<li><p>Turn off Automatic Shared Memory Management - MEMORY_TARGET = 0</p>
</li>
<li><p>Turn off Automatic Management - SGA_TARGET = 0</p>
</li>
<li><p>Set SGA_MAX_SIZE</p>
</li>
<li><p>Set DB_CACHE_SIZE</p>
</li>
<li><p>Set SHARED_POOL_SIZE</p>
</li>
<li><p>Set LARGE_POOL_SIZE</p>
</li>
<li><p>Modify a few kernel parameters (SHMMAX, SHMALL, file open limits), modify sysctl.conf and limits.conf and reboot the instance a few times.</p>
</li>
<li><p>Create a separate TABLESPACE to hold the table with the right number and size of data files and make sure they extend automatically.</p>
</li>
<li><p>Grant privileges on this TABLESPACE to the right USER.</p>
</li>
<li><p>Create the table with the right TABLESPACE for data but also the right TABLESPACE for INDEX otherwise it will create index in the default tablespace.</p>
</li>
<li><p>Figure out SQL LOADER to load the data from a csv into the table. Make sure you have the right commit frequency.</p>
</li>
<li><p>Monitor DBA_FREE_SPACE and add data files when it comes close.</p>
</li>
<li><p>Play with V$SESSION and V$SESSION_WAIT to see what is happening.</p>
</li>
<li><p>Play with EXPLAIN PLANS since Oracle gives a thousand ways to see the actual explain plan.</p>
</li>
</ul>
<h2 id="heading-no-airbyte-run">No Airbyte Run</h2>
<p>We could not do an airbyte run since it requires an enterprise level connector. So this is just our benchmark.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747850411816/ed1596a6-08a6-4365-be32-b5e5c8caa143.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-wirekite-run">Wirekite Run</h2>
<p>So how long did it take for wirekite to move 10 million changes — <strong>6 minutes and 7 seconds</strong>.</p>
<pre><code class="lang-sql">cat wirekite_cdc.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Mon Apr 28 02:47:15 UTC 2025
FINISH: Mon Apr 28 02:53:22 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 6 min 7 sec</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[PostgreSQL to Firebolt - 1B rows - 188x Faster]]></title><description><![CDATA[So we did our first Firebolt benchmark. And wow this was quite a ride. Firebolt is very different from other warehouses - the tradeoffs are really interesting. Some good, Some bad, in our opinion. As I go through the benchmark I will talk about that....]]></description><link>https://benchmarks.wirekite.io/postgres-to-firebolt-1b-rows-8-minutes-47-seconds</link><guid isPermaLink="true">https://benchmarks.wirekite.io/postgres-to-firebolt-1b-rows-8-minutes-47-seconds</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Sat, 07 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742361323294/66d31259-6031-48f2-9674-1334abc9a7e1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So we did our first Firebolt benchmark. And wow this was quite a ride. Firebolt is very different from other warehouses - the tradeoffs are really interesting. Some good, Some bad, in our opinion. As I go through the benchmark I will talk about that.</p>
<p>We chose to compare our benchmark with Airbyte since that is one of the most recognized data migration enterprise software out there.</p>
<p>This was inspired from a benchmark that Airbyte published - <a target="_blank" href="https://airbyte.com/blog/postgres-replication-performance-benchmark-airbyte-vs-fivetran">https://airbyte.com/blog/postgres-replication-performance-benchmark-airbyte-vs-fivetran</a>.</p>
<p>I do want to mention here that Firebolt benchmark is a little different, and slightly slower than what it could possibly be and the reason being that our database server is in GCP while our Firebolt bucket is in AWS. That is definitely a network hop, that will do some latency, as opposed to going from GCP to GCP. This probably explains why Firebolt benchmarks are slightly slower.</p>
<h1 id="heading-benchmark-details">Benchmark Details</h1>
<h1 id="heading-table">Table</h1>
<p>As usual we decided to use our same firenibble table that Airbyte used in their benchmark. We have standardized on this table because we want our benchmarks to be almost a fair comparison between various databases.</p>
<p>The table has a numeric primary key column, some number columns, some string columns and some date columns. This fits nicely with most databases.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> firenibble
(
    f0 <span class="hljs-built_in">BIGINT</span> PRIMARY <span class="hljs-keyword">KEY</span> <span class="hljs-keyword">GENERATED</span> <span class="hljs-keyword">ALWAYS</span> <span class="hljs-keyword">AS</span> <span class="hljs-keyword">IDENTITY</span>,
    f1 <span class="hljs-built_in">BIGINT</span>,
    f2 <span class="hljs-built_in">BIGINT</span>,
    f3 <span class="hljs-built_in">INTEGER</span>,
    f4 <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span>,
    f5 <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span>,
    f6 <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span>,
    f7 <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span>,
    f8 <span class="hljs-built_in">VARCHAR</span> <span class="hljs-keyword">COLLATE</span> pg_catalog.<span class="hljs-string">"default"</span>,
    f9 <span class="hljs-built_in">VARCHAR</span> <span class="hljs-keyword">COLLATE</span> pg_catalog.<span class="hljs-string">"default"</span>,
    f10 <span class="hljs-built_in">DATE</span>,
    f11 <span class="hljs-built_in">DATE</span>,
    f12 <span class="hljs-built_in">DATE</span>,
    f13 <span class="hljs-built_in">VARCHAR</span> <span class="hljs-keyword">COLLATE</span> pg_catalog.<span class="hljs-string">"default"</span>,
    f14 <span class="hljs-built_in">VARCHAR</span> <span class="hljs-keyword">COLLATE</span> pg_catalog.<span class="hljs-string">"default"</span>,
    f15 <span class="hljs-built_in">VARCHAR</span> <span class="hljs-keyword">COLLATE</span> pg_catalog.<span class="hljs-string">"default"</span>
) <span class="hljs-keyword">tablespace</span> <span class="hljs-keyword">benchmark</span> ;
</code></pre>
<p>And here’s the 1 billion rows.</p>
<pre><code class="lang-sql">wirekite=<span class="hljs-comment"># select count(*) from firenibble;</span>
   count
<span class="hljs-comment">------------</span>
 1000000000
(1 row)
</code></pre>
<h1 id="heading-machine-configurations">Machine Configurations</h1>
<p>For Postgres we created an <strong>n2-standard-64</strong> GCP instance with all the standard configurations - 64 CPU’s and 256 GB RAM in the us-central region.</p>
<p>For Firebolt we created an engine with M size (medium), 5 nodes, 2 clusters and it was COMPUTE_OPTIMIZED. We created the engine in us-east region. Firebolt does not offer us-central region. Also Firebolt does not offer L size by default that other cloud vendors offer. We got the following message when we tried to upgrade our engine.</p>
<pre><code class="lang-sql"> =&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"L"</span> NODES = <span class="hljs-number">5</span> MIN_CLUSTERS=<span class="hljs-number">1</span> MAX_CLUSTERS = <span class="hljs-number">2</span>;
2025/03/15 22:46:31 ERROR query <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"L"</span> NODES = <span class="hljs-number">5</span> MIN_CLUSTERS=<span class="hljs-number">1</span> MAX_CLUSTERS = <span class="hljs-number">2</span> <span class="hljs-keyword">failed</span>: <span class="hljs-keyword">error</span> during <span class="hljs-keyword">query</span> execution: <span class="hljs-keyword">error</span> during <span class="hljs-keyword">query</span> request: <span class="hljs-keyword">Alter</span> <span class="hljs-keyword">engine</span> failed. <span class="hljs-string">'L'</span> node <span class="hljs-keyword">type</span> <span class="hljs-keyword">is</span> currently <span class="hljs-keyword">in</span> preview. Reach <span class="hljs-keyword">out</span> <span class="hljs-keyword">to</span> Firebolt Support <span class="hljs-keyword">to</span> <span class="hljs-keyword">enable</span> <span class="hljs-string">'L'</span> node <span class="hljs-keyword">type</span> <span class="hljs-keyword">for</span> this <span class="hljs-keyword">account</span>
=&gt;
</code></pre>
<h2 id="heading-firebolt-command-line">Firebolt Command Line</h2>
<p>Also this is where we discovered that Firebolt does not offer command line. Very Strange for a database /engineer focused company.</p>
<p><strong>So we build our own Firebolt Command Line !!</strong></p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"M"</span> NODES = <span class="hljs-number">5</span> MIN_CLUSTERS=<span class="hljs-number">1</span> MAX_CLUSTERS = <span class="hljs-number">2</span> FAMILY=CO;
ok
=&gt; <span class="hljs-keyword">show</span> <span class="hljs-keyword">engines</span>;
1: engine_name: my_engine
1: engine_owner: sandhu.nurat
1: type: M
1: family: COMPUTE_OPTIMIZED
1: nodes: 5
1: clusters: 1
1: status: RUNNING
1: auto_start: 1
1: auto_stop: 20
1: initially_stopped: 0
1: url: account-1-ewafh.api.us-east-1.app.firebolt.io?engine=my_engine
1: default_database:
1: version: 4.16.8
1: last_started: 2025-03-16 20:29:35.366
1: last_stopped: 2025-03-16 20:20:19.808
1: description:
1: fbu_rate: 40
=&gt;
</code></pre>
<p>You can also see tables and their various properties</p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">show</span> <span class="hljs-keyword">tables</span>;
1: table_name: firenibble
1: table_type: BASE TABLE
1: column_count: 16
1: primary_index: f0
1: schema: <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-string">"firenibble"</span> (<span class="hljs-string">"f0"</span> <span class="hljs-built_in">BIGINT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f1"</span> <span class="hljs-built_in">BIGINT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f2"</span> <span class="hljs-built_in">BIGINT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f3"</span> <span class="hljs-built_in">INTEGER</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f4"</span> <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f5"</span> <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f6"</span> <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f7"</span> <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f8"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f9"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f10"</span> <span class="hljs-built_in">DATE</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f11"</span> <span class="hljs-built_in">DATE</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f12"</span> <span class="hljs-built_in">DATE</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f13"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f14"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f15"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>) PRIMARY <span class="hljs-keyword">INDEX</span> <span class="hljs-string">"f0"</span>
<span class="hljs-number">1</span>: number_of_rows: <span class="hljs-number">1000000000</span>
<span class="hljs-number">1</span>: compressed_bytes: <span class="hljs-number">216.93</span> GiB
<span class="hljs-number">1</span>: uncompressed_bytes: <span class="hljs-number">234.69</span> GiB
<span class="hljs-number">1</span>: compression_ratio: <span class="hljs-number">1</span>
<span class="hljs-number">1</span>: number_of_tablets: <span class="hljs-number">1586</span>
=&gt;
</code></pre>
<p>Sweet !!</p>
<h1 id="heading-wirekite-run">Wirekite Run</h1>
<p>And the the fun began. We tried different combination of number of threads and number of nodes but we kept on getting the following error. <strong>Out of Memory !!</strong></p>
<pre><code class="lang-sql">2025/03/15 22:10:46 data_loader.go:201: ERROR <span class="hljs-keyword">insert</span>/<span class="hljs-keyword">select</span> <span class="hljs-keyword">into</span> <span class="hljs-keyword">table</span> <span class="hljs-keyword">failed</span>: <span class="hljs-keyword">error</span> during <span class="hljs-keyword">query</span> execution: <span class="hljs-keyword">error</span> during <span class="hljs-keyword">query</span> request: <span class="hljs-keyword">Out</span> <span class="hljs-keyword">of</span> <span class="hljs-keyword">memory</span> - Exceeded available <span class="hljs-number">22.14</span> GiB RAM. <span class="hljs-keyword">Consider</span> <span class="hljs-keyword">using</span> an <span class="hljs-keyword">engine</span> <span class="hljs-keyword">with</span> more RAM.
<span class="hljs-number">2025</span>/<span class="hljs-number">03</span>/<span class="hljs-number">15</span> <span class="hljs-number">22</span>:<span class="hljs-number">10</span>:<span class="hljs-number">46</span> data_loader.go:<span class="hljs-number">332</span>: <span class="hljs-keyword">ERROR</span> public.firenibble: <span class="hljs-keyword">error</span> during <span class="hljs-keyword">query</span> execution: <span class="hljs-keyword">error</span> during <span class="hljs-keyword">query</span> request: <span class="hljs-keyword">Out</span> <span class="hljs-keyword">of</span> <span class="hljs-keyword">memory</span> - Exceeded available <span class="hljs-number">22.14</span> GiB RAM. <span class="hljs-keyword">Consider</span> <span class="hljs-keyword">using</span> an <span class="hljs-keyword">engine</span> <span class="hljs-keyword">with</span> more RAM.
</code></pre>
<p>Finally we found a combination that worked. It was 24 threads.</p>
<pre><code class="lang-sql">$ cat wirekite.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Sat Mar 15 23:00:47 UTC 2025
FINISH: Sat Mar 15 23:12:24 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 11 min 37 sec</span>
</code></pre>
<p>But we discovered that we were not bringing Firebolt down to its knees. Our logs told us that the loader took 5 more minutes to load the files after the mover had already moved them. As you can see here the mover finished at <code>23:08:54 data_mover.go:321: INFO all files processed - graceful shutdown</code> but the loader finished at <code>23:12:24 data_loader.go:464: INFO all files processed - graceful shutdown</code>.</p>
<pre><code class="lang-sql">$ grep -E 'startup|shutdown' *.log
fb_loader.log:2025/03/15 23:00:47 data_loader.go:455: INFO graceful startup
fb_loader.log:2025/03/15 23:12:24 data_loader.go:464: INFO all files processed - graceful shutdown
fb_mover.log:2025/03/15 23:00:47 data_mover.go:298: INFO graceful startup
fb_mover.log:2025/03/15 23:08:54 data_mover.go:321: INFO all files processed - graceful shutdown
pg_extract.log:2025/03/15 23:00:47 data_extractor.go:290: INFO graceful startup
pg_extract.log:2025/03/15 23:07:54 data_extractor.go:196: INFO dumped 1380 files to /mnt/benchmark/dumpdir - graceful shutdown
ziggy@instance-20250305-200657:~/benchmark/logs.20250315-231224.pg.fb.24$
</code></pre>
<p>Time to up the threads.</p>
<p>And that’s when we got our fastest run.</p>
<p><strong>1 BILLION rows loaded in 8 minutes and 47 seconds.</strong></p>
<pre><code class="lang-sql">$ cat wirekite.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Sat Mar 15 23:22:43 UTC 2025
FINISH: Sat Mar 15 23:31:30 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 8 min 47 sec</span>
</code></pre>
<p>And the loader was lagging behind the mover by only 30 seconds. Sweet.</p>
<pre><code class="lang-sql">$ grep -E 'startup|shutdown' *.log
fb_loader.log:2025/03/15 23:22:43 data_loader.go:455: INFO graceful startup
fb_loader.log:2025/03/15 23:31:30 data_loader.go:464: INFO all files processed - graceful shutdown
fb_mover.log:2025/03/15 23:22:43 data_mover.go:298: INFO graceful startup
fb_mover.log:2025/03/15 23:30:50 data_mover.go:321: INFO all files processed - graceful shutdown
pg_extract.log:2025/03/15 23:22:43 data_extractor.go:290: INFO graceful startup
pg_extract.log:2025/03/15 23:29:52 data_extractor.go:196: INFO dumped 1380 files to /mnt/benchmark/dumpdir - graceful shutdown
</code></pre>
<p>And here’s the 1 Billion rows.</p>
<pre><code class="lang-sql">$ ./cmdline -c ~/wirekite/benchmark/urlfiles/fi_url.txt
INFO[0000]log.go:182 gofirebolt.(*defaultLogger).Infof Credentials <span class="hljs-keyword">cache</span> <span class="hljs-keyword">path</span>: /home/ziggy/.cache/firebolt/temporary_credential.json
firebolt <span class="hljs-keyword">instance</span> <span class="hljs-keyword">connect</span> successful
=&gt; <span class="hljs-keyword">select</span> <span class="hljs-keyword">count</span>(*) <span class="hljs-keyword">as</span> <span class="hljs-keyword">count</span> <span class="hljs-keyword">from</span> firenibble;
1: count: 1000000000
</code></pre>
<p>Or in the GUI</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742250887564/738e7832-db19-485e-b5d9-05209dafc6f5.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-airbyte-run">Airbyte Run</h1>
<p>Running Airbyte for this connector had it’s fair share of adventures.</p>
<p>There were two ways to configure Airbyte to Firebolt - Inserts or S3 Bucket. We chose the bucket because it the fastest and it is what we used for our runs.</p>
<p>First we ran into AWS bucket permission errors. Not sure why we got that since it is configured with the same security context as our other runs. But we kept on running into this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742251073209/051eadac-f51d-4791-9248-e0bcb9e96d48.png" alt class="image--center mx-auto" /></p>
<p>So we decided to move to Airbyte Cloud. And then it worked. But something to notice here - It seems airbyte first moves the data to the bucket and then loads the bucket to Firebolt. While it is loading data to the bucket it (hopefully) does not touch Firebolt so the engine possibly go to sleep, which is good since you are not charged for that time.</p>
<p>And here’s the Airbyte run. <strong>It took Airbyte 27 hours and 36 minutes to move 1 billion rows.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742344931931/f89ee8ec-dcd7-478a-bdb2-3bc6d7b1692e.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-javascript">  <span class="hljs-string">"status"</span> : <span class="hljs-string">"completed"</span>,
  <span class="hljs-string">"recordsSynced"</span> : <span class="hljs-number">1000000000</span>,
  <span class="hljs-string">"bytesSynced"</span> : <span class="hljs-number">439710415164</span>,
  <span class="hljs-string">"startTime"</span> : <span class="hljs-number">1742245104251</span>,
  <span class="hljs-string">"endTime"</span> : <span class="hljs-number">1742344306406</span>,
  <span class="hljs-string">"totalStats"</span> : {
    <span class="hljs-string">"bytesCommitted"</span> : <span class="hljs-number">439710415164</span>,
    <span class="hljs-string">"bytesEmitted"</span> : <span class="hljs-number">439710415164</span>,
    <span class="hljs-string">"destinationStateMessagesEmitted"</span> : <span class="hljs-number">100000</span>,
    <span class="hljs-string">"destinationWriteEndTime"</span> : <span class="hljs-number">1742344306238</span>,
    <span class="hljs-string">"destinationWriteStartTime"</span> : <span class="hljs-number">1742245104389</span>,
    <span class="hljs-string">"meanSecondsBeforeSourceStateMessageEmitted"</span> : <span class="hljs-number">20</span>,
    <span class="hljs-string">"maxSecondsBeforeSourceStateMessageEmitted"</span> : <span class="hljs-number">100000</span>,
    <span class="hljs-string">"maxSecondsBetweenStateMessageEmittedandCommitted"</span> : <span class="hljs-number">636</span>,
    <span class="hljs-string">"meanSecondsBetweenStateMessageEmittedandCommitted"</span> : <span class="hljs-number">14</span>,
    <span class="hljs-string">"recordsEmitted"</span> : <span class="hljs-number">1000000000</span>,
    <span class="hljs-string">"recordsCommitted"</span> : <span class="hljs-number">1000000000</span>,
    <span class="hljs-string">"recordsFilteredOut"</span> : <span class="hljs-number">0</span>,
    <span class="hljs-string">"bytesFilteredOut"</span> : <span class="hljs-number">0</span>,
    <span class="hljs-string">"replicationEndTime"</span> : <span class="hljs-number">1742344306337</span>,
    <span class="hljs-string">"replicationStartTime"</span> : <span class="hljs-number">1742245104251</span>,
    <span class="hljs-string">"sourceReadEndTime"</span> : <span class="hljs-number">1742343674956</span>,
    <span class="hljs-string">"sourceReadStartTime"</span> : <span class="hljs-number">1742245104390</span>,
    <span class="hljs-string">"sourceStateMessagesEmitted"</span> : <span class="hljs-number">100000</span>
  },
  <span class="hljs-string">"streamStats"</span> : [ {
    <span class="hljs-string">"streamName"</span> : <span class="hljs-string">"firenibble"</span>,
    <span class="hljs-string">"streamNamespace"</span> : <span class="hljs-string">"public"</span>,
    <span class="hljs-string">"stats"</span> : {
      <span class="hljs-string">"bytesCommitted"</span> : <span class="hljs-number">439710415164</span>,
      <span class="hljs-string">"bytesEmitted"</span> : <span class="hljs-number">439710415164</span>,
      <span class="hljs-string">"recordsEmitted"</span> : <span class="hljs-number">1000000000</span>,
      <span class="hljs-string">"recordsCommitted"</span> : <span class="hljs-number">1000000000</span>,
      <span class="hljs-string">"recordsFilteredOut"</span> : <span class="hljs-number">0</span>,
      <span class="hljs-string">"bytesFilteredOut"</span> : <span class="hljs-number">0</span>
    }
  } ],
</code></pre>
<p>Also just to be clear we did use the S3 bucket method to do the load - <code>info Using the S3 writing strategy</code></p>
<pre><code class="lang-sql">2025-03-17 13:58:25 info Creating status: public:firenibble - RUNNING
2025-03-17 13:58:25 info INFO main i.a.i.s.p.PostgresQueryUtils(fileNodeForIndividualStream):235 Relation filenode is for stream "public"."firenibble" is 42019
2025-03-17 13:58:25 info INFO main i.a.i.s.p.c.InitialSyncCtidIterator(createCtidQueryStatement):300 Preparing query for table: firenibble
2025-03-17 13:58:25 info INFO main i.a.i.s.p.c.InitialSyncCtidIterator(createCtidQueryStatement):309 Executing query for table firenibble: <span class="hljs-keyword">SELECT</span> ctid::<span class="hljs-built_in">text</span>, <span class="hljs-string">"f0"</span>,<span class="hljs-string">"f1"</span>,<span class="hljs-string">"f2"</span>,<span class="hljs-string">"f3"</span>,<span class="hljs-string">"f4"</span>,<span class="hljs-string">"f5"</span>,<span class="hljs-string">"f6"</span>,<span class="hljs-string">"f7"</span>,<span class="hljs-string">"f8"</span>,<span class="hljs-string">"f9"</span>,<span class="hljs-string">"f10"</span>,<span class="hljs-string">"f11"</span>,<span class="hljs-string">"f12"</span>,<span class="hljs-string">"f13"</span>,<span class="hljs-string">"f14"</span>,<span class="hljs-string">"f15"</span> <span class="hljs-keyword">FROM</span> <span class="hljs-string">"public"</span>.<span class="hljs-string">"firenibble"</span> <span class="hljs-keyword">WHERE</span> ctid &gt; ?::tid <span class="hljs-keyword">AND</span> ctid &lt;= ?::tid <span class="hljs-keyword">with</span> bindings (<span class="hljs-number">0</span>,<span class="hljs-number">0</span>) <span class="hljs-keyword">and</span> (<span class="hljs-number">131072</span>,<span class="hljs-number">0</span>)
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-17</span> <span class="hljs-number">13</span>:<span class="hljs-number">58</span>:<span class="hljs-number">25</span> info INFO <span class="hljs-keyword">main</span> i.a.c.d.j.s.AdaptiveStreamingQueryConfig(initialize):<span class="hljs-number">24</span> <span class="hljs-keyword">Set</span> <span class="hljs-keyword">initial</span> <span class="hljs-keyword">fetch</span> <span class="hljs-keyword">size</span>: <span class="hljs-number">10</span> <span class="hljs-keyword">rows</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-17</span> <span class="hljs-number">13</span>:<span class="hljs-number">58</span>:<span class="hljs-number">26</span> info INFO <span class="hljs-keyword">main</span> i.a.c.d.j.s.AdaptiveStreamingQueryConfig(<span class="hljs-keyword">accept</span>):<span class="hljs-number">33</span> <span class="hljs-keyword">Set</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">fetch</span> <span class="hljs-keyword">size</span>: <span class="hljs-number">173376</span> <span class="hljs-keyword">rows</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-17</span> <span class="hljs-number">13</span>:<span class="hljs-number">58</span>:<span class="hljs-number">26</span> info <span class="hljs-keyword">Using</span> the S3 writing strategy
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-17</span> <span class="hljs-number">13</span>:<span class="hljs-number">58</span>:<span class="hljs-number">26</span> info INFO <span class="hljs-keyword">main</span> i.a.c.d.j.s.TwoStageSizeEstimator$Companion(getTargetBufferByteSize):<span class="hljs-number">80</span> <span class="hljs-keyword">Max</span> <span class="hljs-keyword">memory</span> <span class="hljs-keyword">limit</span>: <span class="hljs-number">1610612736</span>, JDBC buffer <span class="hljs-keyword">size</span>: <span class="hljs-number">966367642</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-17</span> <span class="hljs-number">13</span>:<span class="hljs-number">58</span>:<span class="hljs-number">26</span> info Stream firenibble <span class="hljs-keyword">is</span> wiped.
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-17</span> <span class="hljs-number">13</span>:<span class="hljs-number">58</span>:<span class="hljs-number">26</span> info INFO <span class="hljs-keyword">main</span> i.a.c.d.j.s.AdaptiveStreamingQueryConfig(<span class="hljs-keyword">accept</span>):<span class="hljs-number">33</span> <span class="hljs-keyword">Set</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">fetch</span> <span class="hljs-keyword">size</span>: <span class="hljs-number">637866</span> <span class="hljs-keyword">rows</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-17</span> <span class="hljs-number">13</span>:<span class="hljs-number">58</span>:<span class="hljs-number">27</span> info INFO <span class="hljs-keyword">main</span> i.a.c.d.j.s.AdaptiveStreamingQueryConfig(<span class="hljs-keyword">accept</span>):<span class="hljs-number">33</span> <span class="hljs-keyword">Set</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">fetch</span> <span class="hljs-keyword">size</span>: <span class="hljs-number">636606</span> <span class="hljs-keyword">rows</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-17</span> <span class="hljs-number">13</span>:<span class="hljs-number">58</span>:<span class="hljs-number">27</span> info INFO <span class="hljs-keyword">main</span> i.a.c.d.j.s.AdaptiveStreamingQueryConfig(<span class="hljs-keyword">accept</span>):<span class="hljs-number">33</span> <span class="hljs-keyword">Set</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">fetch</span> <span class="hljs-keyword">size</span>: <span class="hljs-number">635350</span> <span class="hljs-keyword">rows</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-17</span> <span class="hljs-number">13</span>:<span class="hljs-number">58</span>:<span class="hljs-number">28</span> info INFO <span class="hljs-keyword">main</span> i.a.c.d.j.s.AdaptiveStreamingQueryConfig(<span class="hljs-keyword">accept</span>):<span class="hljs-number">33</span> <span class="hljs-keyword">Set</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">fetch</span> <span class="hljs-keyword">size</span>: <span class="hljs-number">631613</span> <span class="hljs-keyword">rows</span>
</code></pre>
<p>I started wondering why did it take so long while it moved the same table to Snowflake in 12 hours. And I think the answer is this. Airbyte apparently creates the migrated table as 3 columns.</p>
<ul>
<li><p><code>_airbyte_ab_id</code>: a uuid assigned by Airbyte to each event that is processed. The column type in Firebolt is <code>VARCHAR</code>.</p>
</li>
<li><p><code>_airbyte_emitted_at</code>: a timestamp representing when the event was pulled from the data source. The column type in Firebolt is <code>TIMESTAMP</code>.</p>
</li>
<li><p><code>_airbyte_data</code>: a json blob representing the event data. The column type in Firebolt is <code>VARCHAR</code> but can be parsed with JSON functions.</p>
</li>
</ul>
<p>So all <strong>the row data is stored as a JSON</strong>. My guess is Airbyte is spending hell lot of time making a JSON out of each row.</p>
<p>Which is what we saw in our Firebolt database.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742345369896/e43ef088-3ceb-41a9-8453-bed7419a39c8.png" alt class="image--center mx-auto" /></p>
<p>By the way did you notice the query to do count ran in <strong>0.20 seconds</strong>. Sweet !!</p>
]]></content:encoded></item><item><title><![CDATA[Oracle to Firebolt - 10 million ops (inserts + updates + deletes) - 5 mins 50 secs]]></title><description><![CDATA[So we set up a Change Data Capture replication pipeline from Oracle to Firebolt and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark.
I do want to mention here that F...]]></description><link>https://benchmarks.wirekite.io/oracle-to-firebolt-10-million-ops-inserts-updates-deletes-5-mins-50-secs</link><guid isPermaLink="true">https://benchmarks.wirekite.io/oracle-to-firebolt-10-million-ops-inserts-updates-deletes-5-mins-50-secs</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Sat, 07 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1749882731763/c2bfc62d-1c89-4a1b-a3fa-bb56f9c850aa.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So we set up a Change Data Capture replication pipeline from Oracle to Firebolt and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark.</p>
<p>I do want to mention here that Firebolt benchmark is a little different, and slightly slower than what it could possibly be and the reason being that our database server is in GCP while our Firebolt bucket is in AWS. That is definitely a network hop, that will do some latency, as opposed to going from GCP to GCP. This probably explains why Firebolt benchmarks are slightly slower.</p>
<h2 id="heading-benchmark-details">Benchmark Details</h2>
<p>The most important decision here was to determine how to do a replication benchmark, specifically what constitutes a typical load profile of an OLTP database. We realized that a typical OLTP database has the following characteristics</p>
<ul>
<li><p>It has multiple tables.</p>
</li>
<li><p>It has some inserts.</p>
</li>
<li><p>It has somewhat more updates.</p>
</li>
<li><p>It has some deletes.</p>
</li>
<li><p>It has small transactions with lot of commits, mostly single row operations and commits.</p>
</li>
</ul>
<p>Given the above characteristics we decided on doing the following for the benchmark.</p>
<ul>
<li><p>We will have 10 tables.</p>
</li>
<li><p>We will have 2 million single row inserts.</p>
</li>
<li><p>We will have 6 million single row updates.</p>
</li>
<li><p>We will have 2 million single row deletes.</p>
</li>
<li><p>We will have auto commit on, causing all the above operations to have corresponding commit.</p>
</li>
</ul>
<h3 id="heading-table-structure">Table Structure</h3>
<p>We will have 10 tables called firenibble 1 to 10.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> app_db.firenibble1 (
  f0 <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  f1 <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>) ,
  f2 <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>) ,
  f3 <span class="hljs-built_in">int</span> ,
  f4 <span class="hljs-built_in">float</span> ,
  f5 <span class="hljs-built_in">float</span> ,
  f6 <span class="hljs-built_in">float</span> ,
  f7 <span class="hljs-built_in">float</span> ,
  f8 <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>) ,
  f9 <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>) ,
  f10 <span class="hljs-built_in">date</span> ,
  f11 <span class="hljs-built_in">date</span> ,
  f12 <span class="hljs-built_in">date</span> ,
  f13 <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>) ,
  f14 <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>) ,
  f15 <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>) ,
  primary <span class="hljs-keyword">key</span> (f0)
);
</code></pre>
<h2 id="heading-insert">Insert</h2>
<p>Insert will essentially be new primary key insert.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h2 id="heading-update">Update</h2>
<p>Update will be updating of two columns on a primary key value.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">update</span> firenibble1 <span class="hljs-keyword">set</span> f2 = <span class="hljs-number">280396830734761092</span>, f9 = <span class="hljs-string">'n6ChQjN9dfxIl6nc6SNgIzSahfeXfAef'</span> <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h2 id="heading-delete">Delete</h2>
<p>Delete will be essentially a primary key delete.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">delete</span> <span class="hljs-keyword">from</span> firenibble1 <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h3 id="heading-dml-operations-sequence">DML Operations Sequence</h3>
<p>Then came the question of how do we order the load so that we can rerun the load over and over again and never have to clean up the previous load. So we decided that the load will be such that we will start with 0 rows in all 10 tables, do a bunch of inserts, do a bunch of updates, do a bunch of deletes and end up with 0 rows in all tables. This kept the load and the tables rather clean.</p>
<p>So the exact sequence will look like this. I know we could have been more granular mixing the inserts, updates and deletes even more, and as we do more benchmarks we might try that strategy but for starters this looked pretty good. Also we wanted to see how our replication performed with large number of insert only, update only and delete only loads. Also note that there is no relationships between the load and the archivelogs, in the sense there is no alter system switch logfile happening anywhere causing the inserts, updates and deletes to cross binary log boundaries.</p>
<ol>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes</p>
</li>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes.</p>
</li>
</ol>
<p>We will also makes sure that all inserts, updates and deletes happen on 10 tables in a sequence so that the operations are granularily staggered over all tables and not contiguous on one table and the next. Which means, the inserts look like this (and so does the updates and deletes).</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble2 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble3 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble4 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble5 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble6 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble7 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble8 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble9 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble10 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h3 id="heading-benchmark-sequence">Benchmark Sequence</h3>
<p>A choice we had was to make was do one of the following</p>
<ol>
<li><p>Have the wirekite replication running. Run the load and wait for the last event of the load to appear on the target. Measure the time between when the load started and the last event appeared.</p>
</li>
<li><p>Run the load and note down the binlog number and position at which the load started and wait for the load to finish. Now start the wirekite replication from the starting binlog number and position and wait for the last event of the load to appear on the target. Measure the time between when the wirekite replication started and the last event appeared on the target.</p>
</li>
</ol>
<p>We decided to go with option 2. The primary reason being that in option 1 wirekite replication was waiting for the events to finish successfully on the database, and essentially we were not only benchmarking wirekite, but also the database, with the boundaries between the two completely blurred. So we preferred the pre-loaded database with the changes, so that we are only benchmarking wirekite and nothing else.</p>
<h2 id="heading-machine-configuration">Machine Configuration</h2>
<p>For Oracle we created an <strong>n2-standard-16</strong> GCP instance with all the standard configurations - 8 CPU’s and 64 GB RAM in the us-central region. We installed Ubuntu version 24 and Oracle version 19. Our archive log size was 330 MB.</p>
<p>For Firebolt we created a <strong>Medium</strong> Size Warehouse.</p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">show</span> <span class="hljs-keyword">engines</span>;
1: engine_name: my_engine
1: engine_owner: gjkemnitz
1: type: M
1: family: COMPUTE_OPTIMIZED
1: nodes: 5
1: clusters: 1
1: status: RUNNING
1: auto_start: 1
1: auto_stop: 20
1: initially_stopped: 0
1: url: account-1-fxrjk.api.us-east-1.app.firebolt.io?engine=my_engine
1: default_database:
1: version: 4.21.9
1: last_started: 2025-06-14 04:28:27.824
1: last_stopped: 2025-06-14 03:58:10.993
1: description:
1: fbu_rate: 40
</code></pre>
<p>I wish we could automatically create a Large Size Warehouse but we got the following error.</p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"L"</span>;
2025/06/14 04:49:00 ERROR query <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"L"</span> <span class="hljs-keyword">failed</span>: <span class="hljs-keyword">error</span> during <span class="hljs-keyword">query</span> execution: <span class="hljs-keyword">error</span> during <span class="hljs-keyword">query</span> request: <span class="hljs-keyword">Alter</span> <span class="hljs-keyword">engine</span> failed. <span class="hljs-string">'L_COMPUTE_OPTIMIZED'</span> node <span class="hljs-keyword">type</span> <span class="hljs-keyword">is</span> currently <span class="hljs-keyword">in</span> preview. Reach <span class="hljs-keyword">out</span> <span class="hljs-keyword">to</span> Firebolt Support <span class="hljs-keyword">to</span> <span class="hljs-keyword">enable</span> <span class="hljs-string">'L_COMPUTE_OPTIMIZED'</span> node <span class="hljs-keyword">type</span> <span class="hljs-keyword">for</span> this <span class="hljs-keyword">account</span>
</code></pre>
<p>We have been using the same configurations for all our benchmarks so that we are comparing apples and apples.</p>
<h2 id="heading-oracle-run-around">Oracle Run Around</h2>
<p>We wanted to mention this a bit to talk about the uphill challenge that was getting oracle to be up and running and importing data into it.</p>
<p>First it was the installation which we thought we could do using the command line. But once we started playing with response files we realized it was almost impossible to get the right response file. There are hundreds of options that go in oracle response file which makes it impossible to find the right combination. We kept on running into errors.</p>
<p>So we decided to use the GUI. Getting X11 forwarding working took some time (that DISPLAY variable) but we were able to do it. But then Oracle GUI would show up with buttons missing from it - <a target="_blank" href="https://forums.oracle.com/ords/apexds/post/19c-runinstaller-shows-blank-screen-for-15-minutes-9680">https://forums.oracle.com/ords/apexds/post/19c-runinstaller-shows-blank-screen-for-15-minutes-9680</a>.</p>
<p>We realized that some given environment variable has to be set to make sure the GUI runs as intended. Once we did that we got the right GUI and got Oracle installed.</p>
<p>And then came the challenge of configuring the database with sensible values so that you can actually load a reasonable amount of data in it. We had to configure</p>
<ul>
<li><p>Configure and start the LISTENER. Understand LISTENER.ORA and TNSNAMES.ORA.</p>
</li>
<li><p>Figure out the differences between PFILE and SPFILE and the workings of SCOPE.</p>
</li>
<li><p>Turn off Automatic Shared Memory Management - MEMORY_TARGET = 0</p>
</li>
<li><p>Turn off Automatic Management - SGA_TARGET = 0</p>
</li>
<li><p>Set SGA_MAX_SIZE</p>
</li>
<li><p>Set DB_CACHE_SIZE</p>
</li>
<li><p>Set SHARED_POOL_SIZE</p>
</li>
<li><p>Set LARGE_POOL_SIZE</p>
</li>
<li><p>Modify a few kernel parameters (SHMMAX, SHMALL, file open limits), modify sysctl.conf and limits.conf and reboot the instance a few times.</p>
</li>
<li><p>Create a separate TABLESPACE to hold the table with the right number and size of data files and make sure they extend automatically.</p>
</li>
<li><p>Grant privileges on this TABLESPACE to the right USER.</p>
</li>
<li><p>Create the table with the right TABLESPACE for data but also the right TABLESPACE for INDEX otherwise it will create index in the default tablespace.</p>
</li>
<li><p>Figure out SQL LOADER to load the data from a csv into the table. Make sure you have the right commit frequency.</p>
</li>
<li><p>Monitor DBA_FREE_SPACE and add data files when it comes close.</p>
</li>
<li><p>Play with V$SESSION and V$SESSION_WAIT to see what is happening.</p>
</li>
<li><p>Play with EXPLAIN PLANS since Oracle gives a thousand ways to see the actual explain plan.</p>
</li>
</ul>
<h2 id="heading-no-airbyte-run">No Airbyte Run</h2>
<p>We could not do an airbyte run since it requires an enterprise level connector. So this is just our benchmark.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749879599643/ee9e1f04-79b2-4d9c-a312-f0ae4097e379.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-wirekite-run">Wirekite Run</h2>
<p>So how long did it take for wirekite to move 10 million changes — <strong>5 minutes and 50 seconds</strong>.</p>
<pre><code class="lang-sql">cat wirekite_cdc.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Sat Jun 14 04:40:51 UTC 2025
FINISH: Sat Jun 14 04:46:41 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 5 min 50 sec</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[MySQL to Snowflake - 1B rows - 8 minutes 56 seconds]]></title><description><![CDATA[So we did another benchmark this time with MySQL to Snowflake to demonstrate how Wirekite sizes up in the enterprise data migration space. Again we decided to compare the benchmark with Airbyte since it is one of the most recognized data migration en...]]></description><link>https://benchmarks.wirekite.io/mysql-to-snowflake-1b-rows-9-minutes</link><guid isPermaLink="true">https://benchmarks.wirekite.io/mysql-to-snowflake-1b-rows-9-minutes</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Fri, 06 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742360379041/b5a74346-cf06-4c3e-acff-01b3d80ac342.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So we did another benchmark this time with MySQL to Snowflake to demonstrate how Wirekite sizes up in the enterprise data migration space. Again we decided to compare the benchmark with Airbyte since it is one of the most recognized data migration enterprise software out there.</p>
<h1 id="heading-benchmark-details">Benchmark Details</h1>
<h2 id="heading-table">Table</h2>
<p>First of all lets talk about the table structure. We have used the same table that we used in other benchmarks. The table has 16 columns, one of them is a numeric primary key, few columns are numbers of various types, few strings and few dates. This makes the table pretty simple to be absorbed by most databases.</p>
<p>The table also has 1 Billion rows.</p>
<p>We want to make it easy and standardized across various other benchmarks and databases.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-string">`firenibble`</span> (
  <span class="hljs-string">`f0`</span> <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f1`</span> <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f2`</span> <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f3`</span> <span class="hljs-built_in">int</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f4`</span> <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f5`</span> <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f6`</span> <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f7`</span> <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f8`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">256</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f9`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">256</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f10`</span> <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f11`</span> <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f12`</span> <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f13`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">256</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f14`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">256</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f15`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">256</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`f0`</span>)
) <span class="hljs-keyword">ENGINE</span>=<span class="hljs-keyword">InnoDB</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8mb4 <span class="hljs-keyword">COLLATE</span>=utf8mb4_0900_ai_ci <span class="hljs-keyword">DATA</span> <span class="hljs-keyword">DIRECTORY</span>=<span class="hljs-string">'/mnt/benchmark/mysqldata/'</span>
</code></pre>
<p>And here’s the 1 billion rows.</p>
<pre><code class="lang-sql">mysql&gt; <span class="hljs-keyword">select</span> <span class="hljs-keyword">count</span>(*) <span class="hljs-keyword">from</span> firenibble;
+<span class="hljs-comment">------------+</span>
| count(*)   |
+<span class="hljs-comment">------------+</span>
| 1000000000 |
+<span class="hljs-comment">------------+</span>
1 row in <span class="hljs-keyword">set</span> (<span class="hljs-number">13</span> <span class="hljs-keyword">min</span> <span class="hljs-number">4.70</span> sec)

mysql&gt;
</code></pre>
<h2 id="heading-machine-configuration">Machine Configuration</h2>
<p>For MySQL we created an <strong>n2-standard-64</strong> GCP instance with all the standard configurations - 64 CPU’s and 256 GB RAM in the us-central region. We installed Ubuntu version 24 and MySQL version 8.</p>
<p>For Snowflake we created a <strong>Large</strong> size warehouse with <strong>Standard Type</strong> also in the us-central1 region to minimize the network distance.</p>
<p>We have been using the same configurations for all our benchmarks so that we are comparing apples and apples.</p>
<h2 id="heading-airbyte-run">Airbyte Run</h2>
<p>We created the firenibble table with Full Refresh Overwrite and made sure the table did not exist in the target, thus forcing a full sync of the whole table.</p>
<p>And then we ran the benchmark only to get the following message after waiting for a long time.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741983369239/c46a8821-999c-4e84-84cd-02df8ffbaf9c.png" alt class="image--center mx-auto" /></p>
<p>After waiting and watching for almost 18 hours and transferring 103 million records, we did not have the courage to run the benchmark again. Turns out the snowflake free trial that we used to do the benchmark had expired. So we decided to accept this as a technically invalid benchmark, but since the rate of transfer was not changing drastically, we decided to publish it.</p>
<p>The logs</p>
<pre><code class="lang-sql">2025-03-10 23:46:48 info sync summary: {
  "status" : "failed",
  "recordsSynced" : 103123546,
  "bytesSynced" : 41680061203,
  "startTime" : 1741644491842,
  "endTime" : 1741650408147,
  "totalStats" : {
    "bytesCommitted" : 41680061203,
    "bytesEmitted" : 43332279893,
    "destinationStateMessagesEmitted" : 21,
    "destinationWriteEndTime" : 0,
    "destinationWriteStartTime" : 1741644491938,
    "meanSecondsBeforeSourceStateMessageEmitted" : 376,
    "maxSecondsBeforeSourceStateMessageEmitted" : 21,
    "maxSecondsBetweenStateMessageEmittedandCommitted" : 73,
    "meanSecondsBetweenStateMessageEmittedandCommitted" : 59,
    "recordsEmitted" : 107200542,
    "recordsCommitted" : 103123546,
    "recordsFilteredOut" : 0,
    "bytesFilteredOut" : 0,
    "replicationEndTime" : 1741650408144,
    "replicationStartTime" : 1741644491842,
    "sourceReadEndTime" : 0,
    "sourceReadStartTime" : 1741644491939,
    "sourceStateMessagesEmitted" : 21
  }
</code></pre>
<p>But our favorite message in the logs was the following !</p>
<pre><code class="lang-sql">"internalMessage" : "net.snowflake.client.jdbc.SnowflakeSQLException: Your account is suspended due to lack of payment method.",

Stack Trace: net.snowflake.client.jdbc.SnowflakeSQLException: Your free trial has ended and all of your virtual warehouses have been suspended. Add billing information in the Snowflake web UI to continue using the full <span class="hljs-keyword">set</span> <span class="hljs-keyword">of</span> Snowflake features.
</code></pre>
<p>You are poor !! Yes we are.</p>
<h2 id="heading-wirekite-run">Wirekite Run</h2>
<p>After rebooting the MySQL GCP instance to flush the buffer pool and any other remnants of the previous run we ran the same benchmark.</p>
<p>Everything else being same we got the following results.</p>
<p>1 billion rows moved <strong>under 9 minutes</strong> !!</p>
<pre><code class="lang-sql"><span class="hljs-comment"># cat wirekite.log | grep -E 'START|FINISH|ELAPSED'</span>
<span class="hljs-keyword">START</span>: Mon Mar <span class="hljs-number">10</span> <span class="hljs-number">03</span>:<span class="hljs-number">06</span>:<span class="hljs-number">20</span> UTC <span class="hljs-number">2025</span>
<span class="hljs-keyword">FINISH</span>: Mon Mar <span class="hljs-number">10</span> <span class="hljs-number">03</span>:<span class="hljs-number">15</span>:<span class="hljs-number">16</span> UTC <span class="hljs-number">2025</span>
ELAPSED: <span class="hljs-number">0</span> hrs <span class="hljs-number">8</span> <span class="hljs-keyword">min</span> <span class="hljs-number">56</span> sec
</code></pre>
<p>The billion rows in Snowflake.</p>
<pre><code class="lang-sql"><span class="hljs-comment">#COMPUTE_WH@TEST.APP_DB&gt;select count(*) from FIRENIBBLE;</span>
+<span class="hljs-comment">------------+</span>
|   COUNT(*) |
|<span class="hljs-comment">------------|</span>
| 1000000000 |
+<span class="hljs-comment">------------+</span>
1 Row(s) produced. Time Elapsed: 0.242s
<span class="hljs-comment">#COMPUTE_WH@TEST.APP_DB&gt;</span>
Goodbye!
</code></pre>
]]></content:encoded></item><item><title><![CDATA[MySQL to Snowflake - 10 million ops (inserts + updates + deletes) - 2 mins 41 secs]]></title><description><![CDATA[So we set up a Change Data Capture replication pipeline from MySQL to Snowflake and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark and how did we fare compared to s...]]></description><link>https://benchmarks.wirekite.io/mysql-to-snowflake-replication-10-million-ops-inserts-updates-deletes-2-mins-41-secs</link><guid isPermaLink="true">https://benchmarks.wirekite.io/mysql-to-snowflake-replication-10-million-ops-inserts-updates-deletes-2-mins-41-secs</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Fri, 06 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1745304469524/25341465-03f0-42e6-a565-b8a4b1a09764.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So we set up a Change Data Capture replication pipeline from MySQL to Snowflake and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark and how did we fare compared to standard tools out there.</p>
<h2 id="heading-benchmark-details">Benchmark Details</h2>
<p>The most important decision here was to determine how to do a replication benchmark, specifically what constitutes a typical load profile of an OLTP database. We realized that a typical OLTP database has the following characteristics</p>
<ul>
<li><p>It has multiple tables.</p>
</li>
<li><p>It has some inserts.</p>
</li>
<li><p>It has somewhat more updates.</p>
</li>
<li><p>It has some deletes.</p>
</li>
<li><p>It has small transactions with lot of commits, mostly single row operations and commits.</p>
</li>
</ul>
<p>Given the above characteristics we decided on doing the following for the benchmark.</p>
<ul>
<li><p>We will have 10 tables.</p>
</li>
<li><p>We will have 2 million single row inserts.</p>
</li>
<li><p>We will have 6 million single row updates.</p>
</li>
<li><p>We will have 2 million single row deletes.</p>
</li>
<li><p>We will have auto commit on, causing all the above operations to have corresponding commit.</p>
</li>
</ul>
<h3 id="heading-table-structure">Table Structure</h3>
<p>We will have 10 tables called firenibble 1 to 10.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> public.firenibble1 (
  f0 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  f1 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f2 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f3 <span class="hljs-built_in">int</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f4 <span class="hljs-keyword">double</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f5 <span class="hljs-keyword">double</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f6 <span class="hljs-keyword">double</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f7 <span class="hljs-keyword">double</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f8 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f9 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f10 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f11 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f12 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f13 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f14 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f15 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  PRIMARY <span class="hljs-keyword">KEY</span> (f0)
) <span class="hljs-keyword">ENGINE</span>=<span class="hljs-keyword">InnoDB</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8mb4;
</code></pre>
<h3 id="heading-insert">Insert</h3>
<p>Insert will essentially be new primary key insert.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h3 id="heading-update">Update</h3>
<p>Update will be updating of two columns on a primary key value.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">update</span> firenibble1 <span class="hljs-keyword">set</span> f2 = <span class="hljs-number">280396830734761092</span>, f9 = <span class="hljs-string">'n6ChQjN9dfxIl6nc6SNgIzSahfeXfAef'</span> <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h3 id="heading-delete">Delete</h3>
<p>Delete will be essentially a primary key delete.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">delete</span> <span class="hljs-keyword">from</span> firenibble1 <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h3 id="heading-dml-operations-sequence">DML Operations Sequence</h3>
<p>Then came the question of how do we order the load so that we can rerun the load over and over again and never have to clean up the previous load. So we decided that the load will be such that we will start with 0 rows in all 10 tables, do a bunch of inserts, do a bunch of updates, do a bunch of deletes and end up with 0 rows in all tables. This kept the load and the tables rather clean. So the exact sequence will look like this. I know we could have been more granular mixing the inserts, updates and deletes even more, and as we do more benchmarks we might try that strategy but for starters this looked pretty good. Also we wanted to see how our replication performed with large number of insert only, update only and delete only loads. Also note that there is no relationships between the load and the binlogs, in the sense there is no flush binary logs happening anywhere causing the inserts, updates and deletes to cross binary log boundaries.</p>
<ol>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes</p>
</li>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes.</p>
</li>
</ol>
<p>We will also makes sure that all inserts, updates and deletes happen on 10 tables in a sequence so that the operations are granularily staggered over all tables and not contiguous on one table and the next. Which means, the inserts look like this (and so does the updates and deletes).</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble2 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble3 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble4 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble5 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble6 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble7 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble8 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble9 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble10 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h3 id="heading-benchmark-sequence">Benchmark Sequence</h3>
<p>A choice we had was to make was do one of the following</p>
<ol>
<li><p>Have the wirekite replication running. Run the load and wait for the last event of the load to appear on the target. Measure the time between when the load started and the last event appeared.</p>
</li>
<li><p>Run the load and note down the binlog number and position at which the load started and wait for the load to finish. Now start the wirekite replication from the starting binlog number and position and wait for the last event of the load to appear on the target. Measure the time between when the wirekite replication started and the last event appeared on the target.</p>
</li>
</ol>
<p>We decided to go with option 2. The primary reason being that in option 1 wirekite replication was waiting for the events to finish successfully on the database, and essentially we were not only benchmarking wirekite, but also the database, with the boundaries between the two completely blurred. So we preferred the pre-loaded database with the changes, so that we are only benchmarking wirekite and nothing else.</p>
<h2 id="heading-machine-configuration">Machine Configuration</h2>
<p>For MySQL we created an <strong>n2-standard-8</strong> GCP instance with all the standard configurations - 8 CPU’s and 32 GB RAM in the us-central region. We installed Ubuntu version 24 and MySQL version 8. Our binlog size was 100 MB.</p>
<p>For Snowflake we created a <strong>Large</strong> Size Warehouse with <strong>Standard Type</strong> also in the us-central1 region to minimize the network distance.</p>
<p>We have been using the same configurations for all our benchmarks so that we are comparing apples and apples.</p>
<h2 id="heading-airbyte-run">Airbyte Run</h2>
<p>We created the MySQL to Snowflake connection in Airbyte and made sure we picked the right options. For MySQL we picked the CDC option for syncing since that’s what airbyte recommended.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745302822029/601d46f6-2afe-4580-b5a2-08fcbec03472.png" alt class="image--center mx-auto" /></p>
<p>We also picked the option which creates the mirror copy of source data on the target since that’s what we are doing.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745303467672/8a3200af-f7fc-4028-8bc0-49a3167f4513.png" alt class="image--center mx-auto" /></p>
<p>We also picked the Incremental | Append + Deduped option, since it is what gives us the mirror copy of the data on the target.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745303425577/d4727c63-d95b-40f3-9ab2-ff6cfe6c2cbb.png" alt class="image--center mx-auto" /></p>
<p>For Snowflake we checked the Merge option since we are also presenting data on the target completely as a mirror of the source, i.e de-duplicated.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745303205036/9db3c983-9dc8-414f-81c2-29cca5041a6b.png" alt class="image--center mx-auto" /></p>
<p>And then we let the sync run.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745303559084/026bfca9-a307-4c3f-8f6e-e844aa0de39a.png" alt class="image--center mx-auto" /></p>
<p><strong>And the sync finished successfully !</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745303619404/20aa7671-8917-472b-87aa-104cf5b0f5f7.png" alt class="image--center mx-auto" /></p>
<p>The logs</p>
<pre><code class="lang-sql">2025-04-18 05:03:14 info sync summary: {
  "status" : "completed",
  "recordsSynced" : 10000000,
  "bytesSynced" : 5646273037,
  "startTime" : 1744951533820,
  "endTime" : 1744952594325,
  "totalStats" : {
    "bytesCommitted" : 5646273037,
    "bytesEmitted" : 5646273037,
    "destinationStateMessagesEmitted" : 10000,
    "destinationWriteEndTime" : 1744952594192,
    "destinationWriteStartTime" : 1744951533994,
    "meanSecondsBeforeSourceStateMessageEmitted" : 48,
    "maxSecondsBeforeSourceStateMessageEmitted" : 1000,
    "maxSecondsBetweenStateMessageEmittedandCommitted" : 302,
    "meanSecondsBetweenStateMessageEmittedandCommitted" : 219,
    "recordsEmitted" : 10000000,
    "recordsCommitted" : 10000000,
    "recordsFilteredOut" : 0,
    "bytesFilteredOut" : 0,
    "replicationEndTime" : 1744952594209,
    "replicationStartTime" : 1744951533820,
    "sourceReadEndTime" : 1744952549452,
    "sourceReadStartTime" : 1744951533995,
    "sourceStateMessagesEmitted" : 10000
  },
</code></pre>
<p>The final tally —</p>
<p><strong>Airbyte took 17 minutes and 54 seconds to finish the run !!</strong></p>
<p>Note that you do see an earlier sync also. That sync was the initial sync that was used to create initial tables (with 0 records) on the target so that we can then do the replication run.</p>
<h2 id="heading-wirekite-run">Wirekite Run</h2>
<p>So then we did the same exact run in wirekite.</p>
<p><strong>Wirekite moved the same amount of changes in 2 minutes and 41 seconds.</strong></p>
<pre><code class="lang-sql">$ cat wirekite.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Sat Apr 19 05:46:07 UTC 2025
FINISH: Sat Apr 19 05:48:48 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 2 min 41 sec</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[MySQL to Firebolt - 1B rows - 9 minutes 53 seconds]]></title><description><![CDATA[So we did our second benchmark for Firebolt, this time from MySQL to demonstrate the speed of Wirekite in the enterprise data migration space from one database to another. We decided to not to compare this with Airbyte since we ran into some errors. ...]]></description><link>https://benchmarks.wirekite.io/mysql-to-firebolt-1b-rows-9-minutes-53-seconds</link><guid isPermaLink="true">https://benchmarks.wirekite.io/mysql-to-firebolt-1b-rows-9-minutes-53-seconds</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Thu, 05 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742361192272/21ed6bf9-d820-4acb-a81e-466ef5bdd304.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So we did our second benchmark for Firebolt, this time from MySQL to demonstrate the speed of Wirekite in the enterprise data migration space from one database to another. We decided to not to compare this with Airbyte since we ran into some errors. Also we think the Airbyte Postgres to Firebolt benchmark will give you a good idea where it generally stands.</p>
<p>To see the Postgres benchmark please visit - <a target="_blank" href="https://benchmarks.wirekite.io/postgres-to-firebolt-1b-rows-8-minutes-47-seconds">https://benchmarks.wirekite.io/postgres-to-firebolt-1b-rows-8-minutes-47-seconds</a>.</p>
<p>I do want to mention here that Firebolt benchmark is a little different, and slightly slower than what it could possibly be and the reason being that our database server is in GCP while our Firebolt bucket is in AWS. That is definitely a network hop, that will do some latency, as opposed to going from GCP to GCP. This probably explains why Firebolt benchmarks are slightly slower.</p>
<h1 id="heading-benchmark-details">Benchmark Details</h1>
<h1 id="heading-table">Table</h1>
<p>As always we used the same firenibble table with a billion rows It has 15 columns and has all the datatypes - numbers of various shapes and sizes, some strings and some dates. This makes sure that these datatypes fit in most databases. Also we have used the same table everywhere to make sure our benchmarks stack up nicely in comparison with each other.</p>
<pre><code class="lang-sql"> <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-string">`firenibble`</span> (
  <span class="hljs-string">`f0`</span> <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f1`</span> <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f2`</span> <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f3`</span> <span class="hljs-built_in">int</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f4`</span> <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f5`</span> <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f6`</span> <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f7`</span> <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f8`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">256</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f9`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">256</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f10`</span> <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f11`</span> <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f12`</span> <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f13`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">256</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f14`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">256</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`f15`</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">256</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`f0`</span>)
) <span class="hljs-keyword">ENGINE</span>=<span class="hljs-keyword">InnoDB</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8mb4 <span class="hljs-keyword">COLLATE</span>=utf8mb4_0900_ai_ci <span class="hljs-keyword">DATA</span> <span class="hljs-keyword">DIRECTORY</span>=<span class="hljs-string">'/mnt/benchmark/mysqldata/'</span>
</code></pre>
<p>And here’s the 1 billion rows.</p>
<pre><code class="lang-sql">mysql&gt; <span class="hljs-keyword">select</span> <span class="hljs-keyword">count</span>(*) <span class="hljs-keyword">from</span> firenibble;
+<span class="hljs-comment">------------+</span>
| count(*)   |
+<span class="hljs-comment">------------+</span>
| 1000000000 |
+<span class="hljs-comment">------------+</span>
1 row in <span class="hljs-keyword">set</span> (<span class="hljs-number">13</span> <span class="hljs-keyword">min</span> <span class="hljs-number">4.70</span> sec)

mysql&gt;
</code></pre>
<h1 id="heading-machine-configurations">Machine Configurations</h1>
<p>For MySQL we created an <strong>n2-standard-64</strong> GCP instance with all the standard configurations - 64 CPU’s and 256 GB RAM in the us-central region. We installed Ubuntu version 24 and MySQL version 8.</p>
<p>For Firebolt we created an engine with M size (medium), 5 nodes, 2 clusters and it was COMPUTE_OPTIMIZED. We created the engine in us-east region. Firebolt does not offer us-central region. Also Firebolt does not offer L size by default that other cloud vendors offer. We got the following message when we tried to upgrade our engine.</p>
<pre><code class="lang-sql"> =&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"L"</span> NODES = <span class="hljs-number">5</span> MIN_CLUSTERS=<span class="hljs-number">1</span> MAX_CLUSTERS = <span class="hljs-number">2</span>;
2025/03/15 22:46:31 ERROR query <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"L"</span> NODES = <span class="hljs-number">5</span> MIN_CLUSTERS=<span class="hljs-number">1</span> MAX_CLUSTERS = <span class="hljs-number">2</span> <span class="hljs-keyword">failed</span>: <span class="hljs-keyword">error</span> during <span class="hljs-keyword">query</span> execution: <span class="hljs-keyword">error</span> during <span class="hljs-keyword">query</span> request: <span class="hljs-keyword">Alter</span> <span class="hljs-keyword">engine</span> failed. <span class="hljs-string">'L'</span> node <span class="hljs-keyword">type</span> <span class="hljs-keyword">is</span> currently <span class="hljs-keyword">in</span> preview. Reach <span class="hljs-keyword">out</span> <span class="hljs-keyword">to</span> Firebolt Support <span class="hljs-keyword">to</span> <span class="hljs-keyword">enable</span> <span class="hljs-string">'L'</span> node <span class="hljs-keyword">type</span> <span class="hljs-keyword">for</span> this <span class="hljs-keyword">account</span>
=&gt;
</code></pre>
<h2 id="heading-firebolt-command-line">Firebolt Command Line</h2>
<p>Also this is where we discovered that Firebolt does not offer command line. Very Strange for a database /engineer focused company.</p>
<p><strong>So we build our own Firebolt Command Line !!</strong></p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"M"</span> NODES = <span class="hljs-number">5</span> MIN_CLUSTERS=<span class="hljs-number">1</span> MAX_CLUSTERS = <span class="hljs-number">2</span> FAMILY=CO;
ok
=&gt; <span class="hljs-keyword">show</span> <span class="hljs-keyword">engines</span>;
1: engine_name: my_engine
1: engine_owner: sandhu.nurat
1: type: M
1: family: COMPUTE_OPTIMIZED
1: nodes: 5
1: clusters: 1
1: status: RUNNING
1: auto_start: 1
1: auto_stop: 20
1: initially_stopped: 0
1: url: account-1-ewafh.api.us-east-1.app.firebolt.io?engine=my_engine
1: default_database:
1: version: 4.16.8
1: last_started: 2025-03-16 20:29:35.366
1: last_stopped: 2025-03-16 20:20:19.808
1: description:
1: fbu_rate: 40
=&gt;
</code></pre>
<p>You can also see tables and their various properties</p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">show</span> <span class="hljs-keyword">tables</span>;
1: table_name: firenibble
1: table_type: BASE TABLE
1: column_count: 16
1: primary_index: f0
1: schema: <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-string">"firenibble"</span> (<span class="hljs-string">"f0"</span> <span class="hljs-built_in">BIGINT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f1"</span> <span class="hljs-built_in">BIGINT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f2"</span> <span class="hljs-built_in">BIGINT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f3"</span> <span class="hljs-built_in">INTEGER</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f4"</span> <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f5"</span> <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f6"</span> <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f7"</span> <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f8"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f9"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f10"</span> <span class="hljs-built_in">DATE</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f11"</span> <span class="hljs-built_in">DATE</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f12"</span> <span class="hljs-built_in">DATE</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f13"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f14"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f15"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>) PRIMARY <span class="hljs-keyword">INDEX</span> <span class="hljs-string">"f0"</span>
<span class="hljs-number">1</span>: number_of_rows: <span class="hljs-number">1000000000</span>
<span class="hljs-number">1</span>: compressed_bytes: <span class="hljs-number">216.93</span> GiB
<span class="hljs-number">1</span>: uncompressed_bytes: <span class="hljs-number">234.69</span> GiB
<span class="hljs-number">1</span>: compression_ratio: <span class="hljs-number">1</span>
<span class="hljs-number">1</span>: number_of_tablets: <span class="hljs-number">1586</span>
=&gt;
</code></pre>
<h1 id="heading-airbyte-run">Airbyte Run</h1>
<p>We tried Airbyte but it failed on us with errors that we did not how to troubleshoot.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742259314993/8ea0ba4a-0304-4d7d-8063-6b3ca493d693.png" alt class="image--center mx-auto" /></p>
<p>But there is one very interesting thing we found. Airbyte is essentially using Debezium for its MySQL extractor. We found that to be pretty strange since it competes with Debezium.</p>
<pre><code class="lang-javascript">ziggy@instance<span class="hljs-number">-20240626</span><span class="hljs-number">-215025</span>:~/Downloads$ cat mysql___firebolt_logs_3_txt.txt | grep -i debezium-engine
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    connector.class = io.debezium.connector.mysql.MySqlConnector
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    snapshot.locking.mode = none
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    max.queue.size = <span class="hljs-number">8192</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    database.sslMode = preferred
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    include.schema.changes = <span class="hljs-literal">false</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    schema.history.internal.store.only.captured.databases.ddl = <span class="hljs-literal">true</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    schema.history.internal.file.filename = <span class="hljs-regexp">/tmp/</span>airbyte-debezium-state11123047976539933388/dbhistory.dat
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    value.converter.replace.null.with.default = <span class="hljs-literal">false</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    topic.prefix = public
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    decimal.handling.mode = string
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    binary.handling.mode = base64
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    offset.storage.file.filename = <span class="hljs-regexp">/tmp/</span>airbyte-debezium-state11123047976539933388/offset.dat
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    errors.retry.delay.initial.ms = <span class="hljs-number">299</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    converters = boolean,temporal
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    value.converter = org.apache.kafka.connect.json.JsonConverter
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    key.converter = org.apache.kafka.connect.json.JsonConverter
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    database.sessionVariables = autocommit=<span class="hljs-number">0</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    database.user = ziggy
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    database.dbname = public
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    offset.storage = org.apache.kafka.connect.storage.FileOffsetBackingStore
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    database.server.id = <span class="hljs-number">5511</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    max.queue.size.in.bytes = <span class="hljs-number">268435456</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    database.useCursorFetch = <span class="hljs-literal">true</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    boolean.type = io.airbyte.integrations.source.mysql.MySqlSourceCdcBooleanConverter
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    time.precision.mode = adaptive_time_microseconds
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    temporal.type = io.airbyte.integrations.source.mysql.MySqlSourceCdcTemporalConverter
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    errors.retry.delay.max.ms = <span class="hljs-number">300</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    offset.flush.timeout.ms = <span class="hljs-number">5000</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    heartbeat.interval.ms = <span class="hljs-number">10000</span>
<span class="hljs-number">2025</span><span class="hljs-number">-03</span><span class="hljs-number">-16</span> <span class="hljs-number">23</span>:<span class="hljs-number">53</span>:<span class="hljs-number">05</span> info INFO debezium-engine i.d.c.c.BaseSourceTask(lambda$start$<span class="hljs-number">0</span>):<span class="hljs-number">247</span>    schema.history.internal.skip.unparseable.ddl = <span class="hljs-literal">true</span>
</code></pre>
<h1 id="heading-wirekite-run">Wirekite Run</h1>
<p>After running into a bunch of Out of Memory error, we found the right combination of threads.</p>
<pre><code class="lang-sql">Out of memory - Exceeded available 22.14 GiB RAM. Consider using an engine <span class="hljs-keyword">with</span> more RAM.
</code></pre>
<p>And we got a successful run.</p>
<p><strong>1 BILLION rows moved in 9 minutes and 53 seconds.</strong></p>
<pre><code class="lang-sql">$ cat wirekite.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Sun Mar 16 00:57:22 UTC 2025
FINISH: Sun Mar 16 01:07:15 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 9 min 53 sec</span>
</code></pre>
<p>An interesting to note here is how Firebolt loader lagged the mover. We want the lag to be minimum which essentially makes sure that we are using Firebolt to its full capacity. As you can see the loader - <code>01:07:15 data_loader.go:464: INFO all files processed - graceful shutdown</code> - lagged the mover - <code>01:06:21 data_mover.go:321: INFO all files processed - graceful shutdown</code> - by about a minute. Not bad !!</p>
<pre><code class="lang-sql">$ grep -E 'startup|shutdown' *.log
fb_loader.log:2025/03/16 00:57:23 data_loader.go:455: INFO graceful startup
fb_loader.log:2025/03/16 01:07:15 data_loader.go:464: INFO all files processed - graceful shutdown
fb_mover.log:2025/03/16 00:57:22 data_mover.go:298: INFO graceful startup
fb_mover.log:2025/03/16 01:06:21 data_mover.go:321: INFO all files processed - graceful shutdown
my_extract.log:2025/03/16 00:57:22 data_extractor_parallel.go:328: INFO graceful startup
my_extract.log:2025/03/16 01:06:10 data_extractor_parallel.go:221: INFO dumped 1250 files to /mnt/benchmark/dumpdir - graceful shutdown
</code></pre>
<p>And here’s the <strong>1 billion rows.</strong></p>
<pre><code class="lang-sql">INFO[0000]log.go:182 gofirebolt.(*defaultLogger).Infof Credentials <span class="hljs-keyword">cache</span> <span class="hljs-keyword">path</span>: /home/ziggy/.cache/firebolt/temporary_credential.json
firebolt <span class="hljs-keyword">instance</span> <span class="hljs-keyword">connect</span> successful
=&gt; <span class="hljs-keyword">select</span> <span class="hljs-keyword">count</span>(*) <span class="hljs-keyword">as</span> <span class="hljs-keyword">count</span> <span class="hljs-keyword">from</span> firenibble;
1: count: 1000000000
</code></pre>
<p>And on the GUI</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742253461713/3a7a8123-25b0-4af3-81dc-ecdab7d837bf.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[MySQL to Firebolt - 10 million ops (inserts + updates + deletes) - 0 mins 53 secs]]></title><description><![CDATA[So we set up a Change Data Capture replication pipeline from MySQL to Firebolt and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark and how did we fare compared to st...]]></description><link>https://benchmarks.wirekite.io/mysql-to-firebolt-10-million-ops-inserts-updates-deletes-0-mins-53-secs</link><guid isPermaLink="true">https://benchmarks.wirekite.io/mysql-to-firebolt-10-million-ops-inserts-updates-deletes-0-mins-53-secs</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Thu, 05 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1749882888792/f2ced9b4-9967-4b1e-a6e0-01bd736878c7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So we set up a Change Data Capture replication pipeline from MySQL to Firebolt and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark and how did we fare compared to standard tools out there.</p>
<p>I do want to mention here that Firebolt benchmark is a little different, and slightly slower than what it could possibly be and the reason being that our database server is in GCP while our Firebolt bucket is in AWS. That is definitely a network hop, that will do some latency, as opposed to going from GCP to GCP. This probably explains why Firebolt benchmarks are slightly slower.</p>
<h2 id="heading-benchmark-details">Benchmark Details</h2>
<p>The most important decision here was to determine how to do a replication benchmark, specifically what constitutes a typical load profile of an OLTP database. We realized that a typical OLTP database has the following characteristics</p>
<ul>
<li><p>It has multiple tables.</p>
</li>
<li><p>It has some inserts.</p>
</li>
<li><p>It has somewhat more updates.</p>
</li>
<li><p>It has some deletes.</p>
</li>
<li><p>It has small transactions with lot of commits, mostly single row operations and commits.</p>
</li>
</ul>
<p>Given the above characteristics we decided on doing the following for the benchmark.</p>
<ul>
<li><p>We will have 10 tables.</p>
</li>
<li><p>We will have 2 million single row inserts.</p>
</li>
<li><p>We will have 6 million single row updates.</p>
</li>
<li><p>We will have 2 million single row deletes.</p>
</li>
<li><p>We will have auto commit on, causing all the above operations to have corresponding commit.</p>
</li>
</ul>
<h2 id="heading-table-structure">Table Structure</h2>
<p>We will have 10 tables called firenibble 1 to 10.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> public.firenibble1 (
  f0 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  f1 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f2 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f3 <span class="hljs-built_in">int</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f4 <span class="hljs-keyword">double</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f5 <span class="hljs-keyword">double</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f6 <span class="hljs-keyword">double</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f7 <span class="hljs-keyword">double</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f8 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f9 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f10 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f11 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f12 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f13 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f14 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f15 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  PRIMARY <span class="hljs-keyword">KEY</span> (f0)
) <span class="hljs-keyword">ENGINE</span>=<span class="hljs-keyword">InnoDB</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8mb4;
</code></pre>
<h2 id="heading-insert">Insert</h2>
<p>Insert will essentially be new primary key insert.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h2 id="heading-update">Update</h2>
<p>Update will be updating of two columns on a primary key value.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">update</span> firenibble1 <span class="hljs-keyword">set</span> f2 = <span class="hljs-number">280396830734761092</span>, f9 = <span class="hljs-string">'n6ChQjN9dfxIl6nc6SNgIzSahfeXfAef'</span> <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h2 id="heading-delete">Delete</h2>
<p>Delete will be essentially a primary key delete.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">delete</span> <span class="hljs-keyword">from</span> firenibble1 <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h3 id="heading-dml-operations-sequence">DML Operations Sequence</h3>
<p>Then came the question of how do we order the load so that we can rerun the load over and over again and never have to clean up the previous load. So we decided that the load will be such that we will start with 0 rows in all 10 tables, do a bunch of inserts, do a bunch of updates, do a bunch of deletes and end up with 0 rows in all tables. This kept the load and the tables rather clean.</p>
<p>So the exact sequence will look like this. I know we could have been more granular mixing the inserts, updates and deletes even more, and as we do more benchmarks we might try that strategy but for starters this looked pretty good. Also we wanted to see how our replication performed with large number of insert only, update only and delete only loads. Also note that there is no relationships between the load and the binlogs, in the sense there is no flush binary logs happening anywhere causing the inserts, updates and deletes to cross binary log boundaries.</p>
<ol>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes</p>
</li>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes.</p>
</li>
</ol>
<p>We will also makes sure that all inserts, updates and deletes happen on 10 tables in a sequence so that the operations are granularily staggered over all tables and not contiguous on one table and the next. Which means, the inserts look like this (and so does the updates and deletes).</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble2 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble3 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble4 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble5 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble6 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble7 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble8 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble9 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble10 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h3 id="heading-benchmark-sequence">Benchmark Sequence</h3>
<p>A choice we had was to make was do one of the following</p>
<ol>
<li><p>Have the wirekite replication running. Run the load and wait for the last event of the load to appear on the target. Measure the time between when the load started and the last event appeared.</p>
</li>
<li><p>Run the load and note down the binlog number and position at which the load started and wait for the load to finish. Now start the wirekite replication from the starting binlog number and position and wait for the last event of the load to appear on the target. Measure the time between when the wirekite replication started and the last event appeared on the target.</p>
</li>
</ol>
<p>We decided to go with option 2. The primary reason being that in option 1 wirekite replication was waiting for the events to finish successfully on the database, and essentially we were not only benchmarking wirekite, but also the database, with the boundaries between the two completely blurred. So we preferred the pre-loaded database with the changes, so that we are only benchmarking wirekite and nothing else.</p>
<h2 id="heading-machine-configuration">Machine Configuration</h2>
<p>For MySQL we created an <strong>n2-standard-16</strong> GCP instance with all the standard configurations - 16 CPU’s and 64 GB RAM in the us-central region. We installed Ubuntu version 24 and MySQL version 8. Our binlog size was 100 MB.</p>
<p>For Snowflake we created a <strong>Medium</strong> Size Warehouse.</p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">show</span> <span class="hljs-keyword">engines</span>;
1: engine_name: my_engine
1: engine_owner: gjkemnitz
1: type: M
1: family: COMPUTE_OPTIMIZED
1: nodes: 5
1: clusters: 1
1: status: RUNNING
1: auto_start: 1
1: auto_stop: 20
1: initially_stopped: 0
1: url: account-1-fxrjk.api.us-east-1.app.firebolt.io?engine=my_engine
1: default_database:
1: version: 4.21.9
1: last_started: 2025-06-14 04:28:27.824
1: last_stopped: 2025-06-14 03:58:10.993
1: description:
1: fbu_rate: 40
</code></pre>
<p>We would have loved to upgrade the size to Large but we got the following error.</p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"L"</span>;
2025/06/14 04:49:00 ERROR query <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"L"</span> <span class="hljs-keyword">failed</span>: <span class="hljs-keyword">error</span> during <span class="hljs-keyword">query</span> execution: <span class="hljs-keyword">error</span> during <span class="hljs-keyword">query</span> request: <span class="hljs-keyword">Alter</span> <span class="hljs-keyword">engine</span> failed. <span class="hljs-string">'L_COMPUTE_OPTIMIZED'</span> node <span class="hljs-keyword">type</span> <span class="hljs-keyword">is</span> currently <span class="hljs-keyword">in</span> preview. Reach <span class="hljs-keyword">out</span> <span class="hljs-keyword">to</span> Firebolt Support <span class="hljs-keyword">to</span> <span class="hljs-keyword">enable</span> <span class="hljs-string">'L_COMPUTE_OPTIMIZED'</span> node <span class="hljs-keyword">type</span> <span class="hljs-keyword">for</span> this account.
</code></pre>
<p>We have been using the same configurations for all our benchmarks so that we are comparing apples and apples.</p>
<h2 id="heading-wirekite-run">Wirekite Run</h2>
<p>So how long did it take to move 10 million operations from MySQL to Firebolt — <strong>0 minutes and 53 seconds !</strong></p>
<pre><code class="lang-sql">$ cat wirekite.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Sat Jun 14 05:33:14 UTC 2025
FINISH: Sat Jun 14 05:34:07 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 0 min 53 sec</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Oracle to Snowflake - 1B rows - 6 minutes 9 seconds]]></title><description><![CDATA[So one more benchmark except this time with a really expensive enterprise grade database.
We could not compare this benchmark with Airbyte since Airbyte does not allow an open source connector for Oracle. Entirely understandable. When we tried to con...]]></description><link>https://benchmarks.wirekite.io/oracle-to-snowflake-1b-rows-6-minutes</link><guid isPermaLink="true">https://benchmarks.wirekite.io/oracle-to-snowflake-1b-rows-6-minutes</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Wed, 04 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742360698554/6d57227d-d35a-4148-8d96-dcbb74a723cb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So one more benchmark except this time with a really expensive enterprise grade database.</p>
<p>We could not compare this benchmark with Airbyte since Airbyte does not allow an open source connector for Oracle. Entirely understandable. When we tried to configure the connector after spending a long time installing Airbyte we got the following message. Would have been nice to know this earlier.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1741988956290/fe4fa05a-de5d-4145-a811-b7e351fde522.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-benchmark-details">Benchmark Details</h1>
<p>Since we could not do an Airbyte benchmark we decided to play a little bit with oracle and see how far we can scale our benchmarks as we increased the source Oracle machine configuration, the target Snowflake configurations and the number of wirekite threads.</p>
<h2 id="heading-table">Table</h2>
<p>As usual we used our standard firenibble table.</p>
<p>The table has 16 columns, one of them is a numeric primary key, few columns are numbers of various shapes and sizes, few strings and few dates. This makes the table pretty simple to be absorbed by most databases.</p>
<p>The table also has 1 Billion rows.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> app_db.firenibble (
    f0    <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>)    <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
    f1    <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>),
    f2    <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>),
    f3    <span class="hljs-built_in">int</span>,
    f4    <span class="hljs-built_in">float</span>,
    f5    <span class="hljs-built_in">float</span>,
    f6    <span class="hljs-built_in">float</span>,
    f7    <span class="hljs-built_in">float</span>,
    f8    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    f9    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    f10    <span class="hljs-built_in">date</span>,
    f11    <span class="hljs-built_in">date</span>,
    f12    <span class="hljs-built_in">date</span>,
    f13    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    f14    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    f15    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    PRIMARY <span class="hljs-keyword">KEY</span> (f0)
);
</code></pre>
<p>The 1 billion rows.</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">select</span> <span class="hljs-keyword">count</span>(*) <span class="hljs-keyword">from</span> app_db.firenibble;

  COUNT(*)
<span class="hljs-comment">----------</span>
1000000000

1 row selected.

SQL&gt;
</code></pre>
<h2 id="heading-oracle-stuff">Oracle Stuff</h2>
<p>We wanted to mention this a bit to talk about the uphill challenge that was getting oracle to be up and running and importing data into it.</p>
<p>First it was the installation which we thought we could do using the command line. But once we started playing with response files we realized it was almost impossible to get the right response file. There are hundreds of options that go in oracle response file which makes it impossible to find the right combination. We kept on running into errors.</p>
<p>So we decided to use the GUI. Getting X11 forwarding working took some time (that DISPLAY variable) but we were able to do it. But then Oracle GUI would show up with buttons missing from it - <a target="_blank" href="https://forums.oracle.com/ords/apexds/post/19c-runinstaller-shows-blank-screen-for-15-minutes-9680">https://forums.oracle.com/ords/apexds/post/19c-runinstaller-shows-blank-screen-for-15-minutes-9680</a>.</p>
<p>We realized that some given environment variable has to be set to make sure the GUI runs as intended. Once we did that we got the right GUI and got Oracle installed.</p>
<p>And then came the challenge of configuring the database with sensible values so that you can actually load a reasonable amount of data in it. We had to configure</p>
<ul>
<li><p>Configure and start the LISTENER. Understand LISTENER.ORA and TNSNAMES.ORA.</p>
</li>
<li><p>Figure out the differences between PFILE and SPFILE and the workings of SCOPE.</p>
</li>
<li><p>Turn off Automatic Shared Memory Management - MEMORY_TARGET = 0</p>
</li>
<li><p>Turn off Automatic Management - SGA_TARGET = 0</p>
</li>
<li><p>Set SGA_MAX_SIZE</p>
</li>
<li><p>Set DB_CACHE_SIZE</p>
</li>
<li><p>Set SHARED_POOL_SIZE</p>
</li>
<li><p>Set LARGE_POOL_SIZE</p>
</li>
<li><p>Modify a few kernel parameters (SHMMAX, SHMALL, file open limits), modify sysctl.conf and limits.conf and reboot the instance a few times.</p>
</li>
<li><p>Create a separate TABLESPACE to hold the table with the right number and size of data files and make sure they extend automatically.</p>
</li>
<li><p>Grant privileges on this TABLESPACE to the right USER.</p>
</li>
<li><p>Create the table with the right TABLESPACE for data but also the right TABLESPACE for INDEX otherwise it will create index in the default tablespace.</p>
</li>
<li><p>Figure out SQL LOADER to load the data from a csv into the table. Make sure you have the right commit frequency.</p>
</li>
<li><p>Monitor DBA_FREE_SPACE and add data files when it comes close.</p>
</li>
<li><p>Play with V$SESSION and V$SESSION_WAIT to see what is happening.</p>
</li>
<li><p>Play with EXPLAIN PLANS since Oracle gives a thousand ways to see the actual explain plan.</p>
</li>
</ul>
<p>And phew !! You have an oracle database and the table with the data that you desire.</p>
<p>So how does Oracle look like when it is completely pushed to its seams. This is how. As you can see either the wait event is <code>db file sequential read</code> - which means it is going through the primary key index - or it is <code>SQL*Net more data to client</code> - which means it is sending data to the client.</p>
<pre><code class="lang-sql">INST_ID                              <span class="hljs-keyword">START</span>                                               <span class="hljs-keyword">WAIT</span>
:<span class="hljs-keyword">SID</span>    USERNAME    MACHINE                  D HH:MM:SS  SQL_ID       <span class="hljs-keyword">MODULE</span>        <span class="hljs-keyword">EVENT</span>                SEQ<span class="hljs-comment">#  (SEC)</span>
<span class="hljs-comment">------- --------------- ---------------------------------------- ----------- ------------- ---------------- --------------------------------- ------ ------</span>
<span class="hljs-number">1</span>:<span class="hljs-number">676</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span> <span class="hljs-number">975</span>qxtgwmxfp6 runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>      <span class="hljs-number">122</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">604</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">01</span> <span class="hljs-number">3</span>wvvjvptdzx33 runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>         <span class="hljs-number">783</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">532</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">01</span> <span class="hljs-number">5</span>sxg963sxm3ay runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">1353</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">556</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">01</span> <span class="hljs-number">8</span>ywzssbgay2rc runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>        <span class="hljs-number">1045</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">628</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">01</span> dtks5wx6dc7ug runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>      <span class="hljs-number">616</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">580</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">01</span> fvf8wxqwx30w3 runquery@instan  <span class="hljs-keyword">ON</span> CPU                 <span class="hljs-number">906</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">508</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">01</span> gjvnup94j6nq7 runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">1297</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">412</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> <span class="hljs-number">1</span>y5crzp0bvksm runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">1681</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">316</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> <span class="hljs-number">4</span>kthrfxrk0d62 runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">1785</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">364</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> <span class="hljs-number">5</span>tm23gtarzn0d runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">1833</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">459</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> <span class="hljs-number">6</span>gzbbtnmsxcam runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">1527</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">341</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> <span class="hljs-number">78</span>u3msqm33wv8 runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">1736</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">245</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> <span class="hljs-number">7</span>xv7s23bsjxwa runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">2029</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">221</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> <span class="hljs-number">8</span>ask5tjwyqg95 runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>        <span class="hljs-number">2499</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">291</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> <span class="hljs-number">8</span>qna8nwchb7yx runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">2528</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">197</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> <span class="hljs-number">94</span>b8wkyb6vyxn runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">2597</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">172</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> b1y9um3f5gz99 runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">2672</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">268</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> cg0s1hcp4k72z runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">2452</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">436</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> d5r7aba9hv1dt runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">1549</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">388</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> dpn54kc4j6bdt runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">1586</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">484</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> fgyhxt1tyzj2z runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">1475</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">76</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02</span> ghvu59jj9r9r4 runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">1957</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">52</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">03</span> <span class="hljs-number">129</span>kf42rfscj3 runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">3159</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">100</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">03</span> <span class="hljs-number">2</span>kx656wz4gsd8 runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">3426</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">124</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">03</span> <span class="hljs-number">7782</span>fuuud928k runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">2988</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">3</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">03</span> brjxucsns1r3c runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">3784</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1467</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">03</span> cg5746pt2fnrf runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">3960</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1444</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">03</span> ck8hth7q8dfm0 runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>        <span class="hljs-number">3878</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">27</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">03</span> fqjtzvs9qbyf9 runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">3170</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1491</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">03</span> g0p4s6wp1sfvg runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">3254</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1323</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">04</span> <span class="hljs-number">4188</span>ktumx0b49 runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">5191</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1394</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">04</span> <span class="hljs-number">7</span>f4mcwydwm3ky runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>        <span class="hljs-number">4169</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1370</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">04</span> <span class="hljs-number">92</span>k8p7q5hh6bf runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">4454</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1418</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">04</span> as5mwg3dp83wb runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">4057</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1347</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">04</span> fqpyzcy3qkytg runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>        <span class="hljs-number">4691</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1299</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">05</span> <span class="hljs-number">0</span>kyfxa2t2tp7v runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>        <span class="hljs-number">5522</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1179</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">05</span> <span class="hljs-number">3</span>xt6n4mxuprmv runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>        <span class="hljs-number">6242</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1154</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">05</span> <span class="hljs-number">5</span>uq2747pb6jk9 runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">6194</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1275</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">05</span> <span class="hljs-number">65</span>rqpvqsv76fq runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>        <span class="hljs-number">5731</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1203</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">05</span> <span class="hljs-number">8</span>bqtnz43039fh runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">6045</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">985</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">05</span> ar773z9udt2pg runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">6326</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1106</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">05</span> c14pkzp1w8x3n runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">6164</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1130</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">05</span> f1ph8q6xxp18g runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>        <span class="hljs-number">6212</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1249</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">05</span> gfkuzggduvd7v runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">5244</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1227</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">05</span> gz6vhhdtv3zhu runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">6043</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1034</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">06</span> <span class="hljs-number">0</span>phgv66z4yr4u runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">7160</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">963</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">06</span> <span class="hljs-number">3</span>bkn5h3ab3kzw runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">7524</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1059</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">06</span> <span class="hljs-number">8</span>p1109f4puvf8 runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">6709</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1010</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">06</span> fn1qdrs7m20h0 runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">7357</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1083</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">06</span> gsjrhtyca5c75 runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>        <span class="hljs-number">6706</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">867</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">07</span> <span class="hljs-number">04</span>pczjgn6nfc2 runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">8553</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">942</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">07</span> <span class="hljs-number">0x67</span>wt8sz7pqv runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>        <span class="hljs-number">7847</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">460</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">07</span> <span class="hljs-number">3</span>au7843wvzn1u runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">9084</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">913</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">07</span> <span class="hljs-number">4</span>nrht8urvwgch runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>        <span class="hljs-number">7906</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">844</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">07</span> <span class="hljs-number">6</span>gf43vy81uv0u runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">8522</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">820</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">07</span> <span class="hljs-number">8</span>drjj5gnk9qqw runquery@instan  <span class="hljs-keyword">ON</span> CPU                <span class="hljs-number">8459</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">890</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">07</span> <span class="hljs-number">8</span>g1r2dpqnvdbr runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">8134</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">293</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">08</span> <span class="hljs-number">56</span>fb3yjcgcm0y runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">9399</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1515</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">08</span> aah6qs5vtyhuc runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>     <span class="hljs-number">9321</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1490</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">08</span> fw6fc9zwk2dyq runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>        <span class="hljs-number">9696</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1443</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">08</span> gth67y255by8r runquery@instan  db <span class="hljs-keyword">file</span> <span class="hljs-keyword">sequential</span> <span class="hljs-keyword">read</span>        <span class="hljs-number">9774</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">1417</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         +<span class="hljs-number">0</span> <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">09</span> dy22d8j8npat0 runquery@instan  <span class="hljs-keyword">SQL</span>*Net more <span class="hljs-keyword">data</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">client</span>        <span class="hljs-number">10626</span>      <span class="hljs-number">0</span>
<span class="hljs-number">1</span>:<span class="hljs-number">289</span>    <span class="hljs-keyword">SYS</span>        <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         nul         nul       nul            *IDLE* OFS idle               <span class="hljs-number">10528</span>      <span class="hljs-number">2</span>
<span class="hljs-number">1</span>:<span class="hljs-number">700</span>    WIREKITE    <span class="hljs-keyword">instance</span><span class="hljs-number">-20240906</span><span class="hljs-number">-204153</span>         nul         <span class="hljs-number">25</span>yx2p6anpkty runquery@instan  <span class="hljs-keyword">ON</span> CPU                  <span class="hljs-number">19</span>      <span class="hljs-number">0</span>

<span class="hljs-number">64</span> <span class="hljs-keyword">rows</span> selected.
</code></pre>
<h2 id="heading-wirekite-run-1">Wirekite Run 1</h2>
<p>We had a standard 64 CPU GCP instance with 256 GB RAM. The host was Linux RHEL8 with Oracle version 19c. The machine lived in us-central1 region. We rebooted instances between runs.</p>
<p>For Snowflake we created a Large size warehouse with Standard Type also in the us-central1 region to minimize the network distance.</p>
<p>We ran with 64 wirekite threads.</p>
<p>We have been using the same configurations for all our benchmarks so that we are comparing apples and apples.</p>
<p>And this was the result. It took about <strong>11 minutes</strong> to move 1 billion rows from oracle to snowflake.</p>
<pre><code class="lang-sql">$ cat wirekite.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Fri Mar 14 00:39:48 UTC 2025
FINISH: Fri Mar 14 00:50:24 UTC 2025
ELAPSED: 0 hrs 10 min 36 sec</span>
</code></pre>
<h2 id="heading-wirekite-run-2">Wirekite Run 2</h2>
<p>We upgrade the oracle machine to 128 CPU, 512 GB RAM, but not changing any oracle parameters - keeping the same memory and buffer cache values.</p>
<p>We also upgraded the snowflake to X Large with Standard type.</p>
<p>We ran with 128 wirekite threads.</p>
<p>This is what we got. A whopping <strong>6 minutes and 9 seconds</strong> to migrate a BILLION rows from Oracle to Snowflake.</p>
<pre><code class="lang-sql">$ cat wirekite.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Fri Mar 14 00:13:06 UTC 2025
FINISH: Fri Mar 14 00:19:15 UTC 2025
ELAPSED: 0 hrs 6 min 9 sec</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[SQL Server to Snowflake - 10 million ops (inserts + updates + deletes) - 1 mins 45 secs]]></title><description><![CDATA[So we set up a Change Data Capture replication pipeline from SQL Server to Snowflake and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark.
Benchmark Details
The most ...]]></description><link>https://benchmarks.wirekite.io/sql-server-to-snowflake-10-million-ops-inserts-updates-deletes-1-mins-45-secs</link><guid isPermaLink="true">https://benchmarks.wirekite.io/sql-server-to-snowflake-10-million-ops-inserts-updates-deletes-1-mins-45-secs</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Wed, 04 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750288884391/fb490b29-4cc2-4915-a2d1-7bd1923097bd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So we set up a Change Data Capture replication pipeline from SQL Server to Snowflake and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark.</p>
<h2 id="heading-benchmark-details">Benchmark Details</h2>
<p>The most important decision here was to determine how to do a replication benchmark, specifically what constitutes a typical load profile of an OLTP database. We realized that a typical OLTP database has the following characteristics</p>
<ul>
<li><p>It has multiple tables.</p>
</li>
<li><p>It has some inserts.</p>
</li>
<li><p>It has somewhat more updates.</p>
</li>
<li><p>It has some deletes.</p>
</li>
<li><p>It has small transactions with lot of commits, mostly single row operations and commits.</p>
</li>
</ul>
<p>Given the above characteristics we decided on doing the following for the benchmark.</p>
<ul>
<li><p>We will have 10 tables.</p>
</li>
<li><p>We will have 2 million single row inserts.</p>
</li>
<li><p>We will have 6 million single row updates.</p>
</li>
<li><p>We will have 2 million single row deletes.</p>
</li>
<li><p>We will have auto commit on, causing all the above operations to have corresponding commit.</p>
</li>
</ul>
<h3 id="heading-table-structure">Table Structure</h3>
<p>We will have 10 tables called firenibble 1 to 10.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> dbo.firenibble1 (
    f0 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
    f1 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f2 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f3 <span class="hljs-built_in">int</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f4 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f5 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f6 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f7 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f8 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f9 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f10 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f11 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f12 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f13 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f14 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f15 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    PRIMARY <span class="hljs-keyword">KEY</span> (f0)
  );
</code></pre>
<h2 id="heading-insert">Insert</h2>
<p>Insert will essentially be new primary key insert.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h2 id="heading-update">Update</h2>
<p>Update will be updating of two columns on a primary key value.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">update</span> firenibble1 <span class="hljs-keyword">set</span> f2 = <span class="hljs-number">280396830734761092</span>, f9 = <span class="hljs-string">'n6ChQjN9dfxIl6nc6SNgIzSahfeXfAef'</span> <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h2 id="heading-delete">Delete</h2>
<p>Delete will be essentially a primary key delete.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">delete</span> <span class="hljs-keyword">from</span> firenibble1 <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h3 id="heading-dml-operations-sequence">DML Operations Sequence</h3>
<p>Then came the question of how do we order the load so that we can rerun the load over and over again and never have to clean up the previous load. So we decided that the load will be such that we will start with 0 rows in all 10 tables, do a bunch of inserts, do a bunch of updates, do a bunch of deletes and end up with 0 rows in all tables. This kept the load and the tables rather clean. So the exact sequence will look like this.</p>
<p>I know we could have been more granular mixing the inserts, updates and deletes even more, and as we do more benchmarks we might try that strategy but for starters this looked pretty good. Also we wanted to see how our replication performed with large number of insert only, update only and delete only loads. 1 million inserts</p>
<ol>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes</p>
</li>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes.</p>
</li>
</ol>
<p>We will also makes sure that all inserts, updates and deletes happen on 10 tables in a sequence so that the operations are granularily staggered over all tables and not contiguous on one table and the next. Which means, the inserts look like this (and so does the updates and deletes).</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble2 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble3 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble4 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble5 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble6 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble7 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble8 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble9 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble10 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h3 id="heading-benchmark-sequence">Benchmark Sequence</h3>
<p>A choice we had was to make was do one of the following</p>
<ol>
<li><p>Have the wirekite replication running. Run the load and wait for the last event of the load to appear on the target. Measure the time between when the load started and the last event appeared.</p>
</li>
<li><p>Run the load and note down the binlog number and position at which the load started and wait for the load to finish. Now start the wirekite replication from the starting binlog number and position and wait for the last event of the load to appear on the target. Measure the time between when the wirekite replication started and the last event appeared on the target.</p>
</li>
</ol>
<p>We decided to go with option 2. The primary reason being that in option 1 wirekite replication was waiting for the events to finish successfully on the database, and essentially we were not only benchmarking wirekite, but also the database, with the boundaries between the two completely blurred. So we preferred the pre-loaded database with the changes, so that we are only benchmarking wirekite and nothing else.</p>
<h2 id="heading-machine-configuration">Machine Configuration</h2>
<p>For SQL Server we created an <strong>n2-standard-16</strong> GCP instance with all the standard configurations - 8 CPU’s and 64 GB RAM in the us-central region. We installed Ubuntu version 24 and SQL Server version 19.</p>
<p>For Snowflake we created a <strong>Large</strong> Size Warehouse with <strong>Standard Type</strong> also in the us-central1 region to minimize the network distance.</p>
<p>We have been using the same configurations for all our benchmarks so that we are comparing apples and apples.</p>
<h2 id="heading-sql-server-run-around">SQL Server Run Around</h2>
<p>SQL Server had a really different change capturing scheme than all the other databases. While all the other databases use a central repository of some kinds to track changes (Oracle stores changes in archive logs, MySQL stores them in binlogs, Postgres uses WAL and so forth), and the changes are also stored serially across this data store. This means that the changes need to be traversed in order and you have really no opportunity for parallelism.</p>
<p>SQL Server took a very different route - they chose to have “change tables”. When you enable change tracking on a given table, a corresponding change table is created with all the columns of the original table as well as some meta columns to track the change order.</p>
<p><a target="_blank" href="https://learn.microsoft.com/en-us/sql/relational-databases/system-tables/cdc-capture-instance-ct-transact-sql?view=sql-server-ver17">https://learn.microsoft.com/en-us/sql/relational-databases/system-tables/cdc-capture-instance-ct-transact-sql?view=sql-server-ver17</a></p>
<p>This means that one can actually have multiple threads tracking changes across multiple tables, and this is why this is one of our fastest benchmark.</p>
<p>Also note that SQL Server chose to use a cryptic LSN ( as opposed to humanly readable SCN in oracle and humanly readable binlog coordinate in MySQL). The fact that it was cryptic made it really difficult to see order in changes since you can’t tell which change happened before/after the other one.</p>
<p>The multi table approach also caused another problem - a transaction that spanned multiple tables appeared in multiple change tables. And SQL Server has no way of telling which tables are involved in a given transaction. So you have to scan all the change tables for a given LSN and stitch it together.</p>
<p>But one of the good things about SQL Server change tracking was that only committed transaction showed up in the change tables, unlike oracle where an uncommitted transaction can happily show up in an archive log, only to become committed in a later archive log. This was a relief.</p>
<h2 id="heading-no-airbyte-run">No Airbyte Run</h2>
<p>We could not do an airbyte run since it requires an enterprise level connector. So this is just our benchmark.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750222710812/d70b4574-7952-4cb0-9dc1-1888aeeffebf.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-wirekite-run">Wirekite Run</h2>
<p>So how long did it take for wirekite to move 10 million changes — <strong>1 minutes and 45 seconds</strong>.</p>
<pre><code class="lang-sql">cat wirekite_cdc.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Tue Jun 17 01:48:14 UTC 2025
FINISH: Tue Jun 17 01:49:59 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 1 min 45 sec</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Oracle to Firebolt - 1B rows - 11 minutes 58 seconds]]></title><description><![CDATA[So after doing Firebolt benchmarks with Postgres and MySQL we went with Oracle. And as always we cranked it up to see how far does it go before crashing the Firebolt engine. And we came pretty close ! One thing I do want to mention here is that we wo...]]></description><link>https://benchmarks.wirekite.io/oracle-to-firebolt-1b-rows-11-minutes-58-seconds</link><guid isPermaLink="true">https://benchmarks.wirekite.io/oracle-to-firebolt-1b-rows-11-minutes-58-seconds</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Tue, 03 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742361096673/06b5a02b-a064-422e-a71c-b9563d66431f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So after doing Firebolt benchmarks with Postgres and MySQL we went with Oracle. And as always we cranked it up to see how far does it go before crashing the Firebolt engine. And we came pretty close ! One thing I do want to mention here is that we would have probably gotten a better benchmark if we had an L sized Firebolt engine. But we are a startup and did not wanted to pay big bucks. <strong>So this benchmark is done with an M sized engine</strong>, even though things have been cranked up a lot on the Oracle side (128 CPU).</p>
<p>I do want to mention here that Firebolt benchmark is a little different, and slightly slower than what it could possibly be and the reason being that our database server is in GCP while our Firebolt bucket is in AWS. That is definitely a network hop, that will do some latency, as opposed to going from GCP to GCP. This probably explains why Firebolt benchmarks are slightly slower.</p>
<p>Also we could not run a benchmark with Airbyte since it is an enterprise license, and we did not want to go that route. Or to be putting it politely we couldn’t afford it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742256412020/d2b92f0d-49dd-42f5-8f8d-15481a3ba7df.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-benchmark-details">Benchmark Details</h1>
<h1 id="heading-table">Table</h1>
<p>As always used our benchmark table. It has 15 columns. The columns are of very canonical datatypes - numbers of all shapes and sizes, medium sized strings and some dates. We wanted to make sure these datatypes can be transferred to most databases.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> app_db.firenibble (
    f0    <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>)    <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
    f1    <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>),
    f2    <span class="hljs-built_in">number</span>(<span class="hljs-number">38</span>),
    f3    <span class="hljs-built_in">int</span>,
    f4    <span class="hljs-built_in">float</span>,
    f5    <span class="hljs-built_in">float</span>,
    f6    <span class="hljs-built_in">float</span>,
    f7    <span class="hljs-built_in">float</span>,
    f8    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    f9    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    f10    <span class="hljs-built_in">date</span>,
    f11    <span class="hljs-built_in">date</span>,
    f12    <span class="hljs-built_in">date</span>,
    f13    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    f14    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    f15    <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">128</span>),
    PRIMARY <span class="hljs-keyword">KEY</span> (f0)
);
</code></pre>
<p>And here’s the 1 Billion rows that we inserted in Oracle.</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">select</span> <span class="hljs-keyword">count</span>(*) <span class="hljs-keyword">from</span> app_db.firenibble;

  COUNT(*)
<span class="hljs-comment">----------</span>
1000000000

1 row selected.

SQL&gt;
</code></pre>
<h1 id="heading-oracle-stuff">Oracle Stuff</h1>
<p>We wanted to mention this a bit to talk about the uphill challenge that was getting oracle to be up and running and importing data into it.</p>
<p>First it was the installation which we thought we could do using the command line. But once we started playing with response files we realized it was almost impossible to get the right response file. There are hundreds of options that go in oracle response file which makes it impossible to find the right combination. We kept on running into errors.</p>
<p>So we decided to use the GUI. Getting X11 forwarding working took some time (that DISPLAY variable) but we were able to do it. But then Oracle GUI would show up with buttons missing from it - <a target="_blank" href="https://forums.oracle.com/ords/apexds/post/19c-runinstaller-shows-blank-screen-for-15-minutes-9680">https://forums.oracle.com/ords/apexds/post/19c-runinstaller-shows-blank-screen-for-15-minutes-9680</a>.</p>
<p>We realized that some given environment variable has to be set to make sure the GUI runs as intended. Once we did that we got the right GUI and got Oracle installed.</p>
<p>And then came the challenge of configuring the database with sensible values so that you can actually load a reasonable amount of data in it. We had to configure</p>
<ul>
<li><p>Configure and start the LISTENER. Understand LISTENER.ORA and TNSNAMES.ORA.</p>
</li>
<li><p>Figure out the differences between PFILE and SPFILE and the workings of SCOPE.</p>
</li>
<li><p>Turn off Automatic Shared Memory Management - MEMORY_TARGET = 0</p>
</li>
<li><p>Turn off Automatic Management - SGA_TARGET = 0</p>
</li>
<li><p>Set SGA_MAX_SIZE</p>
</li>
<li><p>Set DB_CACHE_SIZE</p>
</li>
<li><p>Set SHARED_POOL_SIZE</p>
</li>
<li><p>Set LARGE_POOL_SIZE</p>
</li>
<li><p>Modify a few kernel parameters (SHMMAX, SHMALL, file open limits), modify sysctl.conf and limits.conf and reboot the instance a few times.</p>
</li>
<li><p>Create a separate TABLESPACE to hold the table with the right number and size of data files and make sure they extend automatically.</p>
</li>
<li><p>Grant privileges on this TABLESPACE to the right USER.</p>
</li>
<li><p>Create the table with the right TABLESPACE for data but also the right TABLESPACE for INDEX otherwise it will create index in the default tablespace.</p>
</li>
<li><p>Figure out SQL LOADER to load the data from a csv into the table. Make sure you have the right commit frequency.</p>
</li>
<li><p>Monitor DBA_FREE_SPACE and add data files when it comes close.</p>
</li>
<li><p>Play with V$SESSION and V$SESSION_WAIT to see what is happening.</p>
</li>
<li><p>Play with EXPLAIN PLANS since Oracle gives a thousand ways to see the actual explain plan.</p>
</li>
</ul>
<p>And phew !! You have an oracle database and the table with the data that you desire.</p>
<p>So how does Oracle look like when it is completely pushed to its seams. This is how. As you can see either the wait event is <code>db file sequential read</code> - which means it is going through the primary key index - or it is <code>SQL*Net more data to client</code> - which means it is sending data to the client.</p>
<p>As you can see 128 rows - 128 CPU pushed to their max. Just how we like it.</p>
<pre><code class="lang-sql">INST_ID                                                   WAIT
:SID    USERNAME    MACHINE           SQL_ID      EVENT                  (SEC)
<span class="hljs-comment">------- --------------- ------------------------- --------------- --------------------------------- ------</span>
1:1095    WIREKITE    instance-20240906-204153  g7pakv22nf5k5   db file sequential read         0
1:781    WIREKITE    instance-20240906-204153  fp8p2f77qk3x3   ON CPU                 0
1:973    WIREKITE    instance-20240906-204153  38hztq2rqb641   SQL*Net more data to client         0
1:961    WIREKITE    instance-20240906-204153  5m4sdx6rwq95h   db file sequential read         0
1:1021    WIREKITE    instance-20240906-204153  76s40b7hwpxb0   SQL*Net more data to client         0
1:997    WIREKITE    instance-20240906-204153  bx88bvp7czy31   SQL*Net more data to client         0
1:1285    WIREKITE    instance-20240906-204153  0b9hp762bv399   SQL*Net more data to client         0
1:1083    WIREKITE    instance-20240906-204153  1fv0rnd0d72r5   SQL*Net more data to client         0
1:1153    WIREKITE    instance-20240906-204153  2tyxx90zuk1q2   SQL*Net more data to client         0
1:1237    WIREKITE    instance-20240906-204153  40hw44jqarbg4   ON CPU                 0
1:1178    WIREKITE    instance-20240906-204153  507771twhbkw4   SQL*Net more data to client         0
1:1333    WIREKITE    instance-20240906-204153  5bfubswhvwjn5   SQL*Net more data to client         0
1:1225    WIREKITE    instance-20240906-204153  6wj8brk2db946   db file sequential read         0
1:1273    WIREKITE    instance-20240906-204153  7gctuq46a8rpc   db file sequential read         0
1:1213    WIREKITE    instance-20240906-204153  81vd9na2vtagd   SQL*Net more data to client         0
1:1129    WIREKITE    instance-20240906-204153  99fz5udxxnt85   db file sequential read         0
1:1309    WIREKITE    instance-20240906-204153  9ttgr05j0g4m7   ON CPU                 0
1:1070    WIREKITE    instance-20240906-204153  az9fbzv7v3vuu   SQL*Net more data to client         0
1:1201    WIREKITE    instance-20240906-204153  azbwu204rvra1   db file sequential read         0
1:1046    WIREKITE    instance-20240906-204153  b73m35uvk887d   ON CPU                 0
1:1165    WIREKITE    instance-20240906-204153  bavddw44z91y3   db file sequential read         0
1:1249    WIREKITE    instance-20240906-204153  fsgbvc82873pp   db file sequential read         0
1:1297    WIREKITE    instance-20240906-204153  gp72k5ug0bzqh   SQL*Net more data to client         0
1:290    WIREKITE    instance-20240906-204153  01r6nk321c1mu   ON CPU                 0
1:1381    WIREKITE    instance-20240906-204153  158731r73vt9j   db file sequential read         0
1:1033    WIREKITE    instance-20240906-204153  15kd0wc9g60hb   db file sequential read         0
1:1119    WIREKITE    instance-20240906-204153  4gm01vu41pw4u   ON CPU                 0
1:1261    WIREKITE    instance-20240906-204153  6kf7k1gp9uahy   db file sequential read         0
1:171    WIREKITE    instance-20240906-204153  6npmrk46q0vdj   ON CPU                 0
1:1191    WIREKITE    instance-20240906-204153  8hzk0chgnuqca   db file sequential read         0
1:1345    WIREKITE    instance-20240906-204153  9rrhpfu34wvgg   ON CPU                 0
1:158    WIREKITE    instance-20240906-204153  a4su8wmz91zdk   ON CPU                 0
1:1501    WIREKITE    instance-20240906-204153  dpbnwgk8bm630   SQL*Net more data to client         0
1:75    WIREKITE    instance-20240906-204153  08smhdfa4r4np   ON CPU                 0
1:1    WIREKITE    instance-20240906-204153  0k2au740xs4cy   ON CPU                 0
1:13    WIREKITE    instance-20240906-204153  0mgwahtaumhk3   ON CPU                 0
1:86    WIREKITE    instance-20240906-204153  18bz44xnhfdn6   ON CPU                 0
1:218    WIREKITE    instance-20240906-204153  27h9njd2x453w   ON CPU                 0
1:1393    WIREKITE    instance-20240906-204153  2p2t8du5r4q5b   db file sequential read         0
1:1441    WIREKITE    instance-20240906-204153  2xkr7c5urs9av   db file sequential read         0
1:302    WIREKITE    instance-20240906-204153  315rp762ufvf2   SQL*Net more data to client         0
1:50    WIREKITE    instance-20240906-204153  356628aj189y6   ON CPU                 0
1:1369    WIREKITE    instance-20240906-204153  4q7pqa4awvg13   SQL*Net more data to client         0
1:1357    WIREKITE    instance-20240906-204153  4u08sk6rq38sg   SQL*Net more data to client         0
1:62    WIREKITE    instance-20240906-204153  67mbpqqzz2cvj   ON CPU                 0
1:194    WIREKITE    instance-20240906-204153  6mxdbwnkgg3za   ON CPU                 0
1:134    WIREKITE    instance-20240906-204153  6ud8n88tr1z73   ON CPU                 0
1:278    WIREKITE    instance-20240906-204153  6vr6374cyb99t   db file sequential read         0
1:111    WIREKITE    instance-20240906-204153  6w9102strfqr0   SQL*Net more data to client         0
1:230    WIREKITE    instance-20240906-204153  7ucatg27a5whu   ON CPU                 0
1:1321    WIREKITE    instance-20240906-204153  850fj4fk4ctj6   SQL*Net more data to client         0
1:26    WIREKITE    instance-20240906-204153  bhhwkm7an9w4x   SQL*Net more data to client         0
1:1489    WIREKITE    instance-20240906-204153  cwvpn8r7jmsj4   db file sequential read         0
1:1513    WIREKITE    instance-20240906-204153  fr8xuvzn69n3d   SQL*Net more data to client         0
1:1429    WIREKITE    instance-20240906-204153  2mxxtnudav2jh   SQL*Net more data to client         0
1:531    WIREKITE    instance-20240906-204153  2xdb3g1uj8j76   db file sequential read         0
1:542    WIREKITE    instance-20240906-204153  2xuacbbh7nrtq   ON CPU                 0
1:434    WIREKITE    instance-20240906-204153  39darj310bbpx   ON CPU                 0
1:458    WIREKITE    instance-20240906-204153  3vhftrap7gt7u   ON CPU                 0
1:1465    WIREKITE    instance-20240906-204153  4t492w9zpt8w9   db file sequential read         0
1:410    WIREKITE    instance-20240906-204153  5c3pkzwd61pgm   ON CPU                 0
1:206    WIREKITE    instance-20240906-204153  5hwrfgnwvw59g   ON CPU                 0
1:1417    WIREKITE    instance-20240906-204153  6rhvsb3hxakth   SQL*Net more data to client         0
1:506    WIREKITE    instance-20240906-204153  89tmwx6m7vmpd   ON CPU                 0
1:314    WIREKITE    instance-20240906-204153  959dftbyd3akw   ON CPU                 0
1:326    WIREKITE    instance-20240906-204153  bf4069bm6ac6z   ON CPU                 0
1:494    WIREKITE    instance-20240906-204153  chtd5700kg1y0   ON CPU                 0
1:422    WIREKITE    instance-20240906-204153  d3xv12cs8cpx6   db file sequential read         0
1:374    WIREKITE    instance-20240906-204153  d4amkamq2adv4   SQL*Net more data to client         0
1:446    WIREKITE    instance-20240906-204153  dcsj735hkfwuz   db file sequential read         0
1:242    WIREKITE    instance-20240906-204153  djba5d36155fg   ON CPU                 0
1:254    WIREKITE    instance-20240906-204153  duffm4fk4t0v3   ON CPU                 0
1:338    WIREKITE    instance-20240906-204153  fw0y58p1j9yd8   SQL*Net more data to client         0
1:519    WIREKITE    instance-20240906-204153  gfqzbjtkp73yf   SQL*Net more data to client         0
1:99    WIREKITE    instance-20240906-204153  gpasjhbh4fa8j   ON CPU                 0
1:577    WIREKITE    instance-20240906-204153  015p1b3nbkqvc   ON CPU                 0
1:661    WIREKITE    instance-20240906-204153  0975yasnaj84s   ON CPU                 0
1:398    WIREKITE    instance-20240906-204153  0ynvbuwbfdw07   ON CPU                 0
1:673    WIREKITE    instance-20240906-204153  1ska47yqfpcvk   db file sequential read         0
1:482    WIREKITE    instance-20240906-204153  28gm4phpbf4ac   ON CPU                 0
1:685    WIREKITE    instance-20240906-204153  2gmjbw3jqk679   SQL*Net more data to client         0
1:266    WIREKITE    instance-20240906-204153  3jsdn4ug83781   ON CPU                 0
1:613    WIREKITE    instance-20240906-204153  4y36j319p82b7   SQL*Net more data to client         0
1:735    WIREKITE    instance-20240906-204153  51cvp6bqgz8x2   db file sequential read         0
1:350    WIREKITE    instance-20240906-204153  6afq0f90fr3bm   ON CPU                 0
1:567    WIREKITE    instance-20240906-204153  70qwru3066dmd   db file sequential read         0
1:747    WIREKITE    instance-20240906-204153  84dc8hjzvzp7r   SQL*Net more data to client         0
1:721    WIREKITE    instance-20240906-204153  aa0xj74hkvaga   SQL*Net more data to client         0
1:651    WIREKITE    instance-20240906-204153  aurk5kvvurn0p   SQL*Net more data to client         0
1:591    WIREKITE    instance-20240906-204153  bcyx6agc775c0   db file sequential read         0
1:806    WIREKITE    instance-20240906-204153  c2n80x6mnhxug   ON CPU                 0
1:1453    WIREKITE    instance-20240906-204153  c7q8qmck82c0t   db file sequential read         0
1:147    WIREKITE    instance-20240906-204153  cc13fpt8x6333   db file sequential read         0
1:1143    WIREKITE    instance-20240906-204153  cck3huajnx049   ON CPU                 0
1:603    WIREKITE    instance-20240906-204153  chvpbd00683mn   ON CPU                 0
1:1477    WIREKITE    instance-20240906-204153  ck08wccrdj779   db file sequential read         0
1:697    WIREKITE    instance-20240906-204153  dcfqd69fu43r6   SQL*Net more data to client         0
1:637    WIREKITE    instance-20240906-204153  fqu65yb2z41g4   ON CPU                 0
1:709    WIREKITE    instance-20240906-204153  gc1khr7cb0jkr   db file sequential read         0
1:771    WIREKITE    instance-20240906-204153  0bbhpg4xh1quz   SQL*Net more data to client         0
1:914    WIREKITE    instance-20240906-204153  0p963knq6ug5k   ON CPU                 0
1:962    WIREKITE    instance-20240906-204153  0yfrquyhguvkk   SQL*Net more data to client         0
1:842    WIREKITE    instance-20240906-204153  2csqptc251j6m   db file sequential read         0
1:855    WIREKITE    instance-20240906-204153  2qy7dp5h6j683   db file sequential read         0
1:903    WIREKITE    instance-20240906-204153  5zttc28j8an72   SQL*Net more data to client         0
1:626    WIREKITE    instance-20240906-204153  6488r8g08pg98   ON CPU                 0
1:867    WIREKITE    instance-20240906-204153  6czbxsbpt40pa   SQL*Net more data to client         0
1:782    WIREKITE    instance-20240906-204153  9rx1amu5t7687   db file sequential read         0
1:891    WIREKITE    instance-20240906-204153  ar1u44uu4duc8   SQL*Net more data to client         0
1:819    WIREKITE    instance-20240906-204153  atb6tt99g545d   db file sequential read         0
1:759    WIREKITE    instance-20240906-204153  dtvncwjyn7q5w   SQL*Net more data to client         0
1:795    WIREKITE    instance-20240906-204153  du8vgs1fa71dc   SQL*Net more data to client         0
1:879    WIREKITE    instance-20240906-204153  f5mx7ufxd69nb   ON CPU                 0
1:831    WIREKITE    instance-20240906-204153  fs4fmhy0m526q   db file sequential read         0
1:122    WIREKITE    instance-20240906-204153  g8pjrt41acun3   ON CPU                 0
1:986    WIREKITE    instance-20240906-204153  0860mtbbqascq   db file sequential read         0
1:974    WIREKITE    instance-20240906-204153  7npm3f6qsgv96   SQL*Net more data to client         0
1:470    WIREKITE    instance-20240906-204153  7s0ksx9hw8y60   ON CPU                 0
1:927    WIREKITE    instance-20240906-204153  f4g4puxbhnjz3   SQL*Net more data to client         0
1:1358    WIREKITE    instance-20240906-204153  1njp9bm8ndt0s   SQL*Net more data to client         0
1:1346    WIREKITE    instance-20240906-204153  6bg4w57gv8h98   SQL*Net more data to client         0
1:1130    WIREKITE    instance-20240906-204153  70m7j9dgx8fdk   db file sequential read         0
1:1202    WIREKITE    instance-20240906-204153  89phb3p3vxtbx   ON CPU                 0
1:1226    WIREKITE    instance-20240906-204153  g5pp3j89hxnky   SQL*Net more data to client         0
1:1177    WIREKITE    instance-20240906-204153  gt1gg8k4ukpad   SQL*Net more data to client         0
1:1154    WIREKITE    instance-20240906-204153  3sukb15sm2fyp   SQL*Net more data to client         0
1:1370    WIREKITE    instance-20240906-204153  dwcphffv8vn15   db file sequential read         0
1:145    SYS        instance-20240906-204153  nul          *IDLE* OFS idle             3

128 rows selected.

SQL&gt;
</code></pre>
<h1 id="heading-firebolt-stuff">Firebolt Stuff</h1>
<p>Firebolt has been a very interesting ride. They have decided on some very serious Engineering Tradeoffs. Their focus is just speed. And anything that comes in the way needs to go !!</p>
<p>We like it.</p>
<p>But they did not have a Command Line Utility. Which is a bit strange for a Database company focussed on creating a gnarly engineering product.</p>
<p><strong>So we build our own Command Line Utility !!</strong></p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"M"</span> NODES = <span class="hljs-number">5</span> MIN_CLUSTERS=<span class="hljs-number">1</span> MAX_CLUSTERS = <span class="hljs-number">2</span> FAMILY=CO;
ok
=&gt; <span class="hljs-keyword">show</span> <span class="hljs-keyword">engines</span>;
1: engine_name: my_engine
1: engine_owner: sandhu.nurat
1: type: M
1: family: COMPUTE_OPTIMIZED
1: nodes: 5
1: clusters: 1
1: status: RUNNING
1: auto_start: 1
1: auto_stop: 20
1: initially_stopped: 0
1: url: account-1-ewafh.api.us-east-1.app.firebolt.io?engine=my_engine
1: default_database:
1: version: 4.16.8
1: last_started: 2025-03-16 20:29:35.366
1: last_stopped: 2025-03-16 20:20:19.808
1: description:
1: fbu_rate: 40
=&gt;
</code></pre>
<p>You can use it to check tables and various properties.</p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">show</span> <span class="hljs-keyword">tables</span>;
1: table_name: firenibble
1: table_type: BASE TABLE
1: column_count: 16
1: primary_index: f0
1: schema: <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-string">"firenibble"</span> (<span class="hljs-string">"f0"</span> <span class="hljs-built_in">BIGINT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f1"</span> <span class="hljs-built_in">BIGINT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f2"</span> <span class="hljs-built_in">BIGINT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f3"</span> <span class="hljs-built_in">INTEGER</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f4"</span> <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f5"</span> <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f6"</span> <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f7"</span> <span class="hljs-keyword">DOUBLE</span> <span class="hljs-keyword">PRECISION</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f8"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f9"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f10"</span> <span class="hljs-built_in">DATE</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f11"</span> <span class="hljs-built_in">DATE</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f12"</span> <span class="hljs-built_in">DATE</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f13"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f14"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>, <span class="hljs-string">"f15"</span> <span class="hljs-built_in">TEXT</span> <span class="hljs-literal">NULL</span>) PRIMARY <span class="hljs-keyword">INDEX</span> <span class="hljs-string">"f0"</span>
<span class="hljs-number">1</span>: number_of_rows: <span class="hljs-number">1000000000</span>
<span class="hljs-number">1</span>: compressed_bytes: <span class="hljs-number">216.93</span> GiB
<span class="hljs-number">1</span>: uncompressed_bytes: <span class="hljs-number">234.69</span> GiB
<span class="hljs-number">1</span>: compression_ratio: <span class="hljs-number">1</span>
<span class="hljs-number">1</span>: number_of_tablets: <span class="hljs-number">1586</span>
=&gt;
</code></pre>
<h1 id="heading-machine-configuration">Machine Configuration</h1>
<p>For Firebolt we created an engine with <strong>M size (medium), 5 nodes, 2 clusters and it was COMPUTE_OPTIMIZED</strong>. We created the engine in us-east region. Firebolt does not offer us-central region. Also Firebolt does not offer L size by default that other cloud vendors offer. We got the following message when we tried to upgrade our engine.</p>
<pre><code class="lang-sql"> =&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"L"</span> NODES = <span class="hljs-number">5</span> MIN_CLUSTERS=<span class="hljs-number">1</span> MAX_CLUSTERS = <span class="hljs-number">2</span>;
2025/03/15 22:46:31 ERROR query <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"L"</span> NODES = <span class="hljs-number">5</span> MIN_CLUSTERS=<span class="hljs-number">1</span> MAX_CLUSTERS = <span class="hljs-number">2</span> <span class="hljs-keyword">failed</span>: <span class="hljs-keyword">error</span> during <span class="hljs-keyword">query</span> execution: <span class="hljs-keyword">error</span> during <span class="hljs-keyword">query</span> request: <span class="hljs-keyword">Alter</span> <span class="hljs-keyword">engine</span> failed. <span class="hljs-string">'L'</span> node <span class="hljs-keyword">type</span> <span class="hljs-keyword">is</span> currently <span class="hljs-keyword">in</span> preview. Reach <span class="hljs-keyword">out</span> <span class="hljs-keyword">to</span> Firebolt Support <span class="hljs-keyword">to</span> <span class="hljs-keyword">enable</span> <span class="hljs-string">'L'</span> node <span class="hljs-keyword">type</span> <span class="hljs-keyword">for</span> this <span class="hljs-keyword">account</span>
=&gt;
</code></pre>
<h1 id="heading-wirekite-run-1">Wirekite Run 1</h1>
<p>We had a standard 64 CPU GCP instance with 256 GB RAM. The host was Linux RHEL8 with Oracle version 19c. The machine lived in us-central1 region. We rebooted instances between runs.</p>
<p>We ran with 64 wirekite threads.</p>
<p>We have been using the same configurations for all our benchmarks so that we are comparing apples and apples.</p>
<p>And this was the result. It took about <strong>16 minutes</strong> to move 1 billion rows from oracle to firebolt.</p>
<pre><code class="lang-sql">$ cat wirekite.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Sun Mar 16 02:36:51 UTC 2025
FINISH: Sun Mar 16 02:53:15 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 16 min 24 sec</span>
</code></pre>
<h1 id="heading-wirekite-run-2">Wirekite Run 2</h1>
<p>We upped the source oracle instance to 128 CPU with 512 GB RAM. Rest everything remains same. This also forces an Oracle instance start and makes the buffer cold.</p>
<p>We ran with 128 threads.</p>
<p>We migrated <strong>1 BILLION rows in 11 minutes and 58 seconds.</strong></p>
<pre><code class="lang-sql">$ cat wirekite.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Sun Mar 16 03:50:35 UTC 2025
FINISH: Sun Mar 16 04:02:33 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 11 min 58 sec</span>
</code></pre>
<p>And here’s the 1 Billion rows.</p>
<pre><code class="lang-sql">INFO[0000]log.go:182 gofirebolt.(*defaultLogger).Infof Credentials <span class="hljs-keyword">cache</span> <span class="hljs-keyword">path</span>: /home/ziggy/.cache/firebolt/temporary_credential.json
firebolt <span class="hljs-keyword">instance</span> <span class="hljs-keyword">connect</span> successful
=&gt; <span class="hljs-keyword">select</span> <span class="hljs-keyword">count</span>(*) <span class="hljs-keyword">as</span> <span class="hljs-keyword">count</span> <span class="hljs-keyword">from</span> firenibble;
1: count: 1000000000
</code></pre>
<p>And on the GUI</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742257670917/d4585871-02ea-4e9a-b920-3ebafb919248.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[SQL Server to Firebolt - 10 million ops (inserts + updates + deletes) - 1 mins 13 secs]]></title><description><![CDATA[So we set up a Change Data Capture replication pipeline from SQL Server to Firebolt and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark.
I do want to mention here th...]]></description><link>https://benchmarks.wirekite.io/sql-server-to-firebolt-10-million-ops-inserts-updates-deletes-1-mins-13-secs</link><guid isPermaLink="true">https://benchmarks.wirekite.io/sql-server-to-firebolt-10-million-ops-inserts-updates-deletes-1-mins-13-secs</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Tue, 03 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1749882228209/40ec96db-530f-4a66-8d87-6612b9881df5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So we set up a Change Data Capture replication pipeline from SQL Server to Firebolt and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark.</p>
<p>I do want to mention here that Firebolt benchmark is a little different, and slightly slower than what it could possibly be and the reason being that our database server is in GCP while our Firebolt bucket is in AWS. That is definitely a network hop, that will do some latency, as opposed to going from GCP to GCP. This probably explains why Firebolt benchmarks are slightly slower.</p>
<h2 id="heading-benchmark-details">Benchmark Details</h2>
<p>The most important decision here was to determine how to do a replication benchmark, specifically what constitutes a typical load profile of an OLTP database. We realized that a typical OLTP database has the following characteristics</p>
<ul>
<li><p>It has multiple tables.</p>
</li>
<li><p>It has some inserts.</p>
</li>
<li><p>It has somewhat more updates.</p>
</li>
<li><p>It has some deletes.</p>
</li>
<li><p>It has small transactions with lot of commits, mostly single row operations and commits.</p>
</li>
</ul>
<p>Given the above characteristics we decided on doing the following for the benchmark.</p>
<ul>
<li><p>We will have 10 tables.</p>
</li>
<li><p>We will have 2 million single row inserts.</p>
</li>
<li><p>We will have 6 million single row updates.</p>
</li>
<li><p>We will have 2 million single row deletes.</p>
</li>
<li><p>We will have auto commit on, causing all the above operations to have corresponding commit.</p>
</li>
</ul>
<h3 id="heading-table-structure">Table Structure</h3>
<p>We will have 10 tables called firenibble 1 to 10.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> dbo.firenibble1 (
    f0 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
    f1 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f2 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f3 <span class="hljs-built_in">int</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f4 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f5 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f6 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f7 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f8 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f9 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f10 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f11 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f12 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f13 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f14 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f15 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    PRIMARY <span class="hljs-keyword">KEY</span> (f0)
  );
</code></pre>
<h2 id="heading-insert">Insert</h2>
<p>Insert will essentially be new primary key insert.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h2 id="heading-update">Update</h2>
<p>Update will be updating of two columns on a primary key value.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">update</span> firenibble1 <span class="hljs-keyword">set</span> f2 = <span class="hljs-number">280396830734761092</span>, f9 = <span class="hljs-string">'n6ChQjN9dfxIl6nc6SNgIzSahfeXfAef'</span> <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h2 id="heading-delete">Delete</h2>
<p>Delete will be essentially a primary key delete.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">delete</span> <span class="hljs-keyword">from</span> firenibble1 <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h3 id="heading-dml-operations-sequence">DML Operations Sequence</h3>
<p>Then came the question of how do we order the load so that we can rerun the load over and over again and never have to clean up the previous load. So we decided that the load will be such that we will start with 0 rows in all 10 tables, do a bunch of inserts, do a bunch of updates, do a bunch of deletes and end up with 0 rows in all tables. This kept the load and the tables rather clean. So the exact sequence will look like this.</p>
<p>I know we could have been more granular mixing the inserts, updates and deletes even more, and as we do more benchmarks we might try that strategy but for starters this looked pretty good. Also we wanted to see how our replication performed with large number of insert only, update only and delete only loads. 1 million inserts</p>
<ol>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes</p>
</li>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes.</p>
</li>
</ol>
<p>We will also makes sure that all inserts, updates and deletes happen on 10 tables in a sequence so that the operations are granularily staggered over all tables and not contiguous on one table and the next. Which means, the inserts look like this (and so does the updates and deletes).</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble2 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble3 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble4 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble5 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble6 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble7 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble8 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble9 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble10 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h3 id="heading-benchmark-sequence">Benchmark Sequence</h3>
<p>A choice we had was to make was do one of the following</p>
<ol>
<li><p>Have the wirekite replication running. Run the load and wait for the last event of the load to appear on the target. Measure the time between when the load started and the last event appeared.</p>
</li>
<li><p>Run the load and note down the binlog number and position at which the load started and wait for the load to finish. Now start the wirekite replication from the starting binlog number and position and wait for the last event of the load to appear on the target. Measure the time between when the wirekite replication started and the last event appeared on the target.</p>
</li>
</ol>
<p>We decided to go with option 2. The primary reason being that in option 1 wirekite replication was waiting for the events to finish successfully on the database, and essentially we were not only benchmarking wirekite, but also the database, with the boundaries between the two completely blurred. So we preferred the pre-loaded database with the changes, so that we are only benchmarking wirekite and nothing else.</p>
<h2 id="heading-machine-configuration">Machine Configuration</h2>
<p>For SQL Server we created an <strong>n2-standard-16</strong> GCP instance with all the standard configurations - 8 CPU’s and 64 GB RAM in the us-central region. We installed Ubuntu version 24 and SQL Server version 19.</p>
<p>For Firebolt we created a <strong>Medium</strong> Size Warehouse also in the us-central1 region to minimize the network distance.</p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"M"</span> NODES = <span class="hljs-number">5</span> MIN_CLUSTERS=<span class="hljs-number">1</span> MAX_CLUSTERS = <span class="hljs-number">2</span> FAMILY=CO;
ok
</code></pre>
<p>We have been using the same configurations for all our benchmarks so that we are comparing apples and apples.</p>
<h2 id="heading-sql-server-run-around">SQL Server Run Around</h2>
<p>SQL Server had a really different change capturing scheme than all the other databases. While all the other databases use a central repository of some kinds to track changes (Oracle stores changes in archive logs, MySQL stores them in binlogs, Postgres uses WAL and so forth), and the changes are also stored serially across this data store. This means that the changes need to be traversed in order and you have really no opportunity for parallelism.</p>
<p>SQL Server took a very different route - they chose to have “change tables”. When you enable change tracking on a given table, a corresponding change table is created with all the columns of the original table as well as some meta columns to track the change order.</p>
<p><a target="_blank" href="https://learn.microsoft.com/en-us/sql/relational-databases/system-tables/cdc-capture-instance-ct-transact-sql?view=sql-server-ver17">https://learn.microsoft.com/en-us/sql/relational-databases/system-tables/cdc-capture-instance-ct-transact-sql?view=sql-server-ver17</a></p>
<p>This means that one can actually have multiple threads tracking changes across multiple tables, and this is why this is one of our fastest benchmark.</p>
<p>Also note that SQL Server chose to use a cryptic LSN ( as opposed to humanly readable SCN in oracle and humanly readable binlog coordinate in MySQL). The fact that it was cryptic made it really difficult to see order in changes since you can’t tell which change happened before/after the other one.</p>
<p>The multi table approach also caused another problem - a transaction that spanned multiple tables appeared in multiple change tables. And SQL Server has no way of telling which tables are involved in a given transaction. So you have to scan all the change tables for a given LSN and stitch it together.</p>
<p>But one of the good things about SQL Server change tracking was that only committed transaction showed up in the change tables, unlike oracle where an uncommitted transaction can happily show up in an archive log, only to become committed in a later archive log. This was a relief.</p>
<h2 id="heading-no-airbyte-run">No Airbyte Run</h2>
<p>We could not do an airbyte run since it requires an enterprise level connector. So this is just our benchmark.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749796520303/d7dba388-02aa-4397-a53d-f19ab7bb181b.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-wirekite-run">Wirekite Run</h2>
<p>So how long did it take for wirekite to move 10 million changes — <strong>1 minutes and 13 seconds</strong>.</p>
<pre><code class="lang-sql">cat wirekite_cdc.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Fri Jun 13 05:07:24 UTC 2025
FINISH: Fri Jun 13 05:08:37 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 1 min 13 sec</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[PostgreSQL to Snowflake - 10 million ops (inserts + updates + deletes) - 3 mins 52 secs]]></title><description><![CDATA[So we set up a Change Data Capture replication pipeline from PostgreSQL to Snowflake and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark.
Benchmark Details
The most ...]]></description><link>https://benchmarks.wirekite.io/postgresql-to-snowflake-10-million-ops-inserts-updates-deletes-3-mins-52-secs</link><guid isPermaLink="true">https://benchmarks.wirekite.io/postgresql-to-snowflake-10-million-ops-inserts-updates-deletes-3-mins-52-secs</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Mon, 02 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747851132134/72e760b5-4d84-43c4-a1b0-20a50946b60b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So we set up a Change Data Capture replication pipeline from PostgreSQL to Snowflake and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark.</p>
<h2 id="heading-benchmark-details">Benchmark Details</h2>
<p>The most important decision here was to determine how to do a replication benchmark, specifically what constitutes a typical load profile of an OLTP database. We realized that a typical OLTP database has the following characteristics</p>
<ul>
<li><p>It has multiple tables.</p>
</li>
<li><p>It has some inserts.</p>
</li>
<li><p>It has somewhat more updates.</p>
</li>
<li><p>It has some deletes.</p>
</li>
<li><p>It has small transactions with lot of commits, mostly single row operations and commits.</p>
</li>
</ul>
<p>Given the above characteristics we decided on doing the following for the benchmark.</p>
<ul>
<li><p>We will have 10 tables.</p>
</li>
<li><p>We will have 2 million single row inserts.</p>
</li>
<li><p>We will have 6 million single row updates.</p>
</li>
<li><p>We will have 2 million single row deletes.</p>
</li>
<li><p>We will have auto commit on, causing all the above operations to have corresponding commit.</p>
</li>
</ul>
<h3 id="heading-table-structure">Table Structure</h3>
<p>We will have 10 tables called firenibble 1 to 10.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> public.firenibble1 (
  f0 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  f1 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f2 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f3 <span class="hljs-built_in">int</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f4 float8 <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f5 float8 <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f6 float8 <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f7 float8 <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f8 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f9 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f10 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f11 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f12 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f13 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f14 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f15 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  PRIMARY <span class="hljs-keyword">KEY</span> (f0)
) ;
</code></pre>
<h2 id="heading-insert">Insert</h2>
<p>Insert will essentially be new primary key insert.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h2 id="heading-update">Update</h2>
<p>Update will be updating of two columns on a primary key value.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">update</span> firenibble1 <span class="hljs-keyword">set</span> f2 = <span class="hljs-number">280396830734761092</span>, f9 = <span class="hljs-string">'n6ChQjN9dfxIl6nc6SNgIzSahfeXfAef'</span> <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h2 id="heading-delete">Delete</h2>
<p>Delete will be essentially a primary key delete.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">delete</span> <span class="hljs-keyword">from</span> firenibble1 <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h3 id="heading-dml-operations-sequence">DML Operations Sequence</h3>
<p>Then came the question of how do we order the load so that we can rerun the load over and over again and never have to clean up the previous load. So we decided that the load will be such that we will start with 0 rows in all 10 tables, do a bunch of inserts, do a bunch of updates, do a bunch of deletes and end up with 0 rows in all tables. This kept the load and the tables rather clean. So the exact sequence will look like this. I know we could have been more granular mixing the inserts, updates and deletes even more, and as we do more benchmarks we might try that strategy but for starters this looked pretty good. Also we wanted to see how our replication performed with large number of insert only, update only and delete only loads. Also note that there is no relationships between the load and the change logs, in the sense there is no flush binary logs happening anywhere causing the inserts, updates and deletes to cross binary log boundaries.</p>
<ol>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes</p>
</li>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes.</p>
</li>
</ol>
<p>We will also makes sure that all inserts, updates and deletes happen on 10 tables in a sequence so that the operations are granularily staggered over all tables and not contiguous on one table and the next. Which means, the inserts look like this (and so does the updates and deletes).</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble2 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble3 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble4 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble5 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble6 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble7 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble8 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble9 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble10 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h2 id="heading-benchmark-sequence">Benchmark Sequence</h2>
<p>A choice we had was to make was do one of the following</p>
<ol>
<li><p>Have the wirekite replication running. Run the load and wait for the last event of the load to appear on the target. Measure the time between when the load started and the last event appeared.</p>
</li>
<li><p>Run the load and note down the binlog number and position at which the load started and wait for the load to finish. Now start the wirekite replication from the starting binlog number and position and wait for the last event of the load to appear on the target. Measure the time between when the wirekite replication started and the last event appeared on the target.</p>
</li>
</ol>
<p>We decided to go with option 2. The primary reason being that in option 1 wirekite replication was waiting for the events to finish successfully on the database, and essentially we were not only benchmarking wirekite, but also the database, with the boundaries between the two completely blurred. So we preferred the pre-loaded database with the changes, so that we are only benchmarking wirekite and nothing else.</p>
<h2 id="heading-machine-configuration">Machine Configuration</h2>
<p>For Postgres we created an <strong>n2-standard-16</strong> GCP instance with all the standard configurations - 8 CPU’s and 64 GB RAM in the us-central region. We installed Ubuntu version 24 and Oracle version 19. Our archive log size was 330 MB.</p>
<p>For Snowflake we created a <strong>Large</strong> Size Warehouse with <strong>Standard Type</strong> also in the us-central1 region to minimize the network distance.</p>
<p>We have been using the same configurations for all our benchmarks so that we are comparing apples and apples.</p>
<h2 id="heading-wirekite-run">Wirekite Run</h2>
<p>So how long did it take for wirekite to move 10 million changes — <strong>3 minutes and 52 seconds</strong>.</p>
<pre><code class="lang-sql">cat wirekite_cdc.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Tue May 13 06:46:30 UTC 2025
FINISH: Tue May 13 06:50:22 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 4 min 5 sec</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[SQL Server to Snowflake - 1B rows - 10 minutes 52 seconds]]></title><description><![CDATA[So one more benchmark except this time with a really expensive enterprise grade database.
We could not compare this benchmark with Airbyte since Airbyte does not allow an open source connector for SQL Server. Entirely understandable. When we tried to...]]></description><link>https://benchmarks.wirekite.io/sql-server-to-snowflake-1b-rows-10-minutes-52-seconds</link><guid isPermaLink="true">https://benchmarks.wirekite.io/sql-server-to-snowflake-1b-rows-10-minutes-52-seconds</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Mon, 02 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750288622436/e839071f-22f6-4cfa-a8d8-27c935891287.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So one more benchmark except this time with a really expensive enterprise grade database.</p>
<p>We could not compare this benchmark with Airbyte since Airbyte does not allow an open source connector for SQL Server. Entirely understandable. When we tried to configure the connector after spending a long time installing Airbyte we got the following message.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750279158509/336a9a92-3d37-40f9-ae64-86e088d9dd76.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-benchmark-details">Benchmark Details</h2>
<p>As usual we will use our firenibble table with 1 Billion rows. That’s a lot of rows.</p>
<p>Since we could not do an Airbyte benchmark we decided to play a little bit with SQL Server and see how far we can scale our benchmarks as we increased the source SQL Server machine configuration, the target Snowflake configurations and the number of wirekite threads.</p>
<h2 id="heading-table">Table</h2>
<p>As usual we used our standard firenibble table.</p>
<p>The table has 16 columns, one of them is a numeric primary key, few columns are numbers of various shapes and sizes, few strings and few dates. This makes the table pretty simple to be absorbed by most databases.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> dbo.firenibble (
    f0 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
    f1 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f2 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f3 <span class="hljs-built_in">int</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f4 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f5 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f6 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f7 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f8 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f9 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f10 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f11 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f12 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f13 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f14 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f15 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    PRIMARY <span class="hljs-keyword">KEY</span> (f0)
  );
</code></pre>
<p>The table also has 1 Billion rows.</p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">select</span> <span class="hljs-keyword">count</span>(*) <span class="hljs-keyword">from</span> dbo.firenibble1;
1: : 1000000000
=&gt;
</code></pre>
<h2 id="heading-loading-data-in-sql-server">Loading Data in SQL Server</h2>
<p>We used the following command to load the 1 Billion rows in the firenibble table. It took sometime but it worked.</p>
<pre><code class="lang-sql">BULK <span class="hljs-keyword">INSERT</span> dbo.firenibble <span class="hljs-keyword">FROM</span> <span class="hljs-string">'/mnt/spinning/csv/firenibble.csv'</span> <span class="hljs-keyword">WITH</span> (FIELDTERMINATOR = <span class="hljs-string">'\t'</span>, ROWTERMINATOR = <span class="hljs-string">'\n'</span>, FIRSTROW = <span class="hljs-number">1</span>, BATCHSIZE=<span class="hljs-number">5000</span>);
</code></pre>
<h2 id="heading-wirekite-run-1">Wirekite Run 1</h2>
<p>We had a standard 128 CPU GCP instance with 512 GB RAM. The host was Linux Ubuntu 20.04 with SQL Server version 2022. The machine lived in us-central1 region. We rebooted instances between runs.</p>
<p>For Snowflake we created a Large size warehouse with Standard Type also in the us-central1 region to minimize the network distance.</p>
<p>We ran with <strong>96 wirekite threads</strong>.</p>
<p>And it took about <strong>10 minutes and 55 seconds</strong>.</p>
<pre><code class="lang-sql">cat wirekite.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Mon Jun 16 23:58:11 UTC 2025
FINISH: Tue Jun 17 00:09:06 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 10 min 55 sec</span>
</code></pre>
<h2 id="heading-wirekite-run-2">Wirekite Run 2</h2>
<p>Ran with same machine configurations but with 90 threads and got this - <strong>10 minutes and 58 seconds</strong>. Oops the time increased.</p>
<pre><code class="lang-sql">cat wirekite.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Tue Jun 17 00:11:11 UTC 2025
FINISH: Tue Jun 17 00:22:09 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 10 min 58 sec</span>
</code></pre>
<h2 id="heading-wirekite-run-3">Wirekite Run 3</h2>
<p>This time we ran with <strong>84 threads</strong> and got our best time.</p>
<p>Moved 1 billion rows from SQL Server to Snowflake in <strong>10 minutes and 52 seconds.</strong></p>
<pre><code class="lang-sql">cat wirekite.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Mon Jun 16 23:44:02 UTC 2025
FINISH: Mon Jun 16 23:54:54 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 10 min 52 sec</span>
</code></pre>
<p>I think there is still scope for improvement.</p>
]]></content:encoded></item><item><title><![CDATA[SQL Server to Firebolt - 1B rows - 12 minutes 19 seconds]]></title><description><![CDATA[So one more benchmark except this time with a really expensive enterprise grade database.
I do want to mention here that Firebolt benchmark is a little different, and slightly slower than what it could possibly be and the reason being that our databa...]]></description><link>https://benchmarks.wirekite.io/sql-server-to-firebolt-1b-rows-12-minutes-19-seconds</link><guid isPermaLink="true">https://benchmarks.wirekite.io/sql-server-to-firebolt-1b-rows-12-minutes-19-seconds</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Sun, 01 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750288238111/234c180b-435f-47bc-a1da-f23687e8e6e8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So one more benchmark except this time with a really expensive enterprise grade database.</p>
<p>I do want to mention here that Firebolt benchmark is a little different, and slightly slower than what it could possibly be and the reason being that our database server is in GCP while our Firebolt bucket is in AWS. That is definitely a network hop, that will do some latency, as opposed to going from GCP to GCP. This probably explains why Firebolt benchmarks are slightly slower.</p>
<p>We could not compare this benchmark with Airbyte since Airbyte does not allow an open source connector for SQL Server. Entirely understandable. When we tried to configure the connector after spending a long time installing Airbyte we got the following message.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750281836874/88ca9543-9cb7-4790-9abe-a03ca80871a3.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-benchmark-details">Benchmark Details</h2>
<p>As usual we will use our firenibble table with 1 Billion rows. That’s a lot of rows.</p>
<p>Since we could not do an Airbyte benchmark we decided to play a little bit with SQL Server and see how far we can scale our benchmarks as we increased the source SQL Server machine configuration, the target Snowflake configurations and the number of wirekite threads.</p>
<h2 id="heading-table">Table</h2>
<p>As usual we used our standard firenibble table.</p>
<p>The table has 16 columns, one of them is a numeric primary key, few columns are numbers of various shapes and sizes, few strings and few dates. This makes the table pretty simple to be absorbed by most databases.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> dbo.firenibble (
    f0 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
    f1 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f2 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f3 <span class="hljs-built_in">int</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f4 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f5 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f6 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f7 <span class="hljs-built_in">float</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f8 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f9 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f10 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f11 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f12 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f13 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f14 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    f15 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
    PRIMARY <span class="hljs-keyword">KEY</span> (f0)
  );
</code></pre>
<p>The table also has 1 Billion rows.</p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">select</span> <span class="hljs-keyword">count</span>(*) <span class="hljs-keyword">from</span> dbo.firenibble1;
1: : 1000000000
=&gt;
</code></pre>
<h2 id="heading-loading-data-in-sql-server">Loading Data in SQL Server</h2>
<p>We used the following command to load the 1 Billion rows in the firenibble table. It took sometime but it worked.</p>
<pre><code class="lang-sql">BULK <span class="hljs-keyword">INSERT</span> dbo.firenibble <span class="hljs-keyword">FROM</span> <span class="hljs-string">'/mnt/spinning/csv/firenibble.csv'</span> <span class="hljs-keyword">WITH</span> (FIELDTERMINATOR = <span class="hljs-string">'\t'</span>, ROWTERMINATOR = <span class="hljs-string">'\n'</span>, FIRSTROW = <span class="hljs-number">1</span>, BATCHSIZE=<span class="hljs-number">5000</span>);
</code></pre>
<h2 id="heading-wirekite-run-1">Wirekite Run 1</h2>
<p>We had a standard 128 CPU GCP instance with 512 GB RAM. The host was Linux Ubuntu 20.04 with SQL Server version 2022. The machine lived in us-central1 region. We rebooted instances between runs.</p>
<p>For Firebolt we created a <strong>Medium</strong> Size Warehouse also in the us-central1 region to minimize the network distance.</p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"M"</span> NODES = <span class="hljs-number">5</span> MIN_CLUSTERS=<span class="hljs-number">1</span> MAX_CLUSTERS = <span class="hljs-number">2</span> FAMILY=CO;
ok
</code></pre>
<p>We ran with <strong>84 wirekite threads</strong>.</p>
<p>And it took about <strong>12 minutes and 35 seconds</strong>.</p>
<pre><code class="lang-sql">cat wirekite.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Sun Jun 15 05:39:39 UTC 2025
FINISH: Sun Jun 15 05:52:14 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 12 min 35 sec</span>
</code></pre>
<h2 id="heading-wirekite-run-2">Wirekite Run 2</h2>
<p>This time we ran with <strong>96 threads</strong> and got our best time.</p>
<p>Moved 1 billion rows from SQL Server to Firebolt in <strong>12 minutes and 19 seconds.</strong></p>
<pre><code class="lang-sql">cat wirekite.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Sun Jun 15 05:39:39 UTC 2025
FINISH: Sun Jun 15 05:52:14 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 12 min 35 sec</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[PostgreSQL to Firebolt - 10 million ops (inserts + updates + deletes) - 2 mins 18 secs]]></title><description><![CDATA[So we set up a Change Data Capture replication pipeline from PostgreSQL to Firebolt and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark.
Benchmark Details
The most i...]]></description><link>https://benchmarks.wirekite.io/postgresql-to-firebolt-10-million-ops-inserts-updates-deletes-2-mins-18-secs</link><guid isPermaLink="true">https://benchmarks.wirekite.io/postgresql-to-firebolt-10-million-ops-inserts-updates-deletes-2-mins-18-secs</guid><dc:creator><![CDATA[Wirekite]]></dc:creator><pubDate>Sun, 01 Jun 2025 07:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750288790058/6e731045-caba-44eb-9f28-ac28e14b24b9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So we set up a Change Data Capture replication pipeline from PostgreSQL to Firebolt and wanted to benchmark how it performs under a “typical” OLTP load. This article discusses the various characteristics of the benchmark.</p>
<h2 id="heading-benchmark-details">Benchmark Details</h2>
<p>The most important decision here was to determine how to do a replication benchmark, specifically what constitutes a typical load profile of an OLTP database. We realized that a typical OLTP database has the following characteristics</p>
<ul>
<li><p>It has multiple tables.</p>
</li>
<li><p>It has some inserts.</p>
</li>
<li><p>It has somewhat more updates.</p>
</li>
<li><p>It has some deletes.</p>
</li>
<li><p>It has small transactions with lot of commits, mostly single row operations and commits.</p>
</li>
</ul>
<p>Given the above characteristics we decided on doing the following for the benchmark.</p>
<ul>
<li><p>We will have 10 tables.</p>
</li>
<li><p>We will have 2 million single row inserts.</p>
</li>
<li><p>We will have 6 million single row updates.</p>
</li>
<li><p>We will have 2 million single row deletes.</p>
</li>
<li><p>We will have auto commit on, causing all the above operations to have corresponding commit.</p>
</li>
</ul>
<h3 id="heading-table-structure">Table Structure</h3>
<p>We will have 10 tables called firenibble 1 to 10.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> public.firenibble1 (
  f0 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  f1 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f2 <span class="hljs-built_in">bigint</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f3 <span class="hljs-built_in">int</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f4 float8 <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f5 float8 <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f6 float8 <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f7 float8 <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f8 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f9 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f10 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f11 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f12 <span class="hljs-built_in">date</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f13 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f14 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  f15 <span class="hljs-built_in">varchar</span>(<span class="hljs-number">128</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-literal">NULL</span>,
  PRIMARY <span class="hljs-keyword">KEY</span> (f0)
) ;
</code></pre>
<h2 id="heading-insert">Insert</h2>
<p>Insert will essentially be new primary key insert.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h2 id="heading-update">Update</h2>
<p>Update will be updating of two columns on a primary key value.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">update</span> firenibble1 <span class="hljs-keyword">set</span> f2 = <span class="hljs-number">280396830734761092</span>, f9 = <span class="hljs-string">'n6ChQjN9dfxIl6nc6SNgIzSahfeXfAef'</span> <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h2 id="heading-delete">Delete</h2>
<p>Delete will be essentially a primary key delete.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">delete</span> <span class="hljs-keyword">from</span> firenibble1 <span class="hljs-keyword">where</span> f0 = <span class="hljs-number">19998</span>;
</code></pre>
<h3 id="heading-dml-operations-sequence">DML Operations Sequence</h3>
<p>Then came the question of how do we order the load so that we can rerun the load over and over again and never have to clean up the previous load. So we decided that the load will be such that we will start with 0 rows in all 10 tables, do a bunch of inserts, do a bunch of updates, do a bunch of deletes and end up with 0 rows in all tables. This kept the load and the tables rather clean. So the exact sequence will look like this. I know we could have been more granular mixing the inserts, updates and deletes even more, and as we do more benchmarks we might try that strategy but for starters this looked pretty good. Also we wanted to see how our replication performed with large number of insert only, update only and delete only loads. Also note that there is no relationships between the load and the change logs, in the sense there is no flush binary logs happening anywhere causing the inserts, updates and deletes to cross binary log boundaries.</p>
<ol>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes</p>
</li>
<li><p>1 million inserts</p>
</li>
<li><p>3 million updates</p>
</li>
<li><p>1 million deletes.</p>
</li>
</ol>
<p>We will also makes sure that all inserts, updates and deletes happen on 10 tables in a sequence so that the operations are granularily staggered over all tables and not contiguous on one table and the next. Which means, the inserts look like this (and so does the updates and deletes).</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble1 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble2 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble3 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble4 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble5 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble6 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble7 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble8 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble9 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> firenibble10 <span class="hljs-keyword">values</span> (<span class="hljs-number">19998</span>, <span class="hljs-number">5963887289447355291</span>, <span class="hljs-number">6644703987735879175</span>, <span class="hljs-number">-2094978734</span>, <span class="hljs-number">0.51946</span>, <span class="hljs-number">0.480314</span>, <span class="hljs-number">0.528386</span>, <span class="hljs-number">0.247536</span>, <span class="hljs-string">'Y4Jt79YtKat99KRV8CioT7p6bUVdtsm6'</span>, <span class="hljs-string">'hC8SKt3MgvoGkOYJIljgKjdEaoY68YJe'</span>, <span class="hljs-string">'5354-04-29'</span>, <span class="hljs-string">'5741-02-18'</span>, <span class="hljs-string">'9548-08-16'</span>, <span class="hljs-string">'K3fiVGzTGeiIB2AfChQDXOAQ7ANZBxEN'</span>, <span class="hljs-string">'SETnGb7dxOVQthQtFdH6lbZ6yqVVoXPU'</span>, <span class="hljs-string">'fJMS3fPnIJBnsi0CBxkFc2fZDf5gUiSJ'</span>);
</code></pre>
<h2 id="heading-benchmark-sequence">Benchmark Sequence</h2>
<p>A choice we had was to make was do one of the following</p>
<ol>
<li><p>Have the wirekite replication running. Run the load and wait for the last event of the load to appear on the target. Measure the time between when the load started and the last event appeared.</p>
</li>
<li><p>Run the load and note down the binlog number and position at which the load started and wait for the load to finish. Now start the wirekite replication from the starting binlog number and position and wait for the last event of the load to appear on the target. Measure the time between when the wirekite replication started and the last event appeared on the target.</p>
</li>
</ol>
<p>We decided to go with option 2. The primary reason being that in option 1 wirekite replication was waiting for the events to finish successfully on the database, and essentially we were not only benchmarking wirekite, but also the database, with the boundaries between the two completely blurred. So we preferred the pre-loaded database with the changes, so that we are only benchmarking wirekite and nothing else.</p>
<h2 id="heading-machine-configuration">Machine Configuration</h2>
<p>For Postgres we created an <strong>n2-standard-16</strong> GCP instance with all the standard configurations - 8 CPU’s and 64 GB RAM in the us-central region. We installed Ubuntu version 24 and Oracle version 19. Our archive log size was 330 MB.</p>
<p>For Firebolt we created a <strong>Medium</strong> Size Warehouse also in the us-central1 region to minimize the network distance.</p>
<pre><code class="lang-sql">=&gt; <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">ENGINE</span> my_engine <span class="hljs-keyword">SET</span> <span class="hljs-keyword">TYPE</span> = <span class="hljs-string">"M"</span> NODES = <span class="hljs-number">5</span> MIN_CLUSTERS=<span class="hljs-number">1</span> MAX_CLUSTERS = <span class="hljs-number">2</span> FAMILY=CO;
ok
</code></pre>
<p>We have been using the same configurations for all our benchmarks so that we are comparing apples and apples.</p>
<h2 id="heading-wirekite-run">Wirekite Run</h2>
<p>So how long did it take for wirekite to move 10 million changes — <strong>5 minutes and 15 seconds</strong>.</p>
<pre><code class="lang-sql">cat wirekite_cdc.log | grep -E '<span class="hljs-keyword">START</span>|<span class="hljs-keyword">FINISH</span>|ELAPSED<span class="hljs-string">'
START: Sun Jun 15 00:19:03 UTC 2025
FINISH: Sun Jun 15 00:24:18 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 5 min 15 sec</span>
</code></pre>
<h2 id="heading-wirekite-run-2-with-lower-commit-frequency">Wirekite Run 2 with Lower Commit Frequency</h2>
<p>We did one more benchmark just to see how commits affect the performance and in fact they do. We got the the same 10 million ops with <strong>2 minutes and 18 seconds</strong>.</p>
<pre><code class="lang-plaintext">cat wirekite_cdc.log | grep -E 'START|FINISH|ELAPSED'
START: Sun Jun 15 00:53:32 UTC 2025
FINISH: Sun Jun 15 00:55:49 UTC 2025
TOTAL ELAPSED TIME: 0 hrs 2 min 18 sec
</code></pre>
]]></content:encoded></item></channel></rss>