<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Apache Doris Blog</title>
        <link>https://doris.apache.org/ko/blog/</link>
        <description>Apache Doris Blog</description>
        <lastBuildDate>Thu, 08 Oct 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>ko</language>
        <item>
            <title><![CDATA[Apache Doris x Fluss: Unified Queries Across Stream and Lake]]></title>
            <link>https://doris.apache.org/ko/blog/apache-doris-fluss-stream-lake-analytics/</link>
            <guid>https://doris.apache.org/ko/blog/apache-doris-fluss-stream-lake-analytics/</guid>
            <pubDate>Thu, 08 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[How Apache Doris 5.0 reads Fluss log and primary-key tables, combines Paimon history with recent data, and manages JVM memory during Union Read.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Tech Sharing</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">Apache Doris x Fluss: Unified Queries Across Stream and Lake</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">Apache Doris &#xB7; Mingyu Chen</span></span><time datetime="2026-10-08T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 10&#xC6D4; 8&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><p>A campaign&apos;s conversion rate has dropped. The team needs to compare it with similar past campaigns before calling it abnormal. In a road test, a rise in human interventions means little without today&apos;s test-run count, each vehicle&apos;s current state, and records from previous weeks. Both investigations need new events and historical data in the same query.</p>
<p>Fluss keeps event logs and current state in tables. With its <a href="https://doris.apache.org/docs/dev/lakehouse/catalogs/fluss-catalog/" target="_blank" rel="noopener noreferrer">Fluss Catalog</a>, Apache Doris 5.0 can query those tables alongside history tiered to <a href="https://doris.apache.org/docs/dev/lakehouse/catalogs/paimon-catalog/" target="_blank" rel="noopener noreferrer">Paimon</a>. The read path depends on which portion of the data a query needs.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="1-how-fluss-unifies-streams-and-lakes">1. How Fluss unifies streams and lakes<a href="https://doris.apache.org/ko/blog/apache-doris-fluss-stream-lake-analytics/#1-how-fluss-unifies-streams-and-lakes" class="hash-link" aria-label="1. How Fluss unifies streams and lakes &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1. How Fluss unifies streams and lakes &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="keep-event-streams-and-current-state-in-tables">Keep event streams and current state in tables<a href="https://doris.apache.org/ko/blog/apache-doris-fluss-stream-lake-analytics/#keep-event-streams-and-current-state-in-tables" class="hash-link" aria-label="Keep event streams and current state in tables &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Keep event streams and current state in tables &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Many real-time pipelines send events through a message queue and then copy them into a state store or analytics engine. Until the copy finishes, analysts cannot query the latest events. For a query that also needs history or current state, they must keep track of what each system holds.</p>
<p>Apache Fluss stores events in tables with schemas and feeds downstream stream consumers. In a suitable pipeline, it can handle the ingestion and distribution previously done by a separate messaging system. Analysts can query recent events without a copy job built solely for analytics. Fluss&apos;s columnar layout can also reduce I/O when a query selects only a few fields from a wide table.</p>
<p><img decoding="async" loading="lazy" alt="Fluss architecture with log and primary-key tables, a tiering service, and a Paimon lake" src="https://cdnd.selectdb.com/assets/shared/20187fc94d23eb9f3b91f2bf815b736b.jpg" width="1730" height="909" class="img_ev3q"></p>
<p>Fluss has two table types:</p>




















<table><thead><tr><th>Table type</th><th>Suitable data</th><th>Read behavior</th></tr></thead><tbody><tr><td>Log table</td><td>Append-only takeover events, trip records, and device alerts</td><td>Retains events in write order for continuous consumption and analysis</td></tr><tr><td>Primary-key table</td><td>Changing vehicle states, device configurations, and campaign rules</td><td>Maintains the current value by primary key and retains a changelog</td></tr></tbody></table>
<p>Each table has a Log layer for recent writes and a Lake layer for older data. A tiering service writes the older records to an open lake format. The readable lake snapshot records how far the data has been tiered. Doris uses that position to separate lake history from new log records.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="analyze-fluss-data-with-sql">Analyze Fluss data with SQL<a href="https://doris.apache.org/ko/blog/apache-doris-fluss-stream-lake-analytics/#analyze-fluss-data-with-sql" class="hash-link" aria-label="Analyze Fluss data with SQL &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Analyze Fluss data with SQL &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Analysts still need to compare events with history, join them to current state, and inspect individual records. How unusual is a new deviation, and which devices or users account for it? Doris queries Fluss tables directly to answer those questions with SQL.</p>
<p><img decoding="async" loading="lazy" alt="Apache Doris 5.0 queries Fluss log and primary-key tables alongside Paimon history and Doris dimension tables" src="https://cdnd.selectdb.com/assets/shared/64f3acc7ba028e5912142c88502fd881.jpg" width="1730" height="909" class="img_ev3q"></p>

























<table><thead><tr><th>Scenario</th><th>Question</th><th>Data needed</th></tr></thead><tbody><tr><td>Campaign monitoring</td><td>Is a new conversion change outside the range of similar past campaigns?</td><td>Latest behavior events, historical trends, and current campaign state</td></tr><tr><td>Device and fleet analysis</td><td>Which devices have new alerts, and have similar anomalies occurred before?</td><td>Real-time events, long-term operating records, and current device states</td></tr><tr><td>Risk review</td><td>Does a new anomaly match a historical pattern?</td><td>New events, historical details, and continuously updated object states</td></tr></tbody></table>
<p>Suppose human interventions spike at one intersection during an autonomous driving road test. The team queries the last 30 minutes of events, counts the test runs through that segment, and compares the intervention rate with the same time of day over previous weeks. More interventions may simply mean more vehicles passed through. If the rate rose too, the team needs to investigate.</p>
<p>The team then checks current vehicle states, narrows down the trips and time window, and reviews the driving records.</p>
<p>Doris 5.0 queries Fluss tables through the <a href="https://doris.apache.org/docs/dev/lakehouse/catalogs/fluss-catalog/#configuring-catalog" target="_blank" rel="noopener noreferrer">Fluss Catalog</a>. If a table has been tiered to Paimon, the same query can read lake history and records still in the Fluss log.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="2-how-doris-reads-new-events-history-and-current-state-from-fluss">2. How Doris reads new events, history, and current state from Fluss<a href="https://doris.apache.org/ko/blog/apache-doris-fluss-stream-lake-analytics/#2-how-doris-reads-new-events-history-and-current-state-from-fluss" class="hash-link" aria-label="2. How Doris reads new events, history, and current state from Fluss &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2. How Doris reads new events, history, and current state from Fluss &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="21-query-newly-written-events">2.1 Query newly written events<a href="https://doris.apache.org/ko/blog/apache-doris-fluss-stream-lake-analytics/#21-query-newly-written-events" class="hash-link" aria-label="2.1 Query newly written events &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2.1 Query newly written events &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>To investigate, the road-test team filters recent intervention records by road segment, trigger, and the software version running when each event occurred. Copying the records into Doris first would slow down that initial query.</p>
<p>Fluss divides tables into Buckets for parallel reads and writes. In a partitioned table, records go to a partition and then a Bucket. Unpartitioned tables go straight to Buckets. Each Bucket has its own Offset, a position in its log.</p>
<p>Doris reads Fluss log tables through the Fluss Catalog. It can filter and aggregate those records or join them with vehicle models, test plans, and other dimensions in Doris tables. Teams may still store recurring, stable query results in Doris internal tables.</p>
<p><img decoding="async" loading="lazy" alt="Doris selects the relevant Fluss partition and fixes a read-end offset for each Bucket" src="https://cdnd.selectdb.com/assets/shared/aa2f365454800a0cceb9a4c4b71f2ea4.jpg" width="1730" height="909" class="img_ev3q"></p>
<p>Analysts can inspect Fluss databases, tables, and columns through the Catalog before they query. Fluss still owns the source tables; storing results in Doris is optional.</p>
<p>At planning time, Doris fixes the log end position for each Bucket. It stops there even if more records arrive during execution. Those records appear in a later query, so each execution has a fixed endpoint.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="22-combine-lake-history-with-new-fluss-events">2.2 Combine lake history with new Fluss events<a href="https://doris.apache.org/ko/blog/apache-doris-fluss-stream-lake-analytics/#22-combine-lake-history-with-new-fluss-events" class="hash-link" aria-label="2.2 Combine lake history with new Fluss events &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2.2 Combine lake history with new Fluss events &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>To establish a baseline, the team compares the same road segment across several weeks of morning rush hour. Recent intervention and trip events may still be in the Fluss log, outside the latest readable Paimon snapshot. Separate lake and log queries would force the team to reconcile overlap and gaps itself.</p>
<p>The tiering service writes log records to Paimon, commits a readable snapshot, and records the last tiered Offset for each Bucket. Fluss still holds records written after those positions.</p>
<p><img decoding="async" loading="lazy" alt="Union Read uses a Paimon lake snapshot and reads each Fluss Bucket from its tiering position to the query&amp;#39;s fixed end" src="https://cdnd.selectdb.com/assets/shared/d5dbeac1a59124797438fbfb2f4f67d7.jpg" width="1731" height="909" class="img_ev3q"></p>
<p>For Fluss tables with lake tiering enabled, Doris can use <a href="https://doris.apache.org/docs/dev/lakehouse/catalogs/fluss-catalog/#tiered-lake-tables-and-union-read" target="_blank" rel="noopener noreferrer">Union Read</a>. At query planning, Doris fixes a Paimon snapshot and the end Offset for each Bucket. Paimon supplies the history covered by the snapshot; Fluss supplies records from the tiering position to the fixed end. Analysts query one logical table. Records that arrive later appear in the next query.</p>
<p>For append-only events such as interventions, the Offset boundary helps prevent duplicate or missing reads. Analysts can inspect the lake and log separately to check tiering progress. If no readable lake snapshot exists yet, the default query can read only data still retained by Fluss. A task that needs complete history should first confirm that a snapshot is ready and check the log retention range.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="23-reconstruct-the-current-value-of-a-primary-key-table">2.3 Reconstruct the current value of a primary-key table<a href="https://doris.apache.org/ko/blog/apache-doris-fluss-stream-lake-analytics/#23-reconstruct-the-current-value-of-a-primary-key-table" class="hash-link" aria-label="2.3 Reconstruct the current value of a primary-key table &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2.3 Reconstruct the current value of a primary-key table &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Vehicles and device configurations change state too. A vehicle might move from &quot;road testing&quot; to &quot;awaiting maintenance.&quot; Counting both changes as current would put two versions of the same vehicle in the report.</p>
<p>A primary-key table has two possible read baselines. For a Fluss-only read, Doris starts with a KV snapshot and applies the later changelog. For a tiered table using Union Read, it starts with a Paimon lake snapshot and applies the Fluss changelog after that snapshot. Union Read does not combine the KV and lake snapshots.</p>
<p><img decoding="async" loading="lazy" alt="Fluss state reads use a KV snapshot and changelog; Union Read uses a Paimon snapshot and the later changelog" src="https://cdnd.selectdb.com/assets/shared/733c18e16faa47d6dd02961139ec2108.jpg" width="1730" height="909" class="img_ev3q"></p>
<p><em>Figure 5. The two paths use a KV snapshot and a lake snapshot as their respective baselines. In Union Read, an update returns the new value and a deletion removes the primary key.</em></p>
<p>Union Read finds keys changed since the lake snapshot, filters their older lake rows, and emits the latest values from the log tail. An update replaces the old state; a deletion removes the key. Each vehicle appears once in the current-state result.</p>
<p>For road-test analysis, the event table records the software version at the time of the event. The vehicle state table shows the version running now. Those versions answer different questions.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="24-choose-the-read-range-for-the-task">2.4 Choose the read range for the task<a href="https://doris.apache.org/ko/blog/apache-doris-fluss-stream-lake-analytics/#24-choose-the-read-range-for-the-task" class="hash-link" aria-label="2.4 Choose the read range for the task &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2.4 Choose the read range for the task &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Trend analysis needs both history and new events. A baseline report for an archived month may need only lake data. To check tiering progress, analysts need to see what remains in the log. Doris provides three entry points for Fluss tables tiered to Paimon:</p>

























<table><thead><tr><th>Query entry point</th><th>Read range</th><th>Use and limitation</th></tr></thead><tbody><tr><td>Table name</td><td>Normally uses Union Read to cover lake history and untiered changes</td><td>Suitable for combined historical and recent analysis; the default mode may change the read path when its conditions are not met</td></tr><tr><td><code>table$lake</code></td><td>Only data tiered to Paimon</td><td>Checks a historical baseline or tiering result; excludes records not yet in the lake</td></tr><tr><td><code>table$log</code></td><td>Only the Fluss log after the readable lake snapshot</td><td>Checks increments in an append-only event table; excludes lake history and does not apply to primary-key tables</td></tr></tbody></table>
<p><img decoding="async" loading="lazy" alt="The table, table$lake, and table$log entry points cover both sides, only Paimon history, and only the Fluss log tail respectively" src="https://cdnd.selectdb.com/assets/shared/4723d1a1e4a9616effe934424d507b22.jpg" width="1731" height="909" class="img_ev3q"></p>
<p><em>Figure 6. The table name covers both lake and log. <code>$lake</code> reads only the lake; <code>$log</code> reads only the append-only log after the readable lake snapshot.</em></p>
<p>When querying the table name directly, <a href="https://doris.apache.org/docs/dev/lakehouse/catalogs/fluss-catalog/#union-read-modes" target="_blank" rel="noopener noreferrer"><code>fluss.union_read.mode</code></a> controls how Doris chooses the read path. The <code>$lake</code> and <code>$log</code> entry points already identify a specific data segment.</p>

























<table><thead><tr><th>Mode</th><th>Behavior when querying the full table</th><th>When to use it</th></tr></thead><tbody><tr><td><code>auto</code> (default)</td><td>Uses Union Read when a readable lake snapshot exists and the other conditions are met; otherwise adjusts the read path to favor currently readable data</td><td>Everyday analysis where query availability takes priority</td></tr><tr><td><code>required</code></td><td>Must actually use the lake; errors if Union Read cannot run safely</td><td>Deployment acceptance checks that require history and increments to join as expected</td></tr><tr><td><code>disabled</code></td><td>Does not read the lake; reads only data currently available from Fluss</td><td>Temporarily isolate a lake-side problem or compare read paths</td></tr></tbody></table>
<p><code>$log</code> and <code>disabled</code> start at different positions. <code>$log</code> starts at the tiering position recorded by the lake snapshot. For log tables, <code>disabled</code> reads records still retained by Fluss; for primary-key tables, it reconstructs current state. If Fluss has removed older log segments, a <code>disabled</code> query on a log table cannot see history that exists only in the lake.</p>
<p>Several factors affect scan cost and the choice of read path:</p>
<ul>
<li>The lake side uses Doris&apos;s Paimon reader and <a href="https://doris.apache.org/docs/dev/lakehouse/data-cache/" target="_blank" rel="noopener noreferrer">file cache</a>. Partition filters and selecting only the necessary columns can reduce scanning and decoding. A filter on an ordinary data column gives the right result but may not reduce the data read from the source.</li>
<li>Tiering delays lengthen the primary-key changelog tail that must be merged, increasing memory use. Doris limits the number of tail records for primary-key Union Read. Above that limit, <code>auto</code> changes the read path and <code>required</code> returns an error.</li>
<li><a href="https://doris.apache.org/docs/dev/lakehouse/catalogs/fluss-catalog/#union-read-modes" target="_blank" rel="noopener noreferrer"><code>EXPLAIN</code></a> shows whether Union Read is used and the ranges planned for the lake and log. <a href="https://doris.apache.org/docs/dev/query-acceleration/query-profile/" target="_blank" rel="noopener noreferrer">Query Profile</a> shows row counts and time spent on each side. Together, they reveal whether the cost comes from scanning history, reading the log tail, or tiering progress.</li>
</ul>
<p>Teams can save the results of stable, frequently run queries in Doris internal tables when needed.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="3-performance-measurements">3. Performance measurements<a href="https://doris.apache.org/ko/blog/apache-doris-fluss-stream-lake-analytics/#3-performance-measurements" class="hash-link" aria-label="3. Performance measurements &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3. Performance measurements &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>We tested the read paths on an 18-core development machine with 48 GB of memory. Doris 5.0 ran as one FE and one BE, with the BE&apos;s default 2 GB JVM heap. Fluss 1.0.0 ran one CoordinatorServer and one TabletServer; Paimon used MinIO on the same machine. The primary-key test table had 30 million keys, 13 columns (about 210 bytes per row), and 16 Buckets. After one warm-up, we ran each query five times and report the median. Docker port forwarding limited bandwidth to both Fluss and the lake, so comparisons on this machine are more useful than the absolute times.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="31-primary-key-tables-pure-jni-reads-versus-union-read">3.1 Primary-key tables: pure JNI reads versus Union Read<a href="https://doris.apache.org/ko/blog/apache-doris-fluss-stream-lake-analytics/#31-primary-key-tables-pure-jni-reads-versus-union-read" class="hash-link" aria-label="3.1 Primary-key tables: pure JNI reads versus Union Read &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.1 Primary-key tables: pure JNI reads versus Union Read &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p><img decoding="async" loading="lazy" alt="Count and group-by timings for pure JNI reads and Union Read with lake auto-compaction" src="https://cdnd.selectdb.com/assets/shared/bdcda22ea765a85cc90f54064b6db711.jpg" width="1731" height="909" class="img_ev3q"></p>
<p>We measured three read paths:</p>
<ul>
<li>With a pure JNI read (<code>fluss.union_read.mode = &apos;disabled&apos;</code>), the BE does not read the lake. For each Bucket, it copies the full KV snapshot to local disk, scans it with RocksDB, and merges the later changelog to reconstruct current values. The BE calls the Fluss Java SDK through JNI.</li>
<li>With Union Read and lake auto-compaction, Doris uses the Paimon lake snapshot as the baseline and reads lake data with its <a href="https://doris.apache.org/docs/dev/lakehouse/catalogs/fluss-catalog/#query-performance" target="_blank" rel="noopener noreferrer">native Parquet reader</a>. For each Bucket with a log tail, the BE reads that tail once from Fluss through JNI and filters older lake rows by primary key. The lake table has <code>table.datalake.auto-compaction</code> enabled.</li>
<li>With Union Read but no lake auto-compaction, the logical read is the same. Overlapping lake files, however, require the Paimon Java reader through JNI to merge them. This is the default Fluss configuration.</li>
</ul>
<p>The first column counts keys updated after the lake snapshot, which determines how much Union Read must fetch from Fluss: 0, 10,000, or 100,000 keys per Bucket. Each cell gives the time in seconds for <code>COUNT(*)</code>, a grouped aggregation (count, amount sum, and average discount by category), and <code>SELECT *</code> (excluding transfer of results to the client), in that order.</p>

































<table><thead><tr><th>Keys updated after the lake snapshot</th><th>Pure JNI read</th><th>Union Read with auto-compaction</th><th>Union Read speedup (count / group by)</th><th>Union Read without auto-compaction</th></tr></thead><tbody><tr><td>0</td><td>6.04 / 6.23 / 8.07</td><td>0.34 / 1.12 / 9.27</td><td>17.8&#xD7; / 5.6&#xD7;</td><td>1.06 / 2.08 / OOM</td></tr><tr><td>160,000</td><td>6.07 / 6.11 / 6.98</td><td>0.52 / 1.28 / 9.65</td><td>11.8&#xD7; / 4.8&#xD7;</td><td>1.06 / 1.97 / OOM</td></tr><tr><td>1.6 million</td><td>6.25 / 6.73 / 7.84</td><td>1.08 / 1.73 / 10.80</td><td>5.8&#xD7; / 3.9&#xD7;</td><td>1.40 / 2.83 / OOM</td></tr></tbody></table>
<ul>
<li>For <code>SELECT *</code>, pure JNI finishes 1 to 3 seconds sooner than Union Read, but it uses an average of 9 to 10 cores (68 to 75 core-seconds). Union Read uses 1 to 2 cores (9 to 18 core-seconds). Pure JNI consumes 4 to 8 times as much CPU time. The KV snapshot is on local disk, while lake data crosses a forwarded port, which favors pure JNI in this setup.</li>
<li>Pure JNI copies each Bucket&apos;s KV snapshot to a BE temporary directory so RocksDB can open it. A query uses a sampled peak of 2.9 to 4.3 GB and releases the space afterward. Union Read does not copy the KV snapshot and does not use that BE disk space.</li>
<li>Without lake auto-compaction, a merge read can load data from several files into the <a href="https://doris.apache.org/docs/dev/lakehouse/catalogs/fluss-catalog/#be-jvm-heap-memory" target="_blank" rel="noopener noreferrer">BE&apos;s JVM heap</a> at once. A full-table read uses 16 scanners in parallel by default and fails with <code>OutOfMemoryError</code> on the default 2 GB heap. <code>enable_jni_heap_admission</code> prevents that failure in this test, as shown below. Enabling <code>table.datalake.auto-compaction</code> for the primary-key lake table addresses the underlying cause.</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="32-be-jvm-memory-control">3.2 BE JVM Memory Control<a href="https://doris.apache.org/ko/blog/apache-doris-fluss-stream-lake-analytics/#32-be-jvm-memory-control" class="hash-link" aria-label="3.2 BE JVM Memory Control &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.2 BE JVM Memory Control &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>We repeated the full-table read without lake auto-compaction on a BE with a 2 GB JVM heap, then enabled <code>enable_jni_heap_admission</code> and ran it again:</p>
<p><img decoding="async" loading="lazy" alt="JVM heap admission queues JNI readers to avoid running too many heap-intensive scans at once" src="https://cdnd.selectdb.com/assets/shared/1a8b81a8e220c4a31892b442eec0d230.jpg" width="1730" height="909" class="img_ev3q"></p>

























<table><thead><tr><th>Keys updated after the lake snapshot</th><th>Disabled</th><th><code>enable_jni_heap_admission</code> enabled</th></tr></thead><tbody><tr><td>0</td><td>OOM</td><td>11.8 s</td></tr><tr><td>160,000</td><td>OOM</td><td>12.2 s</td></tr><tr><td>1.6 million</td><td>OOM</td><td>13.5 s</td></tr></tbody></table>
<p><a href="https://doris.apache.org/docs/dev/lakehouse/catalogs/fluss-catalog/#jni-heap-admission" target="_blank" rel="noopener noreferrer"><code>enable_jni_heap_admission</code></a> is new in Doris 5.0 and defaults to off. When enabled, readers that expect heavy JVM heap use, including the merge readers in this test, declare an estimate before they start. The BE queues a new reader if admitting it would push declared usage beyond half the maximum JVM heap. Readers proceed as earlier ones finish. This prevented OOM in the test, though queueing increased elapsed time.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="4-planned-work">4. Planned work<a href="https://doris.apache.org/ko/blog/apache-doris-fluss-stream-lake-analytics/#4-planned-work" class="hash-link" aria-label="4. Planned work &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="4. Planned work &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Apache Doris 5.0.0 provides the Fluss Catalog as an experimental feature for reads and analysis. Union Read currently works with Paimon lake tables; Iceberg, Lance, and other lake formats are planned. We plan to benchmark historical scans, log-tail merging, and concurrent queries on reproducible workloads, then use those results to improve performance and resource use.</p>
<p>Today, Doris reads Fluss log and KV data through the Java SDK. Fluss 1.0 has a Rust SDK, and we plan to move these reads to it gradually. Before switching, we need to preserve the semantics of log tables, primary-key tables, and Union Read. Real workloads will show whether Rust improves data conversion, memory use, and resource control.</p></div>]]></content:encoded>
            <category>Tech Sharing</category>
        </item>
        <item>
            <title><![CDATA[Apache Doris 5.0 Variant Across Internal and Open Lakehouse Tables]]></title>
            <link>https://doris.apache.org/ko/blog/apache-doris-variant-open-lakehouse/</link>
            <guid>https://doris.apache.org/ko/blog/apache-doris-variant-open-lakehouse/</guid>
            <pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[How Apache Doris 5.0 plans to use Variant across internal, Iceberg, and Paimon tables, with SQL examples and selection guidance.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Tech Sharing</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">Apache Doris 5.0 Variant Across Internal and Open Lakehouse Tables</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">Apache Doris &#xB7; Mingyu Chen</span></span><time datetime="2026-09-15T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 9&#xC6D4; 15&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<p><strong>Preview: Apache Doris 5.0 multimodal lakehouse (4) | Scenario and solution</strong></p>
<p>Apache Doris introduced Variant as a column type in version 2.1 for storing semi-structured data such as JSON. Users do not need to define fields before creating a table. During ingestion, Doris automatically splits the data into typed subcolumns. This retains the flexibility of JSON ingestion while providing analytical performance close to columnar storage. Apache Doris 5.0 will extend the Variant type from internal tables to open lake formats such as Iceberg and Paimon. The same VARIANT type, SQL syntax, and execution engine will process Variant data across these formats. Using an Agent trace data pipeline as an example, this article explains the need for this capability, the business problems it addresses, and when to use Variant in internal tables or data lakes.</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="1-agent-traces-the-divide-between-variant-producers-and-consumers">1. Agent traces: The divide between Variant producers and consumers<a href="https://doris.apache.org/ko/blog/apache-doris-variant-open-lakehouse/#1-agent-traces-the-divide-between-variant-producers-and-consumers" class="hash-link" aria-label="1. Agent traces: The divide between Variant producers and consumers &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1. Agent traces: The divide between Variant producers and consumers &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>JSON is a natural representation for an AI Agent execution trace. Protocols such as MCP and A2A use JSON-RPC, while tool-call parameters, model output, and span attributes for each step all contain nested structures. A complete trace can range from tens of KB to several MB and may be seven or eight levels deep. Tool lists and parameters also change as models evolve. Eight fields yesterday may become twelve today, so defining a stable schema in advance is often impossible.</p>
<p>Analytical systems have traditionally handled this type of data in three ways:</p>

























<table><thead><tr><th>Approach</th><th>Advantage</th><th>Cost</th></tr></thead><tbody><tr><td>Flatten data through ETL into a wide table</td><td>Fast queries</td><td>Every new upstream field requires changes to jobs and tables, followed by historical backfills</td></tr><tr><td>Store data as JSON strings or JSONB</td><td>Flexible ingestion</td><td>Every SQL query must parse the entire JSON document</td></tr><tr><td>Hard-code the structure with STRUCT or MAP</td><td>Better read performance</td><td>Still strongly typed and insufficiently flexible</td></tr></tbody></table>
<p>The Variant type addresses the trade-off between flexibility and query performance. Apache Doris has provided the Variant column type since version 2.1 for storing semi-structured data such as JSON:</p>
<ul>
<li>When creating a table, users declare a single VARIANT column without defining its fields in advance.</li>
<li>During ingestion, Doris automatically splits JSON into typed subcolumns, performs type inference and promotion, stores infrequently used fields in sparse columns, and allows indexes on subcolumns.</li>
<li>Queries access values by path and read only the relevant subcolumns instead of parsing the entire JSON document.</li>
</ul>
<p>Variant combines the ingestion flexibility of JSON with query performance close to columnar storage.</p>
<p>For Agent observability platforms, the recommended data model is:</p>
<ul>
<li>Store stable fields such as <code>trace_id</code>, <code>tool_name</code>, and latency as regular columns.</li>
<li>Store inputs, outputs, and tool parameters in a VARIANT column, allowing upstream systems to add fields without altering the table.</li>
<li>Use regular SQL with path-based value access for failure attribution, cost aggregation by tool, and effectiveness comparisons across model versions.</li>
<li>Use inverted indexes for full-text searches over text in model outputs.</li>
</ul>
<p>Later Apache Doris releases added Variant features such as Schema Template, secondary indexes at the subcolumn level, DOC mode for JSON documents hundreds of MB in size, and NestedGroup for searching nested arrays.</p>
<p>Changes in enterprise data architectures created another problem. Agent traces are produced by ingestion pipelines running on Flink or Spark. The data usually lands in Paimon first, then feeds training, evaluation, observability, and other workloads. Before version 5.0, Doris could process Variant data only in its own format. Consumers that wanted to analyze the data with Variant had to write and synchronize it to both internal tables and the lake. This duplicated storage and introduced synchronization delays and data inconsistencies.</p>
<p><img decoding="async" loading="lazy" alt="Figure 1: Dual-write divide between Agent trace producers and consumers" src="https://cdnd.selectdb.com/assets/shared/e992399f8408f2eae1a29c6de737984e.jpg" width="1200" height="630" class="img_ev3q"></p>
<p>Other Variant use cases have the same problem:</p>
<ul>
<li><strong>Event tracking:</strong> Event properties can be stored in a VARIANT column, allowing product teams to add properties without altering the table. The same event data is also a shared enterprise asset that algorithm teams need for training features. This requires another copy in Iceberg.</li>
<li><strong>IoT telemetry:</strong> Device properties vary by model and firmware. A wide table would be excessively sparse, while a VARIANT column allows one SQL query to aggregate data across device models. Complete datasets must also be retained for years, and object storage with an open format is the only way to reduce storage costs significantly. Real-time alerts and historical analysis must therefore access different systems, which fragments the user experience.</li>
</ul>
<p>Variant needs to follow the data. When data resides in the lake, Variant must be available there too, and the compute engine must support unified analysis of that Variant data.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="2-variant-standardization-bringing-semi-structured-data-into-the-one-copy-multiple-engines-model">2. Variant standardization: Bringing semi-structured data into the &quot;one copy, multiple engines&quot; model<a href="https://doris.apache.org/ko/blog/apache-doris-variant-open-lakehouse/#2-variant-standardization-bringing-semi-structured-data-into-the-one-copy-multiple-engines-model" class="hash-link" aria-label="2. Variant standardization: Bringing semi-structured data into the &quot;one copy, multiple engines&quot; model &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2. Variant standardization: Bringing semi-structured data into the &quot;one copy, multiple engines&quot; model &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Semi-structured data in a lake traditionally had two options: storage as strings or conversion to STRUCT through ETL. As this data became more widely used, the performance and operational costs of those approaches became harder to ignore. Variant began moving toward open standardization in 2025:</p>
<ul>
<li>In March 2025, Apache Parquet 2.11 defined a binary encoding for Variant and introduced the Shredding specification. Writers can split frequently accessed fields into typed columns while retaining the remaining data in a binary value, giving the file itself a columnar shape. The specification was finalized in August of the same year.</li>
<li>In June 2025, the Apache Iceberg V3 specification was approved, making Variant a first-class table type. Apache Paimon has supported Variant and Shredding since version 1.4.</li>
<li>Spark 4.0/4.1, Flink 2.1, and DuckDB subsequently added support, while Trino began offering experimental support. Snowflake and Databricks also announced general availability of their respective support for Variant in open formats in 2026.</li>
</ul>
<p>The open lakehouse model of &quot;one copy of data shared by multiple engines&quot; is extending to semi-structured data. With a standard format, any compliant engine can read and write Variant data in a lake. We therefore decided to extend the Variant processing capabilities available for internal tables to standard Variant formats.</p>
<p><img decoding="async" loading="lazy" alt="Figure 2: Open standards allow multiple engines to share one copy of Variant data" src="https://cdnd.selectdb.com/assets/shared/388e58e15363ef5723e8bd5c5c9b3791.jpg" width="1200" height="630" class="img_ev3q"></p>
<p>An engine needs to solve three problems to use Variant effectively in a lake:</p>
<ol>
<li><strong>High-performance reads:</strong> The engine must be able to use the Shredded layout directly.</li>
<li><strong>Variant production:</strong> An engine that can read but not write Variant cannot write its analytical results back to the open lakehouse for reuse.</li>
<li><strong>Interoperability between internal and external formats:</strong> Variant should behave consistently across formats.</li>
</ol>
<p>The following sections describe the unified Variant solution planned for Apache Doris 5.0. A later article about Variant internals will explain how Doris reads the Shredded layout.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="3-doris-50-one-variant-type-one-sql-syntax-one-execution-engine">3. Doris 5.0: One Variant type, one SQL syntax, one execution engine<a href="https://doris.apache.org/ko/blog/apache-doris-variant-open-lakehouse/#3-doris-50-one-variant-type-one-sql-syntax-one-execution-engine" class="hash-link" aria-label="3. Doris 5.0: One Variant type, one SQL syntax, one execution engine &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3. Doris 5.0: One Variant type, one SQL syntax, one execution engine &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Doris 5.0 will bring the Variant analytical capabilities of internal tables to open lake formats such as Iceberg and Paimon while keeping the user experience consistent across formats.</p>
<p><img decoding="async" loading="lazy" alt="Figure 3: Variant support in Doris 5.0" src="https://cdnd.selectdb.com/assets/shared/0e8bc81d41e3eca4d7b9d7147c35963d.jpg" width="1200" height="630" class="img_ev3q"></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="31-three-layers-of-unification">3.1 Three layers of unification<a href="https://doris.apache.org/ko/blog/apache-doris-variant-open-lakehouse/#31-three-layers-of-unification" class="hash-link" aria-label="3.1 Three layers of unification &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.1 Three layers of unification &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<ul>
<li>
<p><strong>Upper layer: Unified type and SQL syntax.</strong> Doris has one VARIANT type, with consistent SQL syntax and semantics for internal and external tables.</p>
<ul>
<li>Unified path access syntax: <code>payload[&apos;event&apos;][&apos;type&apos;]</code></li>
<li>Unified conversion logic: use <code>CAST</code> for type conversion and <code>VARIANT_TYPE</code> to inspect the actual type</li>
<li>Unified constructor: use <code>PARSE_TO_VARIANT</code> to construct values from JSON text</li>
<li>Unified nesting: ARRAY, MAP, and STRUCT support nested VARIANT values</li>
<li>Unified NULL semantics: SQL NULL is distinguished from JSON null</li>
</ul>
</li>
<li>
<p><strong>Middle layer: Unified execution operators.</strong> Data read from internal table files or Parquet files in the lake is converted into the execution engine&apos;s internal Variant column representation. The same operators then process the data, providing consistent behavior.</p>
<ul>
<li>Variant values from internal and lake tables can appear in the same SQL statement and participate in UNION, JOIN, and other operations.</li>
<li>Internal and external tables can write to each other, for example, <code>INSERT INTO LakeTable SELECT ... FROM DorisTable</code>.</li>
<li>Variant can participate directly in GROUP BY and DISTINCT, with deduplication based on logical values rather than byte representations.</li>
</ul>
</li>
<li>
<p><strong>Lower layer: Unified format access interfaces.</strong> Logical abstractions for Scan and Sink operators allow each format to implement only its own reader and writer. The Doris internal table format, for example, supports subcolumn splitting, inverted indexes, BloomFilters, real-time ingestion, and primary-key updates. Open lake formats support both Plain and Shredded layouts, with each format implementing its own write layout as described in Section 3.2. Format-specific differences remain at the lowest layer wherever possible, allowing most of the execution pipeline to be reused.</p>
</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="32-capability-matrix">3.2 Capability matrix<a href="https://doris.apache.org/ko/blog/apache-doris-variant-open-lakehouse/#32-capability-matrix" class="hash-link" aria-label="3.2 Capability matrix &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.2 Capability matrix &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>The following Variant capabilities for data lakes are planned for Doris 5.0:</p>



















































































<table><thead><tr><th>Area</th><th>Capability</th><th>Iceberg</th><th>Paimon</th></tr></thead><tbody><tr><td>Read</td><td>File layout</td><td>Plain, Shredded, and mixed within the same table</td><td>Plain, Shredded, and mixed within the same table</td></tr><tr><td>Read</td><td>Nested Variant (STRUCT / ARRAY / MAP)</td><td>Supported</td><td>Supported</td></tr><tr><td>Read</td><td>Path extraction, CAST, predicate filtering, and page-level pruning</td><td>Supported</td><td>Supported</td></tr><tr><td>Read</td><td>Existing lake-format capabilities</td><td>Time Travel, Deletion Vector, and schema evolution</td><td>Append tables and primary-key tables</td></tr><tr><td>Read</td><td>Asynchronous materialized views built on lake Variant tables</td><td>Supported</td><td>Supported</td></tr><tr><td>Write</td><td>INSERT INTO / INSERT OVERWRITE / INSERT ... SELECT</td><td>Supported (format-version 3 + Parquet)</td><td>Supported (Append tables, primary-key tables, and partitioned and bucketed tables)</td></tr><tr><td>Write</td><td>Row-level UPDATE / DELETE / MERGE INTO</td><td>Supported</td><td>Supported</td></tr><tr><td>Write</td><td>Nested Variant writes</td><td>Supported</td><td>Supported</td></tr><tr><td>Write</td><td>On-disk layout</td><td>Plain (see note below)</td><td>Written according to the Shredding Schema, specified explicitly or inferred automatically</td></tr><tr><td>Interoperability</td><td>Spark writes &#x2192; Doris reads; Doris writes &#x2192; Spark reads</td><td>Verified</td><td>Verified</td></tr><tr><td>Interoperability</td><td>Internal table &#x2194; lake table INSERT ... SELECT</td><td>Bidirectional</td><td>Bidirectional</td></tr><tr><td>Interoperability</td><td>Query internal and lake tables in the same SQL statement</td><td>Supported</td><td>Supported</td></tr></tbody></table>
<blockquote>
<p>Iceberg currently writes only the Plain layout. Reading the Shredded layout is fully supported. Shredded writes are planned for a later iteration, as described in the conclusion.</p>
</blockquote>
<blockquote>
<p>Availability: The lake Variant capabilities and SQL workflow below are planned for Doris 5.0. They describe the intended behavior rather than a currently released feature.</p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="33-example-unified-lakehouse-analysis-of-agent-traces">3.3 Example: Unified lakehouse analysis of Agent traces<a href="https://doris.apache.org/ko/blog/apache-doris-variant-open-lakehouse/#33-example-unified-lakehouse-analysis-of-agent-traces" class="hash-link" aria-label="3.3 Example: Unified lakehouse analysis of Agent traces &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.3 Example: Unified lakehouse analysis of Agent traces &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>The following example uses an Agent observability platform.</p>
<p>First, Flink writes trace data to Paimon. Stable fields are stored as regular columns, while variable data is stored in a VARIANT column.</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)">-- Flink writes the paimon.obs.agent_traces trace table:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">-- (trace_id, tool_name, latency_ms, dt, payload VARIANT)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">-- 1. Analyze failures in lake tables using path extraction, type conversion, and predicates</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">SELECT</span><span class="token plain"> tool_name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">COUNT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">AS</span><span class="token plain"> failures</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> paimon</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">obs</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">agent_traces</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">WHERE</span><span class="token plain"> CAST</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">payload</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;result&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;status&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">AS</span><span class="token plain"> STRING</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;error&apos;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">  </span><span class="token operator" style="color:hsl(221, 87%, 60%)">AND</span><span class="token plain"> CAST</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">payload</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;model&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;version&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">AS</span><span class="token plain"> STRING</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;v2&apos;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">GROUP</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">BY</span><span class="token plain"> tool_name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">-- 2. Load hot data into internal tables for real-time alerts and full-text search</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">INSERT</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">INTO</span><span class="token plain"> internal</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">obs</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">agent_traces_hot</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">SELECT</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> paimon</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">obs</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">agent_traces </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">WHERE</span><span class="token plain"> dt </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">CURRENT_DATE</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">-- 3. Write derived results and the VARIANT column back to the lake for other engines</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">INSERT</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">INTO</span><span class="token plain"> paimon</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">obs</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">failed_traces</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">SELECT</span><span class="token plain"> trace_id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> tool_name</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> payload</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> internal</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">obs</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">agent_traces_hot</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">WHERE</span><span class="token plain"> CAST</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">payload</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;result&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;status&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">AS</span><span class="token plain"> STRING</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;error&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p>In this pipeline:</p>
<ul>
<li>The lake table and internal table use the same VARIANT type, so they do not require separate schemas.</li>
<li>Internal and lake tables use the same SQL query syntax.</li>
<li>Standard SQL <code>INSERT ... SELECT</code> statements handle data synchronization and write-back.</li>
</ul>
<p>The same pipeline also works for event tracking and IoT:</p>
<ul>
<li><strong>Event tracking:</strong> Events are shared as Iceberg Variant data. Spark creates features, while Doris produces reports. Both use one copy of the data and one schema-evolution process.</li>
<li><strong>IoT:</strong> The complete dataset remains in the lake for long-term retention. Hot data enters internal tables through <code>INSERT ... SELECT</code> for real-time alerting, while hot and cold data use the same data model.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="4-recommendations-for-choosing-a-variant-format">4. Recommendations for choosing a Variant format<a href="https://doris.apache.org/ko/blog/apache-doris-variant-open-lakehouse/#4-recommendations-for-choosing-a-variant-format" class="hash-link" aria-label="4. Recommendations for choosing a Variant format &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="4. Recommendations for choosing a Variant format &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>The following comparison of Variant in internal and external tables can help users select a format.</p>
<p><img decoding="async" loading="lazy" alt="Figure 4: Choosing between internal Variant, lake Variant, and hot-cold collaboration" src="https://cdnd.selectdb.com/assets/shared/0f7b225317b8de6e91dea3c83f1ffdb0.jpg" width="1200" height="630" class="img_ev3q"></p>













































<table><thead><tr><th>Dimension</th><th>Variant in internal tables</th><th>Variant in the lake</th></tr></thead><tbody><tr><td>Storage and format</td><td>Doris proprietary format</td><td>Parquet Variant in Iceberg V3 or Paimon</td></tr><tr><td>Engines that can read and write</td><td>Doris</td><td>&#x2705; <strong>Any standards-compliant engine</strong></td></tr><tr><td>Query performance</td><td>&#x2705; <strong>Best performance through subcolumns and indexes</strong></td><td>Depends on the Shredding strategy; readers access subcolumns directly</td></tr><tr><td>Indexing and search</td><td>&#x2705; <strong>Inverted indexes, BloomFilter, DOC mode, and NestedGroup</strong></td><td>Parquet statistics with page-level pruning</td></tr><tr><td>Schema control</td><td>&#x2705; <strong>Schema Template, with Doris splitting subcolumns</strong></td><td>The writer&apos;s Shredding strategy</td></tr><tr><td>Ingestion latency and updates</td><td>&#x2705; <strong>Real-time ingestion and primary-key updates</strong></td><td>Batch or micro-batch commits; Iceberg row-level updates</td></tr><tr><td>Cost</td><td>Integrated or decoupled storage and compute</td><td>&#x2705; <strong>Object storage with low per-unit storage cost</strong></td></tr></tbody></table>
<p>Variant in internal tables provides more features and better read and write performance. Variant in the lake allows multiple engines to access the same data and offers lower storage costs.</p>
<p>The recommendations are:</p>





















<table><thead><tr><th>Scenario</th><th>Recommendation</th></tr></thead><tbody><tr><td>Data is primarily produced and consumed within Doris; workloads require subsecond real-time ingestion and updates, full-text search, or high-concurrency point lookups and filtering</td><td>Variant in internal tables</td></tr><tr><td>Data is an enterprise asset shared by multiple engines; ingestion is primarily batch or micro-batch; long-term retention and storage costs matter; Spark or Flink production pipelines already exist</td><td>Variant in the lake</td></tr><tr><td>Both scenarios apply</td><td>Put hot data in internal tables and retain the complete dataset in the lake; query both with one SQL statement; accelerate lake Variant tables with asynchronous materialized views; write processing results back to the lake</td></tr></tbody></table>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="5-conclusion-variant-follows-the-data">5. Conclusion: Variant follows the data<a href="https://doris.apache.org/ko/blog/apache-doris-variant-open-lakehouse/#5-conclusion-variant-follows-the-data" class="hash-link" aria-label="5. Conclusion: Variant follows the data &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="5. Conclusion: Variant follows the data &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Doris introduced Variant for internal tables in version 2.1 and plans to support open lake formats in version 5.0. Future work will strengthen Shredded writes for Variant and improve the performance of reading Variant from data lakes. These changes are intended to meet enterprise requirements for semi-structured data analysis and cover more use cases.</p>
<p>The next article, <em>Apache Doris Variant in the Lake: How Shredding Works and Performance Benchmarks</em>, will examine the implementation details of Variant and compare the performance characteristics of different formats. It will explain in more detail how Variant works and how to use it.</p></div>]]></content:encoded>
            <category>Tech Sharing</category>
        </item>
        <item>
            <title><![CDATA[Kwai Vector Search on Paimon with Apache Doris]]></title>
            <link>https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/</link>
            <guid>https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/</guid>
            <pubDate>Thu, 10 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Kwai production practice with Apache Doris and Paimon vector indexes, including IVF-RQ, Top-K pushdown, test conditions, recall, and query latency.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Best Practice</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">Kwai Vector Search on Paimon with Apache Doris</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">Apache Doris &#xB7; Wenqiang Li; Kwai &#xB7; Junrui Li, Shiyao Yu, Fangyuan Deng</span></span><time datetime="2026-09-10T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 9&#xC6D4; 10&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<p><strong>Introduction:</strong></p>
<p><strong>Kwai</strong> uses Apache Doris in production to query vector indexes directly on Apache Paimon tables. Vectors and business data remain in Paimon, while Doris SQL initiates retrieval and pushes execution down to the data lake. Existing ingestion pipelines and OLAP access patterns do not change. This article explains the indexing foundation in Paimon 2.0, the read path developed jointly by the Doris and Paimon communities, and benchmark results for tens of millions and hundreds of millions of vectors.</p>
</blockquote>
<p>As LLM and RAG applications have become more common, semantic search has become a standard data platform requirement. One common design synchronizes vectors, filter fields, and result fields into a standalone vector database. The main cost is not the initial synchronization but the ongoing maintenance. Synchronization pipelines must run continuously, which creates a data freshness window. Vectors and business fields are split across two systems, as are access control and governance. Teams also need additional safeguards to maintain consistency between the systems.</p>
<p>Kwai took a different approach. Vectors and business columns remain in Paimon tables, and the Vector Index in Paimon 2.0 handles retrieval. Doris reads indexes and data directly through Paimon Rust. It retrieves candidates and looks up rows in parallel by bucket. Users continue to write Doris SQL with the same syntax they use for Doris internal tables.</p>
<blockquote>
<p>Availability: Kwai has validated this integration in production, while the Doris 4.2 capabilities described here are scheduled for public release at the end of September.</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="1-data-foundation-indexing-in-paimon-20">1. Data foundation: indexing in Paimon 2.0<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#1-data-foundation-indexing-in-paimon-20" class="hash-link" aria-label="1. Data foundation: indexing in Paimon 2.0 &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1. Data foundation: indexing in Paimon 2.0 &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="11-physical-separation-of-indexes-and-data">1.1 Physical separation of indexes and data<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#11-physical-separation-of-indexes-and-data" class="hash-link" aria-label="1.1 Physical separation of indexes and data &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1.1 Physical separation of indexes and data &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>The Vector Index in Paimon 2.0 works with ordinary Paimon tables and has two forms: the Global Vector Index for append tables and the PK Vector Index for primary-key tables. Both use the same index implementation and retrieval model, but they build indexes and retrieve matching rows differently. Kwai&apos;s business tables are primary-key tables, so the rest of this article focuses on the PK Vector Index.</p>
<p>Both forms store index files separately from data files. A Snapshot references a Data Manifest and an Index Manifest. The Index Manifest records each index file&apos;s type, field, location, and coverage. For append tables, it records the covered Row ID range. For primary-key tables, it records the covered source data files. Adding an index therefore does not require a different data layout, and the same table can still support batch processing, stream processing, and regular OLAP reads.</p>
<p>Figure 1 shows how index files relate to data files.</p>
<p><img decoding="async" loading="lazy" alt="Paimon 2.0 architecture with index files physically separated from data files. A Snapshot references the Data Manifest and Index Manifest, while index matches map back to source rows." src="https://cdnd.selectdb.com/assets/shared/213de6cb00c87ab2e55d11253a68e98c.jpg" width="1731" height="909" class="img_ev3q"></p>
<p><em>Figure 1: Index files and data files are stored separately. The same Snapshot links them through two types of Manifest. Index segments for primary-key tables are generated during compaction and record their source files.</em></p>
<p>Vector columns are declared as <code>ARRAY&lt;FLOAT&gt;</code> or fixed-length <code>VECTOR&lt;FLOAT, N&gt;</code>. For primary-key tables, table properties configure vector indexes, which are built automatically during compaction without a separate trigger. The following Spark SQL specifies the indexed column, index type, and distance metric when creating a primary-key table:</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">TABLE</span><span class="token plain"> vector_items </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">item_id </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">BIGINT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">embedding ARRAY</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FLOAT</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">COMMENT</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;__VECTOR_FIELD;2048&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">payload STRING</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> TBLPROPERTIES </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;primary-key&apos;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;item_id&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;bucket&apos;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;32&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;deletion-vectors.enabled&apos;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;true&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;pk-vector.index.columns&apos;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;embedding&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;fields.embedding.pk-vector.index.type&apos;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;ivf-rq&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;fields.embedding.pk-vector.distance.metric&apos;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;l2&apos;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<ul>
<li>Spark SQL does not have a <code>VECTOR</code> type. The column comment <code>__VECTOR_FIELD;2048</code> declares <code>ARRAY&lt;FLOAT&gt;</code> as a fixed-length, 2,048-dimensional vector.</li>
<li>Build parameters such as <code>nlist</code> are passed as JSON through <code>fields.&lt;col&gt;.pk-vector.index.options</code>.</li>
<li>The reranking multiplier <code>refine_factor</code> can be set in either table properties or query options.</li>
</ul>
<p>After data is written, compaction merges files within a bucket into a level above Level 0 and generates an index segment for the vector column. A new Snapshot references the segment after it is registered in the Index Manifest. The segment records the source data files it covers, which allows matches to map back to physical row positions within those files. Newly written data does not belong to an index segment until the next compaction. Section 2.2 explains how retrieval handles this intermediate state.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="12-five-types-of-vector-indexes">1.2 Five types of vector indexes<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#12-five-types-of-vector-indexes" class="hash-link" aria-label="1.2 Five types of vector indexes &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1.2 Five types of vector indexes &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>The Paimon 2.0 Vector Index currently supports five index implementations, each with different characteristics and trade-offs:</p>



































<table><thead><tr><th>Index</th><th>Main characteristic</th><th>Typical trade-off</th></tr></thead><tbody><tr><td>IVF-Flat</td><td>Stores the original vectors after clustering</td><td>Higher recall, but a larger index</td></tr><tr><td>IVF-PQ</td><td>Product quantization</td><td>Smaller index, but some quantization loss</td></tr><tr><td>IVF-SQ</td><td>8-bit scalar quantization of residuals</td><td>Balanced throughput, recall, and storage</td></tr><tr><td>IVF-RQ</td><td>Rotated residual quantization</td><td>Higher compression, but requires tuning around the quality inflection point</td></tr><tr><td>DiskANN</td><td>Graph search with persistently stored vectors for reranking</td><td>Suitable for local SSDs or a fully local cache</td></tr></tbody></table>
<p>The index types balance query performance, recall, index size, and build time differently. Storing hundreds of millions of 2,048-dimensional vectors at their original precision produces a correspondingly large index and increases the amount of data read from remote storage. RQ uses rotated residual quantization to achieve greater compression, though it must be tuned to meet quality targets. Kwai chose IVF-RQ as a balance between compression and recall. <strong>The measured Recall in Section 3.3 ranges from 96.0% to 99.6%.</strong></p>
<p>Figure 2 compares the five index types and shows Kwai&apos;s choice.</p>
<p><img decoding="async" loading="lazy" alt="Trade-offs among IVF-Flat, IVF-PQ, IVF-SQ, IVF-RQ, and DiskANN. Kwai chose IVF-RQ for 128 million 2,048-dimensional vectors, achieving measured Recall of 96.0% to 99.6%." src="https://cdnd.selectdb.com/assets/shared/55517edbec286a8e41a7421141fab1a5.jpg" width="1731" height="909" class="img_ev3q"></p>
<p><em>Figure 2: Each index type makes a different trade-off between index size and recall. Kwai chose IVF-RQ and used its higher compression to reduce remote reads.</em></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="2-bringing-indexes-back-to-the-data-lake-how-doris-directly-queries-paimon-indexes">2. Bringing indexes back to the data lake: how Doris directly queries Paimon indexes<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#2-bringing-indexes-back-to-the-data-lake-how-doris-directly-queries-paimon-indexes" class="hash-link" aria-label="2. Bringing indexes back to the data lake: how Doris directly queries Paimon indexes &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2. Bringing indexes back to the data lake: how Doris directly queries Paimon indexes &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>A compute engine needs the following capabilities to use indexes on lake data directly for retrieval:</p>
<ul>
<li>A high-performance data read path.</li>
<li>Awareness of index distribution and index coverage.</li>
<li>Optimized index access for common vector-retrieval workloads such as Top-K.</li>
</ul>
<p>Together, these capabilities allow the engine to retrieve and analyze lake data efficiently. Section 2.1 covers the read path. Section 2.2 explains index awareness and retrieval pushdown. Sections 2.3 and 2.4 describe two index-access optimizations for Top-K workloads.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="21-high-performance-reads-from-jni-to-paimon-rust">2.1 High-performance reads: from JNI to Paimon Rust<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#21-high-performance-reads-from-jni-to-paimon-rust" class="hash-link" aria-label="2.1 High-performance reads: from JNI to Paimon Rust &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2.1 High-performance reads: from JNI to Paimon Rust &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>In earlier Doris versions, reading Paimon data in MOR (Merge-On-Read) scenarios required the Paimon Java SDK. Doris called the SDK through JNI to read and merge the data. This approach had two problems:</p>
<ul>
<li>Doris could not track and control JVM memory at query granularity. If a large query exhausted memory, Doris lacked fine-grained visibility and control over its usage.</li>
<li>MOR used substantial memory, and high concurrency could cause JVM OOM errors. Increasing the JVM heap reduced the native memory available to the BE.</li>
</ul>
<p>After testing both options, Kwai chose Paimon Rust. The official Paimon team maintains Paimon Rust and keeps its MOR and index reads in sync with the Java implementation. Tests found that Paimon Rust provided two to three times the read performance of Paimon Java and was approximately 10% slower than the native Doris reader. Most of the difference came from converting Arrow&apos;s in-memory format into Doris Blocks. Paimon Rust uses native memory, so Doris can include its consumption in the existing memory-control system and manage it together with other native memory.</p>
<p>At the code level, the Doris BE, which is the C++ execution process, calls the Paimon Rust Reader through a C ABI. Rust and C++ exchange results through the Arrow C Data Interface. Doris then converts those results into Doris Blocks and passes them to the execution layer. Because Arrow is a columnar format, C++ can consume the data produced by Rust directly by column without an intermediate row-by-row conversion.</p>
<p>Figure 3 shows this read path.</p>
<p><img decoding="async" loading="lazy" alt="Doris FE creates one scan unit per bucket. Doris BE calls the Paimon Rust Reader through a C ABI, receives Arrow data, converts it into Doris Blocks, and performs sorting and merging using tracked native memory." src="https://cdnd.selectdb.com/assets/shared/2f2dcdfeeb65a7f57878cc36829888b1.jpg" width="1731" height="909" class="img_ev3q"></p>
<p><em>Figure 3: Doris BE calls Paimon Rust through a C ABI. Paimon Rust returns results in Arrow&apos;s columnar format, which Doris converts into Blocks. Regular reads and vector retrieval use the same path.</em></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="22-pushing-retrieval-down-to-the-data-lake">2.2 Pushing retrieval down to the data lake<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#22-pushing-retrieval-down-to-the-data-lake" class="hash-link" aria-label="2.2 Pushing retrieval down to the data lake &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2.2 Pushing retrieval down to the data lake &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Unlike a regular read, a vector Top-K query does not know which rows it needs before reading starts. It must identify those rows through the index first. Without the index, a vector Top-K query written as <code>ORDER BY ... LIMIT</code> becomes a full computation. Doris loads the entire vector column into BE memory, calculates distances row by row, and sorts the results. For 128 million rows with 2,048 dimensions, one query would need to transfer approximately 1 TB of vector data.</p>
<p>The query engine must push retrieval down to the index on the data lake. To do this correctly, it must account for four properties of vector indexes on Paimon primary-key tables:</p>
<ul>
<li>Indexes are organized by <code>(Partition, Bucket)</code>. A bucket is both the data-sharding unit and the indexing unit.</li>
<li>Paimon&apos;s background compaction process generates indexes, so indexes cover only compacted data. Newly written L0 files are not included in any index. Correct retrieval must merge three operations: index retrieval, exact fallback over uncovered files, and Deletion Vector mask computation.</li>
<li>An index segment is valid only when its set of covered source files still matches the bucket&apos;s current set of active files. Checking this condition requires the complete file set for the entire bucket.</li>
<li>Kwai&apos;s business tables are Paimon primary-key tables. Rows in primary-key tables can be updated and merged, so they do not have stable global Row IDs. Instead, the index stores physical coordinates: the data file and the row number within that file. Retrieval uses these physical row numbers to fetch rows from the data files.</li>
</ul>
<p>Doris uses the following index-query plan to account for these properties:</p>
<ul>
<li>The Doris FE, the Frontend responsible for query planning, enumerates scan units by bucket for the Paimon table and obtains the complete file list for each unit.</li>
<li>Doris dispatches scan units to different BE nodes. Multiple BEs process the file lists for their assigned buckets in parallel. Within each bucket, they perform retrieval, exact fallback, reranking, row lookup, and Deletion Vector application.</li>
<li>Doris&apos;s sort-and-merge operator computes the global Top-K across buckets.</li>
</ul>
<p>In this design, Paimon Rust performs vector retrieval, while Doris schedules the distributed work and merges the results.</p>
<p>Figure 4 shows whole-bucket dispatch and parallel processing by bucket.</p>
<p><img decoding="async" loading="lazy" alt="Doris FE dispatches complete buckets to BE nodes. Each BE performs index retrieval, exact fallback, and deletion masking within its bucket, while Doris merges the global Top-K across buckets." src="https://cdnd.selectdb.com/assets/shared/88f7021c9d562e780ba503a52d60eda7.jpg" width="1731" height="909" class="img_ev3q"></p>
<p><em>Figure 4: Each scan unit contains one complete bucket. The BE performs index retrieval, exact fallback, and deletion masking within that bucket. Doris then merges the Top-K across buckets.</em></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="23-top-k-pushdown-and-index-only-scan">2.3 Top-K pushdown and index-only scan<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#23-top-k-pushdown-and-index-only-scan" class="hash-link" aria-label="2.3 Top-K pushdown and index-only scan &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2.3 Top-K pushdown and index-only scan &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>A standard vector-retrieval SQL query sorts rows by distance and returns the first K. The Doris FE uses an optimizer rule to recognize this pattern and rewrite the execution plan:</p>
<ul>
<li>Add a retrieval-score column to the scan node.</li>
<li>Rewrite the distance expression in the original SQL as a conversion of this score, which avoids calculating the distance again.</li>
<li>Change the sort order from ascending distance to descending score.</li>
<li>When the vector column does not appear in the <code>SELECT</code> list, do not read the original vector column. This Index-Only Scan removes vector-column reads and transfers.</li>
</ul>
<p>The optimizer applies the rule when all of the following conditions hold:</p>
<ul>
<li>The distance function matches the metric configured for the index.</li>
<li>A vector index exists on the column.</li>
<li>The SQL contains no aggregation or <code>JOIN</code>.</li>
</ul>
<p>If any condition is not met, Doris uses a regular scan to preserve correct results.</p>
<p>The same rule handles queries with filters and pagination. The FE uses partition predicates for partition pruning and retains only buckets from relevant partitions. Predicates that can be converted into Paimon predicates are pushed down to Paimon Rust, which uses them to narrow the candidate set before retrieval. This provides pre-filtering. If the filter column is not indexed, the reader must scan that column. Doris functions such as <code>length(a) &gt; 1</code> cannot be pushed down, so Doris applies those predicates as post-filters to the retrieval results. For pagination, Doris combines <code>OFFSET</code> and <code>LIMIT</code> into a larger K value for pushdown, then applies the actual offset in the upper-level sort operator.</p>
<p>Users can write the same SQL they use for vector retrieval on Doris internal tables. They do not need to modify their queries to use vector indexes on Paimon tables.</p>
<p>Figure 5 shows how the optimizer identifies and rewrites the query.</p>
<p><img decoding="async" loading="lazy" alt="The optimizer rewrites eligible vector Top-K queries from distance ordering to descending score ordering. If the vector is not selected, it uses an Index-Only Scan; otherwise, or when any condition fails, it falls back to a regular scan." src="https://cdnd.selectdb.com/assets/shared/d692d345920ed30315a2e1ba55ebaf52.jpg" width="1731" height="909" class="img_ev3q"></p>
<p><em>Figure 5: A vector Top-K query that meets all three conditions is rewritten to sort by score. If the query does not select the vector column, Doris does not read it. If any condition is unmet, Doris uses a regular scan.</em></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="24-late-materialization-for-large-top-k-queries-separating-retrieval-from-materialization">2.4 Late materialization for large Top-K queries: separating retrieval from materialization<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#24-late-materialization-for-large-top-k-queries-separating-retrieval-from-materialization" class="hash-link" aria-label="2.4 Late materialization for large Top-K queries: separating retrieval from materialization &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2.4 Late materialization for large Top-K queries: separating retrieval from materialization &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>A typical Top-K SQL query looks like this:</p>
<div class="language-Plain language-plain codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-plain codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">select id, embedding from vec_table</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">order by l2_distance_approximate(embedding, [...])</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">limit &lt;K&gt;;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p>This SQL retrieves the <code>id</code> and <code>embedding</code> columns in a single scan and then performs retrieval. When K is small, this execution method adds little overhead.</p>
<p>When K is large, the cost of a single scan grows with it. Each bucket must read all user columns for K candidate rows, although the global merge will discard most of those rows. With K = 1 million and a 2,048-dimensional vector column, each candidate row carries 8 KB of vector data (<code>2,048 &#xD7; 4</code> bytes). As more candidates are discarded, more of those reads are wasted.</p>
<p>Kwai currently rewrites these queries as self-joins. A subquery performs retrieval and returns only IDs, then joins the original table to fetch vectors for the matching rows, as shown in Section 3.2. During the join, Doris pushes the candidate ID set down to the Paimon read layer. The reader uses this set to exclude unrelated files and row groups. It then uses Parquet page-level indexes to skip unrelated pages and materializes the vector column only for matching rows. In the Section 3.3 results, returning only IDs with Top-K = 1 million takes 7.9 to 8.0 seconds, while returning vectors as well takes 65 to 76 seconds. Most of that difference comes from reading and materializing vectors for the 1 million result rows. This approach works, but it requires users to rewrite their SQL.</p>
<p>The next execution plan is still under development. It separates retrieval and materialization into three stages:</p>
<ul>
<li>Candidate stage: Each BE performs retrieval on its assigned buckets without reading user columns and produces only a candidate set.</li>
<li>Merge stage: All candidates are collected for global Top-K selection and reranking. The result is a list of rows to materialize, represented as data files and row ranges within those files. The list is grouped by data file, and matching row ranges are merged.</li>
<li>Materialization stage: Read user columns only for rows in the row list.</li>
</ul>
<p>The merge stage must run on a single node for algorithmic reasons. Reranking needs the global candidate set to calculate the correct Top-K, and grouping and merging row ranges also require the complete set. The aggregated candidate set is only on the order of megabytes, and this stage performs no hash or range repartitioning.</p>
<p>Figure 6 compares the one-pass scan with the three-stage plan.</p>
<p><img decoding="async" loading="lazy" alt="The current one-pass scan reads wide columns for K candidates in every bucket and requires a self-join. The three-stage plan under development separates candidate generation, global merging, and materialization of matching rows." src="https://cdnd.selectdb.com/assets/shared/470535138b2cf007285101e6810c508f.jpg" width="1731" height="909" class="img_ev3q"></p>
<p><em>Figure 6: A one-pass scan makes every bucket read wide columns for K candidates. The three-stage plan first produces candidates alone, then materializes matching rows after the global Top-K step.</em></p>
<p>The expected benefits are:</p>
<ul>
<li>As Top-K grows, more candidate rows are discarded, so the system can avoid more wide-column reads.</li>
<li>The materialization stage replaces the user-written self-join and removes that join from the execution plan.</li>
<li>The FE uses a cost model to choose between the two forms automatically. Users do not need to know which form it selects or change their SQL.</li>
</ul>
<p>Section 3 reports measured performance for the current one-pass form. Section 4 gives the current status of the three-stage implementation.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="3-performance-scale-and-results-in-kwais-production-environment">3. Performance: scale and results in Kwai&apos;s production environment<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#3-performance-scale-and-results-in-kwais-production-environment" class="hash-link" aria-label="3. Performance: scale and results in Kwai&apos;s production environment &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3. Performance: scale and results in Kwai&apos;s production environment &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="31-deployment-and-benchmark-methodology">3.1 Deployment and benchmark methodology<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#31-deployment-and-benchmark-methodology" class="hash-link" aria-label="3.1 Deployment and benchmark methodology &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.1 Deployment and benchmark methodology &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Kwai already uses Doris external tables in production to query vector indexes on Paimon tables. The deployment is configured as follows:</p>









































<table><thead><tr><th>Dimension</th><th>Choice</th></tr></thead><tbody><tr><td>Table type</td><td>Paimon primary-key table (PK Table)</td></tr><tr><td>Vector storage</td><td>Inline, in the same table as the business columns</td></tr><tr><td>Vector index</td><td>IVF-RQ</td></tr><tr><td>Vector dimensions</td><td>2,048 (real production data)</td></tr><tr><td>Read path</td><td>Paimon Rust + Doris BE</td></tr><tr><td>Storage acceleration</td><td>Remote Alluxio cache</td></tr><tr><td>Query interface</td><td>Doris SQL</td></tr><tr><td>Cluster size</td><td>64 CU</td></tr></tbody></table>
<p>The tests use the following dataset sizes:</p>























<table><thead><tr><th>Scale</th><th style="text-align:right">Rows</th><th style="text-align:right">Data volume</th><th style="text-align:right">Buckets</th></tr></thead><tbody><tr><td>Tens of millions</td><td style="text-align:right">16 million</td><td style="text-align:right">Approximately 150 GB</td><td style="text-align:right">32</td></tr><tr><td>Hundreds of millions</td><td style="text-align:right">128 million</td><td style="text-align:right">Approximately 1.1 TB</td><td style="text-align:right">256</td></tr></tbody></table>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="32-two-query-types">3.2 Two query types<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#32-two-query-types" class="hash-link" aria-label="3.2 Two query types &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.2 Two query types &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>The first query type returns only business identifiers. The vector index produces the Top-K directly:</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">select</span><span class="token plain"> id</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">from</span><span class="token plain"> vec_table</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">order</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">by</span><span class="token plain"> l2_distance_approximate</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">embedding</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">/* 2,048-dimensional query vector */</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">limit</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token plain">K</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&gt;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">-- K is 100, 10,000, or 1,000,000</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p>This is a typical Index-Only Scan test case. It primarily measures the cost of retrieval itself.</p>
<p>The second query type returns both business identifiers and vectors. With the current implementation, users rewrite these queries as self-joins. A subquery retrieves the Top-K IDs, then joins the original table to fetch vectors for the matching rows:</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">select</span><span class="token plain"> t1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> embedding</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">from</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">select</span><span class="token plain"> id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> embedding </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">from</span><span class="token plain"> vec_table</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> t1</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">join</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">select</span><span class="token plain"> id</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">from</span><span class="token plain"> vec_table</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">order</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">by</span><span class="token plain"> l2_distance_approximate</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">embedding</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">/* 2,048-dimensional query vector */</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">limit</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token plain">K</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> t2 </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">on</span><span class="token plain"> t1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">id </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> t2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p>The &quot;Business identifier + vector&quot; column in the Section 3.3 table uses this self-join SQL. It primarily measures the cost of reading and materializing the vector column. After the three-stage plan described in Section 2.4 is implemented, users will be able to write the same query directly as:</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">select</span><span class="token plain"> id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> embedding</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">from</span><span class="token plain"> vec_table</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">order</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">by</span><span class="token plain"> l2_distance_approximate</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">embedding</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">/* 2,048-dimensional query vector */</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">limit</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&lt;</span><span class="token plain">K</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&gt;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">-- K is 100, 10,000, or 1,000,000</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p>The materialization stage will then replace the self-join, and the SQL will be identical to a query against a Doris internal table.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="33-measured-results-from-tens-of-millions-to-hundreds-of-millions-of-vectors">3.3 Measured results from tens of millions to hundreds of millions of vectors<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#33-measured-results-from-tens-of-millions-to-hundreds-of-millions-of-vectors" class="hash-link" aria-label="3.3 Measured results from tens of millions to hundreds of millions of vectors &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.3 Measured results from tens of millions to hundreds of millions of vectors &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>The following table reports query performance and recall for different parameter combinations. Both latency columns measure end-to-end latency. Queries that return only business identifiers use the first SQL statement in Section 3.2. Queries that also return vectors use the self-join SQL. The values are representative results from individual queries:</p>






















































<table><thead><tr><th style="text-align:right">Vector count</th><th style="text-align:right">Top-K</th><th style="text-align:right">Business identifier</th><th style="text-align:right">Business identifier + vector</th><th style="text-align:right">Recall</th></tr></thead><tbody><tr><td style="text-align:right">16 million</td><td style="text-align:right">100</td><td style="text-align:right">1.4 seconds</td><td style="text-align:right">2.4 seconds</td><td style="text-align:right">96.0%</td></tr><tr><td style="text-align:right">128 million</td><td style="text-align:right">100</td><td style="text-align:right">1.8 seconds</td><td style="text-align:right">2.5 seconds</td><td style="text-align:right">97.0%</td></tr><tr><td style="text-align:right">16 million</td><td style="text-align:right">10,000</td><td style="text-align:right">1.8 seconds</td><td style="text-align:right">2.3 seconds</td><td style="text-align:right">99.2%</td></tr><tr><td style="text-align:right">128 million</td><td style="text-align:right">10,000</td><td style="text-align:right">2.0 seconds</td><td style="text-align:right">4.6 seconds</td><td style="text-align:right">98.5%</td></tr><tr><td style="text-align:right">16 million</td><td style="text-align:right">1 million</td><td style="text-align:right">7.9 seconds</td><td style="text-align:right">65 seconds</td><td style="text-align:right">97.8%</td></tr><tr><td style="text-align:right">128 million</td><td style="text-align:right">1 million</td><td style="text-align:right">8.0 seconds</td><td style="text-align:right">76 seconds</td><td style="text-align:right">99.6%</td></tr></tbody></table>
<p>The table supports two conclusions:</p>
<ul>
<li>Index-retrieval latency changes little with data scale. When the row count grows from 16 million to 128 million, latency for returning only business identifiers increases by 0.4 seconds, 0.2 seconds, and 0.1 seconds across the three Top-K settings, respectively.</li>
<li>When Top-K = 1 million, vector-column materialization is the bottleneck, not retrieval.</li>
</ul>
<p>These are representative results from individual queries. The table does not cover QPS.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="34-comparing-vector-retrieval-on-paimon-tables-and-doris-internal-tables">3.4 Comparing vector retrieval on Paimon tables and Doris internal tables<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#34-comparing-vector-retrieval-on-paimon-tables-and-doris-internal-tables" class="hash-link" aria-label="3.4 Comparing vector retrieval on Paimon tables and Doris internal tables &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.4 Comparing vector retrieval on Paimon tables and Doris internal tables &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Kwai also compared vector retrieval on Paimon tables with retrieval on Doris internal tables. The team loaded the same Paimon data into Doris internal tables and queried it through Doris&apos;s own vector indexes. The following table gives the results.</p>













































































































<table><thead><tr><th style="text-align:right">Vector count</th><th style="text-align:right">Top-K</th><th>Returned data</th><th style="text-align:right">Doris internal table (local cache)</th><th style="text-align:right">Paimon external table (Alluxio)</th><th style="text-align:right">External / internal</th></tr></thead><tbody><tr><td style="text-align:right">16 million</td><td style="text-align:right">100</td><td>Business identifier</td><td style="text-align:right">0.49 seconds</td><td style="text-align:right">1.4 seconds</td><td style="text-align:right">2.86&#xD7;</td></tr><tr><td style="text-align:right">16 million</td><td style="text-align:right">100</td><td>Business identifier + vector</td><td style="text-align:right">0.7 seconds</td><td style="text-align:right">2.4 seconds</td><td style="text-align:right">3.43&#xD7;</td></tr><tr><td style="text-align:right">128 million</td><td style="text-align:right">100</td><td>Business identifier</td><td style="text-align:right">0.7 seconds</td><td style="text-align:right">1.8 seconds</td><td style="text-align:right">2.57&#xD7;</td></tr><tr><td style="text-align:right">128 million</td><td style="text-align:right">100</td><td>Business identifier + vector</td><td style="text-align:right">0.8 seconds</td><td style="text-align:right">2.5 seconds</td><td style="text-align:right">3.13&#xD7;</td></tr><tr><td style="text-align:right">16 million</td><td style="text-align:right">10,000</td><td>Business identifier</td><td style="text-align:right">0.58 seconds</td><td style="text-align:right">1.8 seconds</td><td style="text-align:right">3.10&#xD7;</td></tr><tr><td style="text-align:right">16 million</td><td style="text-align:right">10,000</td><td>Business identifier + vector</td><td style="text-align:right">1.4 seconds</td><td style="text-align:right">2.3 seconds</td><td style="text-align:right">1.64&#xD7;</td></tr><tr><td style="text-align:right">128 million</td><td style="text-align:right">10,000</td><td>Business identifier</td><td style="text-align:right">0.7 seconds</td><td style="text-align:right">2.0 seconds</td><td style="text-align:right">2.86&#xD7;</td></tr><tr><td style="text-align:right">128 million</td><td style="text-align:right">10,000</td><td>Business identifier + vector</td><td style="text-align:right">1.1 seconds</td><td style="text-align:right">4.6 seconds</td><td style="text-align:right">4.18&#xD7;</td></tr><tr><td style="text-align:right">16 million</td><td style="text-align:right">1 million</td><td>Business identifier</td><td style="text-align:right">7.2 seconds</td><td style="text-align:right">7.9 seconds</td><td style="text-align:right">1.10&#xD7;</td></tr><tr><td style="text-align:right">16 million</td><td style="text-align:right">1 million</td><td>Business identifier + vector</td><td style="text-align:right">61 seconds</td><td style="text-align:right">65 seconds</td><td style="text-align:right">1.07&#xD7;</td></tr><tr><td style="text-align:right">128 million</td><td style="text-align:right">1 million</td><td>Business identifier</td><td style="text-align:right">7.2 seconds</td><td style="text-align:right">8.0 seconds</td><td style="text-align:right">1.11&#xD7;</td></tr><tr><td style="text-align:right">128 million</td><td style="text-align:right">1 million</td><td>Business identifier + vector</td><td style="text-align:right">56 seconds</td><td style="text-align:right">76 seconds</td><td style="text-align:right">1.36&#xD7;</td></tr></tbody></table>
<ul>
<li>External-table latency is 1.07 to 4.18 times internal-table latency. When the query returns only business identifiers, the absolute difference is 0.7 to 1.3 seconds.</li>
<li>At Top-K = 1 million, the difference narrows to 1.07 to 1.36 times. Most of the latency at this setting comes from row lookup and materialization. Both sides read the same amount of data, which reduces the effect of cache location.</li>
</ul>
<p>Figure 7 summarizes the results measured by Kwai.</p>
<p><img decoding="async" loading="lazy" alt="Benchmark overview for IVF-RQ with 2,048-dimensional vectors on 64 CUs. The datasets contain 16 million rows in 150 GB across 32 buckets and 128 million rows in 1.1 TB across 256 buckets. Recall is 96.0% to 99.6%; identifier-only latency is 1.4 to 2.0 seconds for Top-K from 10,000 to 100,000 and 8 seconds for Top-K 1 million; returning vectors at Top-K 1 million takes 65 to 76 seconds." src="https://cdnd.selectdb.com/assets/shared/d4a5f74486b15561b2ed59f08ee9a0b5.jpg" width="1731" height="909" class="img_ev3q"></p>
<p><em>Figure 7: Recall is 96.0% to 99.6% at both scales. Queries that return only business identifiers finish within 2.0 seconds for Top-K values up to 10,000. At Top-K = 1 million, materialization accounts for most of the latency.</em></p>
<p>Internal tables perform better, but returning only business identifiers adds just 0.7 to 1.3 seconds of query latency in absolute terms. In return, Kwai gets the following operational benefits:</p>
<ul>
<li>Better data freshness between writing data to Paimon and making it searchable.</li>
<li>Unified storage without redundant data copies.</li>
<li>No compute-resource overhead for transferring and converting data between different systems.</li>
<li>No separate access-control and governance systems to maintain.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="4-results-and-roadmap-of-joint-development-by-the-doris-and-paimon-communities">4. Results and roadmap of joint development by the Doris and Paimon communities<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#4-results-and-roadmap-of-joint-development-by-the-doris-and-paimon-communities" class="hash-link" aria-label="4. Results and roadmap of joint development by the Doris and Paimon communities &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="4. Results and roadmap of joint development by the Doris and Paimon communities &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Kwai, the Apache Doris community, and the Apache Paimon community developed this read path together. Kwai has contributed more than 120 PRs to the Apache Paimon and Apache Paimon Rust communities. The Doris-side changes are planned for merger into the Doris community within the next two months.</p>
<p>Kwai is also working on the following changes to improve vector retrieval performance when Doris queries Paimon:</p>
<ul>
<li>Three-stage late materialization: The plan described in Section 2.4 separates candidate retrieval from vector-column materialization. At operating points such as Top-K = 1 million, the system will stop reading wide columns for candidate rows that are later discarded. Users will also no longer need to write self-joins manually.</li>
<li>Local index caching: Add local disk and memory caches within the calling process, with Doris providing consistent-hash distribution.</li>
<li>Full-text retrieval and Hybrid Search: The full-text retrieval path is already complete on the Paimon side. After the Doris-side integration is complete, users will be able to combine structured filtering, keyword matching, and semantic retrieval on the same lake table.</li>
<li>Completing retrieval semantics: Add similarity-range retrieval. Kwai has begun an internal grayscale rollout and plans to contribute the feature to the community after large-scale production validation. Retrieval parameters will also become overridable per query instead of remaining limited to table-level configuration.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="learn-more">Learn more<a href="https://doris.apache.org/ko/blog/kwai-paimon-vector-search-apache-doris/#learn-more" class="hash-link" aria-label="Learn more &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Learn more &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>The multimodal lakehouse capabilities for Paimon, Iceberg, Lance, and other formats have been merged into the <strong>Doris 4.2</strong> release branch. They are scheduled for official release with version 4.2 at the <strong>end of September</strong>.</p></div>]]></content:encoded>
            <category>Best Practice</category>
        </item>
        <item>
            <title><![CDATA[Apache Doris x Paimon 2.0: Closing the Agentic AI Data Loop]]></title>
            <link>https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/</link>
            <guid>https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/</guid>
            <pubDate>Wed, 09 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[A technical look at Apache Doris and Paimon 2.0 for Agentic AI, covering vector indexes, fresh business context, SQL queries, and feedback write-back.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Tech Sharing</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">Apache Doris x Paimon 2.0: Closing the Agentic AI Data Loop</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">Apache Doris &#xB7; Wenqiang Li</span></span><time datetime="2026-09-09T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 9&#xC6D4; 9&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<p><strong>Abstract</strong></p>
<p><a href="https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/">Apache Doris 5.0 Multimodal Lakehouse Preview</a> (2) | Scenario solutions:</p>
<p>Agentic AI is moving enterprise AI beyond one-off question answering and into a continuous &quot;perceive-retrieve-analyze-act-feedback&quot; cycle. Paimon 2.0 manages changing business facts, multimodal data, and indexes in one system, while Doris uses unified SQL to connect vector retrieval, real-time analytics, and result write-back. Together, they give agents current, consistent, and verifiable business context.</p>
</blockquote>
<hr>
<p>Large models determine what an agent can understand. The data platform determines what the agent knows and can trust at a given moment, along with what it retains after taking action. Agentic AI is moving enterprise AI beyond one-off question answering and into a continuous &quot;perceive-retrieve-analyze-act-feedback&quot; cycle.</p>
<p>Agents need access to more than documents and knowledge bases. They also need current orders, inventory, device status, images, videos, vectors, model outputs, and historical results. A real request requires more than semantic retrieval. It may combine vector and full-text search with structured filtering, cross-table joins, metric computation, and permission checks. This creates two requirements for the data platform. The underlying data must support continuous updates and schema evolution in an open format. The query engine must connect multimodal retrieval, real-time analytics, and result write-back in one execution pipeline.</p>
<p>Apache Paimon 2.0 and Apache Doris address these requirements at different layers. Paimon 2.0 manages continuously changing business facts, multimodal content, model features, and indexes. Doris provides unified SQL for reads, writes, vector retrieval, relational computation, and application serving. Together, they supply agents with current, consistent, and verifiable business context.</p>
<p><img decoding="async" loading="lazy" alt="Open data loop for Agentic AI: Paimon 2.0 manages evolving data and indexes, while Doris unifies retrieval, analytics, and serving" src="https://cdnd.selectdb.com/assets/shared/d7d657a8ccc3204b8685d083c45b6b81.jpg" width="1731" height="909" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="1-core-challenges-of-agentic-ai">1. Core challenges of Agentic AI<a href="https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/#1-core-challenges-of-agentic-ai" class="hash-link" aria-label="1. Core challenges of Agentic AI &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1. Core challenges of Agentic AI &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Traditional BI primarily answers, &quot;What happened in the past?&quot; Traditional RAG primarily answers, &quot;Which documents are relevant to this question?&quot; Agentic AI must answer additional questions: Does the current state permit an action? Do separate pieces of evidence support the same conclusion? What happened after similar actions in the past? How will this action become part of the context for the next request? Consider an industrial fault-diagnosis agent that receives a new defect image. Returning a few visually similar historical images is not enough.</p>
<p>The agent must also determine whether those defects came from the same equipment model and production stage. It needs to check whether sensor metrics were abnormal before or after the event, whether the equipment is currently under maintenance, whether similar problems are occurring in a cluster, and which remediation method improved the yield of subsequent batches. Requests of this kind expose four data challenges.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="11-context-continuously-growing-multimodal-data">1.1 Context: continuously growing multimodal data<a href="https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/#11-context-continuously-growing-multimodal-data" class="hash-link" aria-label="1.1 Context: continuously growing multimodal data &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1.1 Context: continuously growing multimodal data &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>A business record is rarely completed in one operation. Orders, equipment records, and user states may arrive first. Images, videos, and logs appear later. Different jobs then add OCR results, captions, embeddings, model scores, and human-generated labels asynchronously. Model upgrades add new versions of features to the same data. Agents therefore need more than a static wide table. They need a data asset that can keep acquiring fields, content, features, and indexes.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="12-retrieval-produces-candidates-business-analysis-produces-answers">1.2 Retrieval produces candidates; business analysis produces answers<a href="https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/#12-retrieval-produces-candidates-business-analysis-produces-answers" class="hash-link" aria-label="1.2 Retrieval produces candidates; business analysis produces answers &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1.2 Retrieval produces candidates; business analysis produces answers &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Vector retrieval can find semantically or visually similar objects, but it cannot determine inventory, permissions, equipment status, time ranges, or business outcomes on its own. To produce context on which an agent can act, the system must combine vector or full-text retrieval with structured filtering, joins, aggregations, window computations, and business-specific ranking.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="13-agents-need-current-and-consistent-context">1.3 Agents need current and consistent context<a href="https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/#13-agents-need-current-and-consistent-context" class="hash-link" aria-label="1.3 Agents need current and consistent context &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1.3 Agents need current and consistent context &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>When business facts and model features are spread across lake tables, object storage, vector databases, and search systems, each system may have different update times, versions, and deletion states. A stale index may still return a delisted product, a device under maintenance, or a withdrawn document and pass it to an agent.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="14-agent-actions-must-feed-back-into-the-data-loop">1.4 Agent actions must feed back into the data loop<a href="https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/#14-agent-actions-must-feed-back-into-the-data-loop" class="hash-link" aria-label="1.4 Agent actions must feed back into the data loop &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1.4 Agent actions must feed back into the data loop &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Agents produce classifications, summaries, risk scores, tool-call results, and processing states. Human review adds final labels. If those results remain in the application layer, the next analysis cannot use the latest feedback. The data platform must support reads and write-back while preserving transactional consistency. Agentic AI therefore needs more than a vector database. It needs a complete data pipeline in which multimodal data can evolve, indexes can expand their coverage, business facts remain current, retrieval results can be analyzed, and action results can be written back.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="2-paimon-20-continuously-evolving-the-data-required-by-agents">2. Paimon 2.0: continuously evolving the data required by agents<a href="https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/#2-paimon-20-continuously-evolving-the-data-required-by-agents" class="hash-link" aria-label="2. Paimon 2.0: continuously evolving the data required by agents &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2. Paimon 2.0: continuously evolving the data required by agents &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Paimon has traditionally used Flink to ingest database CDC and message streams continuously. It maintains real-time lake tables on object storage and supports updates, deletions, snapshots, and incremental reads. Paimon 2.0 expands that scope from &quot;continuously updated structured rows&quot; to &quot;continuously growing multimodal data assets.&quot;</p>
<ul>
<li><code>BLOB</code> stores large objects such as images, videos, and audio in separate files. Queries do not need to read the object contents when the column is not selected.</li>
<li><code>VECTOR&lt;t, n&gt;</code> provides fixed-dimension semantics and a specialized storage layout for embeddings.</li>
<li><code>VARIANT</code> stores events, model outputs, and tool-call parameters with flexible structures, while allowing frequently used fields to be extracted into typed subcolumns.</li>
<li>Data Evolution allows models to add or update only changed columns without repeatedly rewriting unchanged large objects and business fields.</li>
<li>Global Row ID aligns data files, BLOBs, vectors, indexes, and deletion states with the same logical record.</li>
<li>Global Index incorporates scalar, full-text, and vector indexes into the lake table&apos;s metadata and snapshot system.</li>
</ul>
<p>These capabilities do not force every type of data into the same file format. Each modality can use a suitable physical layout while remaining consistent with the same table, snapshot, and logical record. The system can identify newly written data and the current index coverage, then address freshness by backfilling indexes or selecting an appropriate query mode.</p>
<p>Paimon 2.0 handles how agent data is stored, updated, evolved, and indexed. It does not, by itself, perform cross-table joins, global Top-K computation, real-time metric calculation, permission checks, or high-concurrency serving. Turning this open data into context that agents can use also requires Doris&apos;s query and execution capabilities.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="3-doris-and-paimon-integration-turning-open-data-into-agent-context">3. Doris and Paimon integration: turning open data into agent context<a href="https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/#3-doris-and-paimon-integration-turning-open-data-into-agent-context" class="hash-link" aria-label="3. Doris and Paimon integration: turning open data into agent context &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3. Doris and Paimon integration: turning open data into agent context &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Doris support for Paimon 2.0 goes beyond scanning Paimon files as ordinary Parquet files. The integration connects three paths: snapshot-consistent lake-table reads, multimodal retrieval through Vector Index, and standard SQL writes to Paimon.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="31-reading-the-latest-business-facts-while-preserving-paimon-table-semantics">3.1 Reading the latest business facts while preserving Paimon table semantics<a href="https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/#31-reading-the-latest-business-facts-while-preserving-paimon-table-semantics" class="hash-link" aria-label="3.1 Reading the latest business facts while preserving Paimon table semantics &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.1 Reading the latest business facts while preserving Paimon table semantics &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Doris discovers databases and tables through the Paimon Catalog and caches their metadata. Within one SQL statement, it binds a consistent snapshot and schema. The query planner understands manifests, Primary Key merging, Deletion Vector, incremental ranges, Time Travel, Branch, and Tag, so it does not treat Paimon Primary Key tables as ordinary file scans. Agents can retrieve a consistent business state from a specified snapshot and use incremental queries to detect changes in orders, inventory, equipment, and user states.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="32-vector-retrieval-bringing-vector-index-into-the-doris-query-plan">3.2 Vector retrieval: bringing Vector Index into the Doris query plan<a href="https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/#32-vector-retrieval-bringing-vector-index-into-the-doris-query-plan" class="hash-link" aria-label="3.2 Vector retrieval: bringing Vector Index into the Doris query plan &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.2 Vector retrieval: bringing Vector Index into the Doris query plan &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Doris FE plans and distributes splits, while BE calls the Paimon Rust Reader through the C ABI. A vector query first reads the Vector Index, searches index shards in parallel, and merges the candidates. It then pushes the candidate range down to files, Row Groups, and Parquet Pages. The reader loads vectors, BLOB metadata, and other wide columns only after confirming matches. Results from Rust enter C++ through the Arrow C Data Interface and are converted into Doris Blocks.</p>
<p>The candidate set then enters the Doris MPP engine for scalar filtering, cross-table joins, aggregation, permission checks, reranking, and global Top-K computation. Vector retrieval is a candidate-generation stage within a distributed SQL plan, not a separate system beside Doris. Paimon Vector Index finds relevant data, while Doris determines whether that data is valid, important, and actionable in the current business context.</p>
<p>Community work and Kwai&apos;s production deployments have validated this path. Paimon external tables connect to Doris through the Rust Reader, with data scales ranging from millions to billions of records and Top-K values ranging from 100 to 1 million. Candidate pushdown and on-demand materialization limit the cost of reading wide vectors.</p>
<p><img decoding="async" loading="lazy" alt="Vector Index in the Doris query plan: Paimon retrieves and prunes candidates, while Doris performs business filtering, joins, reranking, and global Top-K" src="https://cdnd.selectdb.com/assets/shared/c8a3bd3266cb82a8f16556fefa510ab9.jpg" width="1200" height="630" class="img_ev3q"></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="33-real-time-writes-writing-to-paimon-with-standard-sql">3.3 Real-time writes: writing to Paimon with standard SQL<a href="https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/#33-real-time-writes-writing-to-paimon-with-standard-sql" class="hash-link" aria-label="3.3 Real-time writes: writing to Paimon with standard SQL &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.3 Real-time writes: writing to Paimon with standard SQL &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>An Agentic AI data pipeline cannot stop after reading data. If aggregation results, model labels, risk scores, and human-review states produced by Doris still require separate Spark or Flink jobs for write-back, the architecture again has fragmented transactional boundaries and additional operational pipelines.</p>
<p>For Doris 4.2, the Paimon Catalog is planned to expand from read-only access to integrated read and write support, including:</p>
<ul>
<li><code>INSERT INTO ... SELECT</code> and <code>INSERT ... VALUES</code> for appending query results or application data to Paimon.</li>
<li><code>INSERT OVERWRITE</code> for overwriting non-partitioned tables or data in static or dynamic partitions.</li>
<li><code>UPDATE</code>, <code>DELETE</code>, and <code>MERGE</code> for updating business states, model labels, and human feedback in Primary Key tables.</li>
<li><code>CREATE TABLE</code> and schema evolution for adding, deleting, renaming, and changing the types of fields.</li>
<li>Variant reads and writes, allowing model results and tool-call parameters with continuously changing structures to enter open lake tables directly.</li>
</ul>
<p>Doris distributes data across BEs according to Paimon&apos;s partitioning and bucket rules, and the BEs generate files in parallel. The FE then collects Commit Messages from multiple writers and creates an atomically visible Paimon snapshot. When a failure or retry occurs, the commit coordinator handles termination, cleanup, deduplication, and idempotent recovery. This prevents partially visible data and duplicate commits. Results produced by agents can return to the same open dataset and become context for later queries and decisions.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="4-execution-framework-how-an-agent-request-completes-retrieval-analysis-and-write-back">4. Execution framework: how an agent request completes retrieval, analysis, and write-back<a href="https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/#4-execution-framework-how-an-agent-request-completes-retrieval-analysis-and-write-back" class="hash-link" aria-label="4. Execution framework: how an agent request completes retrieval, analysis, and write-back &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="4. Execution framework: how an agent request completes retrieval, analysis, and write-back &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p><img decoding="async" loading="lazy" alt="Doris and Paimon vector-search execution flow" src="https://cdnd.selectdb.com/assets/shared/e520e72ac84152379bb686927d1f252d.jpg" width="1731" height="909" class="img_ev3q"></p>
<p>For vector retrieval in an agent request, Paimon Vector Index first narrows the candidates. Doris then performs the business analysis. After a vector query enters Doris, execution proceeds in three stages:</p>
<ol>
<li>
<p><strong>Plan the context.</strong> Doris FE parses the Vector SQL, binds the Paimon snapshot and schema used by the query, and generates parallel splits.</p>
</li>
<li>
<p><strong>Retrieve and read on demand.</strong> BE invokes Paimon Rust through the C ABI. Vector Index produces Top-K candidates, after which the reader prunes files, Row Groups, and Pages according to the candidate range and materializes only matching columns.</p>
</li>
<li>
<p><strong>Generate the business answer.</strong></p>
<ol>
<li>Arrow data is converted into Doris Blocks and enters the MPP engine for joins, filters, aggregation, reranking, and global Top-K computation. The result is then returned to the agent through SQL, an API, or a tool call.</li>
<li>When an agent or human confirmation produces new labels, states, or processing results, Doris starts another write path. Nereids generates a DML plan, data is routed to parallel writers on the BEs, and Commit Messages are returned to the FE for aggregation and atomic commit as a new Paimon snapshot. The new results then become available for the next round of incremental reads, index backfilling, and agent analysis.</li>
<li>With further native integration, Doris will directly consume Paimon Global Index Results, use Global Row IDs to read matching rows, and understand index coverage, the <code>fast</code> / <code>full</code> / <code>detail</code> freshness modes, and the Deletion Vector of the current snapshot. Manifests, index shards, vector pages, and matching data pages will also be managed separately through a tiered local cache.</li>
</ol>
</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="5-production-use-kwai-brings-vector-retrieval-back-to-paimon-lake-tables">5. Production use: Kwai brings vector retrieval back to Paimon lake tables<a href="https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/#5-production-use-kwai-brings-vector-retrieval-back-to-paimon-lake-tables" class="hash-link" aria-label="5. Production use: Kwai brings vector retrieval back to Paimon lake tables &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="5. Production use: Kwai brings vector retrieval back to Paimon lake tables &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p><img decoding="async" loading="lazy" alt="Kwai&amp;#39;s large-scale vector retrieval architecture using Apache Doris and Paimon 2.0" src="https://cdnd.selectdb.com/assets/shared/8939ddeec3e5e66f8705545fe0d337ac.jpg" width="1731" height="909" class="img_ev3q"></p>
<p>In Kwai&apos;s production environment, vectors and business data remain in Paimon, while Doris handles retrieval, row lookup, and analysis. Kwai needed to provide large-scale vector retrieval on its existing Paimon real-time lakehouse while keeping business data, vectors, permission fields, and update states consistent.</p>
<p>Copying vectors, filter fields, and return fields into a separate vector database would create a second copy of the business data and another synchronization pipeline that would need long-term maintenance. As model versions, business states, and deletion states change, the retrieval system could return stale results that no longer match the current business state.</p>
<p>Kwai chose to keep vectors and business data in Paimon Primary Key tables and connect vector retrieval to Doris external-table queries:</p>
<ol>
<li>Paimon tables store business fields and 2,048-dimensional vectors inline. An IVF-RQ Vector Index retrieves candidates, while remote Alluxio provides caching for data and index reads.</li>
<li>Users continue to use Doris SQL. Doris FE plans and distributes splits, and BE invokes the Paimon Rust Reader through the C ABI.</li>
<li>Paimon Rust executes vector retrieval in parallel and merges the candidates. Candidate ranges are pushed down to files, Row Groups, and Parquet Pages, avoiding the need to scan and decode the complete vector column in advance.</li>
<li>When only business identifiers are required, queries can skip materializing wide vectors. When vectors need to be returned, candidate identifiers are used to look up the corresponding rows, reading only matching pages and records.</li>
<li>Read results are converted into Doris Blocks through the Arrow C Data Interface and continue through MPP computations such as filtering, joins, aggregation, and Top-K.</li>
</ol>
<p>Production validation covered datasets with tens of millions and hundreds of millions of records. Public tests used 16 million and 128 million real 2,048-dimensional vectors, with Top-K values of 100, 10,000, and 1 million. Recall through the Paimon external-table path ranged from 96.0% to 99.6%. When comparing &quot;Paimon external tables with remote Alluxio caching&quot; against &quot;Doris internal tables with local caching,&quot; query latency was 1.07 to 4.18 times that of the latter. At a Top-K of 1 million, the gap narrowed to 1.07 to 1.36 times.</p>
<p>These results show that users can keep open data in Paimon and use Doris SQL for vector retrieval and business analysis, even with hundreds of millions of high-dimensional vectors and Top-K values as large as 1 million. They do not have to copy the entire dataset into Doris internal tables or another vector database first.</p>
<p>For Agentic AI, retrieval results can be joined directly with the latest business state in Paimon. Doris can then apply permission filters, compute metrics, and perform relational analysis. Agents receive similar objects together with context that matches current business facts and can be verified before the system acts on it.</p>
<blockquote>
<p>Availability: The Paimon capabilities used in these examples are in the Doris 4.2 release branch and are scheduled for public release at the end of September. Use the examples as preview syntax until that release is available.</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="6-getting-started">6. Getting started<a href="https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/#6-getting-started" class="hash-link" aria-label="6. Getting started &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="6. Getting started &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Teams already using Flink and Paimon do not need to change their existing data pipeline as a first step. They can create a Paimon Catalog in Doris:</p>
<div class="language-SQL language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">CREATE</span><span class="token plain"> CATALOG paimon_catalog PROPERTIES </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;type&apos;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;paimon&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;warehouse&apos;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;s3://example-bucket/warehouse&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;s3.endpoint&apos;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;https://object-storage.example.com&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;s3.region&apos;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;region-id&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;s3.access_key&apos;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;YOUR_ACCESS_KEY&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;s3.secret_key&apos;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;YOUR_SECRET_KEY&apos;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p>Perform structured analysis through Doris SQL:</p>
<div class="language-SQL language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">SELECT</span><span class="token plain"> device_model</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> defect_type</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">COUNT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">AS</span><span class="token plain"> defect_count</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> paimon_catalog</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">quality</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">inspection_records</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">WHERE</span><span class="token plain"> event_time </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&gt;=</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">NOW</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">INTERVAL</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">30</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">DAY</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">GROUP</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">BY</span><span class="token plain"> device_model</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> defect_type</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">BY</span><span class="token plain"> defect_count </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">DESC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p>In the community-developed vector retrieval path, express Top-K queries through Doris SQL:</p>
<div class="language-SQL language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">SELECT</span><span class="token plain"> id</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> paimon_catalog</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">quality</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">vector_items</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">BY</span><span class="token plain"> l2_distance_approximate</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">embedding</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">LIMIT</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">100</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p>After the analysis is complete, write the aggregated results directly back to Paimon:</p>
<div class="language-SQL language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">INSERT</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">INTO</span><span class="token plain"> paimon_catalog</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">quality</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">daily_defect_summary</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">SELECT</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">DATE</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">event_time</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> device_model</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> defect_type</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">COUNT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> paimon_catalog</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">quality</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">inspection_records</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">GROUP</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">BY</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">DATE</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">event_time</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> device_model</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> defect_type</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p>For Primary Key tables that require continuous state corrections, use <code>MERGE</code> to incorporate human reviews or new model results:</p>
<div class="language-SQL language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">MERGE</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">INTO</span><span class="token plain"> paimon_catalog</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">quality</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">inspection_records </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">AS</span><span class="token plain"> target</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">USING</span><span class="token plain"> review_results </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">AS</span><span class="token plain"> source</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">ON</span><span class="token plain"> target</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">record_id </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> source</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">record_id</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">WHEN</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">MATCHED</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">THEN</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">UPDATE</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">SET</span><span class="token plain"> review_status </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> source</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">review_status</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">               defect_type </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> source</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">defect_type</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">WHEN</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">NOT</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">MATCHED</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">THEN</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">INSERT</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">record_id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> review_status</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> defect_type</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">VALUES</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">source</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">record_id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> source</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">review_status</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> source</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">defect_type</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="7-conclusion-using-business-facts-as-they-emerge">7. Conclusion: using business facts as they emerge<a href="https://doris.apache.org/ko/blog/apache-doris-paimon-agentic-ai-data-loop/#7-conclusion-using-business-facts-as-they-emerge" class="hash-link" aria-label="7. Conclusion: using business facts as they emerge &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="7. Conclusion: using business facts as they emerge &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>The data problem in Agentic AI is broader than adding a vector field or deploying a vector database. The system must keep changing business facts, multimodal content, model features, retrieval indexes, and action results consistent. It must then turn that data into verifiable context when an agent needs it.</p>
<p>Paimon 2.0 provides an open foundation for storing, updating, evolving, and indexing this data. Apache Doris connects Paimon snapshot reads, Vector Index, MPP OLAP, and standard SQL writes. This allows agents to maintain a continuous &quot;perceive changes-retrieve evidence-analyze and decide-take action-write back feedback&quot; loop.</p>
<p>Doris users do not need to maintain a separate closed copy of their data for AI workloads. The data can remain in Paimon while Doris handles retrieval and analysis. Doris can then write query results and agent feedback back to the open lake tables. Paimon allows the data used by agents to evolve continuously, while Doris turns that data into current, verifiable business context on which agents can act.</p>
<p>We will publish more articles about the Apache Doris 5.0 multimodal lakehouse and open formats such as Iceberg and Paimon. The series will cover the underlying technical principles, performance evaluations, and typical deployment scenarios.</p>
<hr>
<p>Multimodal lakehouse capabilities for Iceberg, Paimon, Lance, and other formats have now been merged into the Doris 4.2 release branch and are scheduled for official release with version 4.2 at the end of September.</p></div>]]></content:encoded>
            <category>Tech Sharing</category>
        </item>
        <item>
            <title><![CDATA[Apache Doris x Lance for Autonomous Driving and Robotics Analytics]]></title>
            <link>https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/</link>
            <guid>https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/</guid>
            <pubDate>Tue, 08 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[How Apache Doris and Lance support hard-case mining for autonomous driving and failure analysis for robotics with open multimodal datasets.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Tech Sharing</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">Apache Doris x Lance for Autonomous Driving and Robotics Analytics</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">Apache Doris &#xB7; Wenqiang Li</span></span><time datetime="2026-09-08T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 9&#xC6D4; 8&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<p><strong>Abstract:</strong></p>
<p>Apache Doris 5.0 Multimodal Lakehouse Preview (1) | Scenario solutions: Autonomous vehicles and embodied intelligence systems generate massive volumes of multimodal data every day. The practical problem is finding high-value episodes quickly and identifying the scenarios, versions, and tasks associated with failures. This article explains how Apache Doris and Lance combine semantic search, structured filtering, and OLAP analytics for hard-case mining, failure attribution, and closed-loop training and evaluation on an open data architecture.</p>
</blockquote>
<p>Autonomous vehicles generate video, point clouds, vehicle states, and model outputs every day. Each robot task also produces multiple camera streams, joint states, action trajectories, language instructions, and execution results. Storing this data is only part of the problem. Teams must also answer the questions that determine how efficiently they can iterate on their models:</p>
<ul>
<li>Which segments contain scenarios similar to the current accident?</li>
<li>Has the intervention rate of the new model increased at night, in construction zones, or around irregularly shaped obstacles?</li>
<li>Which types of robot tasks are most likely to fail, and what similar visual or action patterns appear before failure?</li>
<li>How can selected high-value episodes be passed to annotation, training, and regression evaluation?</li>
</ul>
<p>Traditional data warehouses handle structured aggregation well. Vector databases specialize in image similarity search, while object storage holds large numbers of files at low cost. Physical AI needs these capabilities to work together, so semantic search, structured filtering, business metrics, and raw evidence can be used in the same analytical workflow.</p>
<p>Apache Doris support for Lance Catalog provides that connection. Lance stores open multimodal datasets and vector indexes designed for AI. Doris queries the data directly and performs predicate pushdown, parallel scans, vector retrieval, global Top-K selection, and OLAP aggregation within a single SQL execution framework. Teams do not need to copy the data into a dedicated analytical replica first, and their AI data assets remain available to more than one compute system.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="1-why-physical-ai-needs-semantic-search-and-analytics-not-vector-search-alone">1. Why physical AI needs semantic search and analytics, not vector search alone<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#1-why-physical-ai-needs-semantic-search-and-analytics-not-vector-search-alone" class="hash-link" aria-label="1. Why physical AI needs semantic search and analytics, not vector search alone &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1. Why physical AI needs semantic search and analytics, not vector search alone &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Data for autonomous driving and embodied intelligence is naturally organized around episodes. An episode is a reconstructable physical process rather than a single image: sensors observe the environment, a model makes a decision, a control system executes an action, and the physical world produces an outcome.</p>
<p>In autonomous driving, finding images similar to the five seconds before an accident is only the first step. Engineering teams must further constrain the search by vehicle model, sensor version, road type, weather, model version, and time range. They then need to compare intervention rates, false-positive rates, or planning deviations among the candidate segments. The same applies to embodied intelligence. A failed grasp involves visual semantics, but it must also be examined in the context of the task type, robot arm model, policy version, joint states, action trajectory, and final outcome.</p>
<p>Finding high-value data therefore requires at least three layers of computation:</p>
<ol>
<li>Use structured conditions to narrow the search space to the correct business context.</li>
<li>Use vector similarity to find related scenarios that the labeling system does not yet cover.</li>
<li>Use aggregation, joins, sorting, and window analysis to turn candidate segments into model evaluation findings and actionable datasets.</li>
</ol>
<p>Lance and Doris handle different parts of this process. Lance manages AI datasets, random access, and vector indexes. Doris brings the retrieval results into an explainable, composable SQL analytics system.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="2-overall-architecture-lance-manages-ai-data-assets-and-doris-provides-unified-queries-and-analytics">2. Overall architecture: Lance manages AI data assets, and Doris provides unified queries and analytics<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#2-overall-architecture-lance-manages-ai-data-assets-and-doris-provides-unified-queries-and-analytics" class="hash-link" aria-label="2. Overall architecture: Lance manages AI data assets, and Doris provides unified queries and analytics &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2. Overall architecture: Lance manages AI data assets, and Doris provides unified queries and analytics &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p><img decoding="async" loading="lazy" alt="Apache Doris and Lance in the Physical AI data architecture" src="https://cdnd.selectdb.com/assets/shared/67c98e7629aa2e5be5b0442f83102ceb.jpg" width="1200" height="630" class="img_ev3q"></p>
<p><strong>Figure 1. Apache Doris and Lance in the Physical AI data architecture</strong></p>
<p>In this architecture, upstream systems continue to use tools such as the Lance SDK, Ray, and Spark to generate and maintain Lance datasets. These datasets include features, embeddings, labels, model outputs, and existing Lance vector indexes. The data can reside in a local file system, S3-compatible object storage, or OSS.</p>
<p>Apache Doris uses Lance Catalog to discover datasets and schemas. During a query, Doris fixes the snapshot, divides fragments or index segments, runs scans and searches in parallel, and performs global Top-K selection and OLAP computation.</p>
<p>Apache Doris covers a layer that can otherwise be fragmented across separate tools before and after training. Engineers, algorithm teams, business analysts, and agents can use the same system to find data, validate models, locate problems, and construct the next training dataset.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="3-autonomous-driving-find-similar-video-and-build-a-closed-hard-case-mining-loop">3. Autonomous driving: Find similar video and build a closed hard-case mining loop<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#3-autonomous-driving-find-similar-video-and-build-a-closed-hard-case-mining-loop" class="hash-link" aria-label="3. Autonomous driving: Find similar video and build a closed hard-case mining loop &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3. Autonomous driving: Find similar video and build a closed hard-case mining loop &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="31-finding-high-value-scenarios-is-the-bottleneck">3.1 Finding high-value scenarios is the bottleneck<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#31-finding-high-value-scenarios-is-the-bottleneck" class="hash-link" aria-label="3.1 Finding high-value scenarios is the bottleneck &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.1 Finding high-value scenarios is the bottleneck &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>In autonomous driving development, hard-case mining means finding high-value scenarios within massive volumes of driving data where models are prone to false positives, false negatives, abnormal braking, or human intervention. These segments make up only a small proportion of all fleet data, but they directly affect model safety and coverage of long-tail scenarios.</p>
<p>Collecting the data is usually easier than finding the right records within the full set of driving data. The main bottlenecks and corresponding solutions include:</p>
<ul>
<li><strong>Anomalous segments are rare, and their context is scattered.</strong> Vehicles continuously generate data from multiple cameras, point clouds, localization systems, vehicle states, and model outputs. An anomaly may exist only in a segment lasting a few seconds and may occur across different vehicle models, roads, weather conditions, and sensor versions. Doris can first narrow the search by business conditions such as time, vehicle model, road, weather, and model version.</li>
<li><strong>Existing labels cannot cover all semantics.</strong> Queries based only on time, vehicle, or labels can easily miss semantically similar segments that have not yet been labeled. Lance stores episode metadata, embeddings, and vector indexes, and Doris reuses those indexes to retrieve similar scenarios.</li>
<li><strong>Similarity results are not yet engineering conclusions.</strong> Vector similarity search alone may return results from irrelevant business contexts and cannot directly determine issue frequency, model-version regressions, or sample value. Once the candidate results enter Doris, distributed statistics and version comparisons can identify the episodes that should be included in annotation, training, and evaluation.</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="32-a-practical-hard-case-mining-workflow">3.2 A practical hard-case mining workflow<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#32-a-practical-hard-case-mining-workflow" class="hash-link" aria-label="3.2 A practical hard-case mining workflow &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.2 A practical hard-case mining workflow &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Suppose a team wants to find segments that are visually and semantically similar to an emergency-braking event involving an irregularly shaped obstacle. The event occurred on urban roads, and the team wants to determine whether the problem is concentrated in a particular perception model version:</p>
<ol>
<li>The Lance dataset stores <code>episode_id</code>, time, road and weather labels, vehicle model, model version, intervention or emergency-braking results, image or segment embeddings, and raw media location information.</li>
<li>Doris pushes down conditions such as time range, urban roads, vehicle model, and model version to narrow the search space before generating vector candidates.</li>
<li>Doris reuses existing Lance vector indexes and searches them in parallel. Fragments not covered by an index are automatically supplemented with Flat Search.</li>
<li>Each parallel task returns local candidates, which Doris merges into a global Top-K result.</li>
<li>SQL aggregates intervention rates, emergency-braking rates, and sample counts by model version, weather, and road type to produce a hard-case distribution.</li>
<li>Candidate <code>episode_id</code> values are sent for human review, annotation, inclusion in a training dataset, or regression evaluation. The Lance SDK reads the raw media precisely.</li>
</ol>
<p><img decoding="async" loading="lazy" alt="Closed-loop hard-case mining for autonomous driving" src="https://cdnd.selectdb.com/assets/shared/c6824edff6dc067893385019688955ff.jpg" width="1200" height="630" class="img_ev3q"></p>
<p><strong>Figure 2. Autonomous-driving hard-case mining: from fleet data to model iteration</strong></p>
<p>This workflow does not require every capability to live in one storage format. Instead, it keeps similar scenarios connected to their business context. Algorithm engineers receive more than a page of similar images. They can determine which versions exhibit similar problems, whether a regression is occurring, how many vehicles and road conditions are affected, and which episodes are most useful for the next training cycle.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="33-find-similar-scenarios-with-a-single-sql-query">3.3 Find similar scenarios with a single SQL query<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#33-find-similar-scenarios-with-a-single-sql-query" class="hash-link" aria-label="3.3 Find similar scenarios with a single SQL query &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="3.3 Find similar scenarios with a single SQL query &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Suppose an upstream tool has already created a <code>scene_embedding</code> index in the Lance dataset. Doris can start a search through <code>vector_search()</code>:</p>
<div class="language-SQL language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">SELECT</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    episode_id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    event_time</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    road_type</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    weather</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    model_version</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    intervention</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    _distance</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> vector_search</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;table&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;lance_ai.autodrive.scene_episodes&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;column&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;scene_embedding&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;query_vector&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;[0.12, -0.08, 0.31, ...]&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;top_k&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;200&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;metric&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;cosine&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;nprobes&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;20&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;refine_factor&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;10&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;filter&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;road_type = &apos;urban&apos; AND event_time &gt;= &apos;2026-08-01&apos;&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;use_index&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;true&quot;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">BY</span><span class="token plain"> _distance </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">ASC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> episode_id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p>Here, <code>filter</code> performs pre-filtering. It first restricts the search to the correct scenario range, then generates vector candidates. This behavior usually fits the semantics of hard-case mining better than post-filtering with <code>WHERE</code> outside the TVF. A smaller <code>_distance</code> value indicates greater similarity. Adding a unique key explicitly as the second sort field produces a stable return order when distances are equal.</p>
<p>Vector candidates can also feed standard SQL aggregation. For example, the following query calculates the distribution of interventions in similar scenarios by model version:</p>
<div class="language-SQL language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">WITH</span><span class="token plain"> similar_scenes </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">AS</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">SELECT</span><span class="token plain"> model_version</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> weather</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> intervention</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> _distance</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> vector_search</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;table&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;lance_ai.autodrive.scene_episodes&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;column&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;scene_embedding&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;query_vector&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;[0.12, -0.08, 0.31, ...]&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;top_k&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;1000&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;metric&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;cosine&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;filter&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;road_type = &apos;urban&apos;&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">        </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;use_index&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;true&quot;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">SELECT</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    model_version</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    weather</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token function" style="color:hsl(221, 87%, 60%)">COUNT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">AS</span><span class="token plain"> scene_count</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token function" style="color:hsl(221, 87%, 60%)">SUM</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">CASE</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">WHEN</span><span class="token plain"> intervention </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">THEN</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">ELSE</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">END</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">AS</span><span class="token plain"> intervention_count</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> similar_scenes</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">GROUP</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">BY</span><span class="token plain"> model_version</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> weather</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">BY</span><span class="token plain"> intervention_count </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">DESC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="4-embodied-intelligence-make-every-episode-searchable-comparable-and-reviewable">4. Embodied intelligence: Make every episode searchable, comparable, and reviewable<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#4-embodied-intelligence-make-every-episode-searchable-comparable-and-reviewable" class="hash-link" aria-label="4. Embodied intelligence: Make every episode searchable, comparable, and reviewable &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="4. Embodied intelligence: Make every episode searchable, comparable, and reviewable &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="41-robot-data-requires-cross-frequency-alignment-random-access-and-cross-episode-analytics">4.1 Robot data requires cross-frequency alignment, random access, and cross-episode analytics<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#41-robot-data-requires-cross-frequency-alignment-random-access-and-cross-episode-analytics" class="hash-link" aria-label="4.1 Robot data requires cross-frequency alignment, random access, and cross-episode analytics &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="4.1 Robot data requires cross-frequency alignment, random access, and cross-episode analytics &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>An embodied intelligence task typically produces data in several forms and at different frequencies. Robot arm states and control signals may be collected at hundreds of hertz, while multiple cameras record environmental changes at tens of frames per second. Other data includes language instructions, frame-level labels, intermediate model results, and information about task success, failure, and retries.</p>
<p>If this data is stored separately in video files, columnar files, and JSON, teams must maintain timestamp alignment and version mappings across those files. They must also repeatedly implement data-assembly logic for training, playback, and problem analysis. A random read may require locating the video segment first, then finding the corresponding state and action records. When schemas or features change, separate copies of the data can become inconsistent.</p>
<p>Training frameworks focus on reading batches of samples at high throughput. Research and development analytics has a different job: locating similar failures among millions of episodes, comparing policy and hardware versions, and determining whether problems originate in perception, planning, control, or execution. Random access alone cannot provide this type of cross-episode aggregation and attribution. Traditional data warehouse full-table scans are also unsuitable for all multimodal sample access.</p>
<p>Lance organizes states, actions, features, embeddings, and media location information by episode and timeline while preserving random-access paths for training and review. Doris performs conditional filtering, vector retrieval, and cross-episode aggregation over the supported fields. With this division of responsibilities, the same robot data can support model training, unified analysis, and review.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="42-from-failed-tasks-to-a-closed-training-data-loop">4.2 From failed tasks to a closed training-data loop<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#42-from-failed-tasks-to-a-closed-training-data-loop" class="hash-link" aria-label="4.2 From failed tasks to a closed training-data loop &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="4.2 From failed tasks to a closed training-data loop &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>For failures involving robot arms attempting to grasp transparent or reflective objects, teams can use the following workflow:</p>
<ol>
<li>Data from multiple cameras, joint states, action trajectories, instructions, policy versions, and task results enters Lance by episode.</li>
<li>An upstream model generates visual or trajectory embeddings and creates vector indexes in Lance.</li>
<li>Doris first performs pre-filtering by robot model, task type, policy version, and <code>success = false</code>.</li>
<li>Vector search finds images or action segments similar to the target failure pattern.</li>
<li>Doris aggregates failure reasons, retry counts, task duration, hardware versions, and policy versions to determine whether the issue is related to perception, planning, control, or hardware.</li>
<li>High-value episodes are sent for review, relabeling, and training. The corrected model is then subjected to regression validation against the same dataset.</li>
</ol>
<p><img decoding="async" loading="lazy" alt="Robot Episode analysis workflow" src="https://cdnd.selectdb.com/assets/shared/4cd9dbac14be1f53473cff0a59a668e8.jpg" width="1200" height="630" class="img_ev3q"></p>
<p><strong>Figure 3. Embodied-intelligence episode analysis: from multi-frequency sensors to a closed training loop</strong></p>
<p>This workflow also works well for agentic data processing. An agent can use SQL to define the task scope, invoke vector search to locate similar failures, and generate distribution statistics and a list of candidate episodes. Each step retains its filter conditions, SQL, and data versions. Reviewers can inspect how the results were produced instead of relying on a model to search file directories or a vector database without a traceable procedure.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="43-example-search-for-robot-failure-patterns">4.3 Example: Search for robot failure patterns<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#43-example-search-for-robot-failure-patterns" class="hash-link" aria-label="4.3 Example: Search for robot failure patterns &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="4.3 Example: Search for robot failure patterns &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>The upstream system generates <code>query_vector</code> with the same embedding model used for <code>frame_embedding</code>. For example, it can pass a reference image, a representative video frame, or an action trajectory to the model and then provide the resulting floating-point array to <code>vector_search()</code>. The query vector&apos;s dimensions, numeric type, and normalization method must match the vector column in the dataset and the settings used when the index was created. The <code>[-0.04, 0.27, 0.18, ...]</code> value in this example only demonstrates the parameter format.</p>
<div class="language-SQL language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">SELECT</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    episode_id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    robot_model</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    policy_version</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    task_type</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    failure_reason</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    retry_count</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    _distance</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> vector_search</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;table&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;lance_ai.robotics.task_episodes&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;column&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;frame_embedding&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;query_vector&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;[-0.04, 0.27, 0.18, ...]&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;top_k&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;300&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;metric&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;cosine&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;filter&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;task_type = &apos;pick&apos; AND success = false&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;use_index&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;true&quot;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">BY</span><span class="token plain"> _distance </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">ASC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> episode_id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p>The results can then be aggregated by <code>policy_version</code>, <code>robot_model</code>, or <code>failure_reason</code>. The query can instead return <code>episode_id</code> and media location fields, allowing an application to use the Lance SDK to open the corresponding video frames, point clouds, or other Blob content for review.</p>
<blockquote>
<p>Availability: Lance Catalog support is in the Doris 4.2 release branch and is scheduled for public release at the end of September. The SQL below shows the planned public syntax.</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="5-how-to-use-lance-catalog-in-apache-doris">5. How to use Lance Catalog in Apache Doris<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#5-how-to-use-lance-catalog-in-apache-doris" class="hash-link" aria-label="5. How to use Lance Catalog in Apache Doris &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="5. How to use Lance Catalog in Apache Doris &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="51-connect-to-a-lance-dataset-in-object-storage">5.1 Connect to a Lance dataset in object storage<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#51-connect-to-a-lance-dataset-in-object-storage" class="hash-link" aria-label="5.1 Connect to a Lance dataset in object storage &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="5.1 Connect to a Lance dataset in object storage &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>The following example uses S3-compatible object storage. In production environments, supply access keys through secure credential management rather than writing them directly into shared scripts.</p>
<div class="language-SQL language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">CREATE</span><span class="token plain"> CATALOG lance_ai PROPERTIES </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;type&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;lance&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;lance.catalog.type&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;filesystem&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;warehouse&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;s3://&lt;bucket&gt;/physical-ai&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;s3.endpoint&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;https://&lt;object-storage-endpoint&gt;&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;s3.region&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;&lt;region&gt;&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;s3.access_key&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;&lt;access-key&gt;&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;s3.secret_key&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;&lt;secret-key&gt;&quot;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p>Doris also supports local file systems, OSS, and Lance REST Catalogs authenticated with Bearer Tokens, API Keys, or custom headers. Filesystem Catalog maps namespaces by directory: a first-level directory under the warehouse root corresponds to a Doris database, and a <code>.lance</code> directory corresponds to a table.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="52-discover-datasets-schemas-and-existing-indexes">5.2 Discover datasets, schemas, and existing indexes<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#52-discover-datasets-schemas-and-existing-indexes" class="hash-link" aria-label="5.2 Discover datasets, schemas, and existing indexes &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="5.2 Discover datasets, schemas, and existing indexes &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<div class="language-SQL language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">SHOW</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">DATABASES</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> lance_ai</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">SHOW</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">TABLES</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> lance_ai</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">autodrive</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">DESC</span><span class="token plain"> lance_ai</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">autodrive</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">scene_episodes</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">SHOW</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">INDEX</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> lance_ai</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">autodrive</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">scene_episodes</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p><code>SHOW INDEX</code> displays indexes that tools in the Lance ecosystem have already created.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="53-run-vector-queries-through-the-catalog">5.3 Run vector queries through the Catalog<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#53-run-vector-queries-through-the-catalog" class="hash-link" aria-label="5.3 Run vector queries through the Catalog &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="5.3 Run vector queries through the Catalog &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<div class="language-SQL language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">SELECT</span><span class="token plain"> episode_id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> event_time</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> model_version</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> _distance</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> vector_search</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;table&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;lance_ai.autodrive.scene_episodes&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;column&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;scene_embedding&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;query_vector&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;[0.12, -0.08, 0.31, ...]&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;top_k&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;200&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;metric&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;cosine&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;filter&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;road_type = &apos;urban&apos;&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;use_index&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;true&quot;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">BY</span><span class="token plain"> _distance </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">ASC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> episode_id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p>Catalog creation, dataset discovery, and vector search all remain within the same Catalog namespace. <code>filter</code> restricts candidates to urban-road scenarios before candidate generation, while <code>_distance</code> returns the similarity distance. The query vector&apos;s dimensions and distance metric must match those used by the upstream system to generate embeddings and create the Lance index.</p>
<p>Pre-filtering and post-filtering differ in when their conditions take part in candidate generation.</p>
<ul>
<li>A condition in the <code>filter</code> parameter of <code>vector_search()</code> is a pre-filter. Lance first filters the data and then performs vector retrieval within that subset. Therefore, <code>top_k</code> represents the Top-K results among the filtered data. This is suitable for conditions such as road type, time range, vehicle model, tenant, or data permissions that must constrain the search space.</li>
<li>A condition in <code>WHERE</code> outside the TVF is a post-filter. Vector search produces candidates first, and Doris then filters those candidates. This is suitable for expressions that Lance cannot currently push down or for scenarios that require semantic retrieval before business filtering. However, the final result may contain fewer than <code>top_k</code> entries, and the system will not automatically expand the retrieval range to fill the requested count.</li>
</ul>
<p>A query can combine both approaches. Put strong constraints that define the search scope in <code>filter</code>, place complex calculations or remaining conditions in the outer <code>WHERE</code>, and use <code>EXPLAIN</code> to confirm which conditions have been pushed down.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="54-use-explain-to-confirm-predicate-pushdown-and-index-use">5.4 Use EXPLAIN to confirm predicate pushdown and index use<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#54-use-explain-to-confirm-predicate-pushdown-and-index-use" class="hash-link" aria-label="5.4 Use EXPLAIN to confirm predicate pushdown and index use &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="5.4 Use EXPLAIN to confirm predicate pushdown and index use &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Before running a query, use <code>EXPLAIN</code> with the same <code>vector_search()</code> query. In the execution plan, <code>lancePushdownPredicate</code> indicates that pre-search conditions have been pushed down, while <code>lanceSearchIndexSegments</code> indicates that Lance index segments have been planned. Doris supplements new fragments not covered by the index with Flat Search so that the query includes all data in the current snapshot.</p>
<div class="language-SQL language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">EXPLAIN</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">SELECT</span><span class="token plain"> episode_id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> _distance</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> vector_search</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;table&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;lance_ai.autodrive.scene_episodes&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;column&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;scene_embedding&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;query_vector&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;[0.12, -0.08, 0.31, ...]&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;top_k&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;200&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;metric&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;cosine&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;filter&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;road_type = &apos;urban&apos;&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;use_index&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;true&quot;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">ORDER</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">BY</span><span class="token plain"> _distance </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">ASC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> episode_id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="55-use-a-tvf-for-temporary-reads-without-creating-a-catalog">5.5 Use a TVF for temporary reads without creating a Catalog<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#55-use-a-tvf-for-temporary-reads-without-creating-a-catalog" class="hash-link" aria-label="5.5 Use a TVF for temporary reads without creating a Catalog &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="5.5 Use a TVF for temporary reads without creating a Catalog &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>If you only need to analyze a specific Lance dataset temporarily and do not want to manage it through a Catalog, you can use the S3 TVF directly. The TVF is suitable for path-based reads and scalar analysis. If you need to reuse datasets, schemas, and vector indexes from a Catalog, use the Lance Catalog and <code>vector_search()</code> described above.</p>
<div class="language-SQL language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">SELECT</span><span class="token plain"> episode_id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> event_time</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> model_version</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">FROM</span><span class="token plain"> s3</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;uri&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;s3://&lt;bucket&gt;/physical-ai/autodrive/scene_episodes.lance&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;s3.endpoint&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;https://&lt;object-storage-endpoint&gt;&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;s3.region&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;&lt;region&gt;&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;s3.access_key&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;&lt;access-key&gt;&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;s3.secret_key&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;&lt;secret-key&gt;&quot;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;format&quot;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&quot;lance&quot;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">WHERE</span><span class="token plain"> event_time </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&gt;=</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;2026-08-01&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="6-conclusion-connect-ai-data-to-decisions">6. Conclusion: Connect AI data to decisions<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#6-conclusion-connect-ai-data-to-decisions" class="hash-link" aria-label="6. Conclusion: Connect AI data to decisions &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="6. Conclusion: Connect AI data to decisions &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Autonomous driving and embodied intelligence systems will continue to produce large amounts of data. The scarce resource is the set of high-value episodes that can explain model problems, cover long-tail scenarios, and inform the next iteration.</p>
<p>Apache Doris and Lance provide a direct path from multimodal assets to business decisions while retaining open formats. Lance organizes and indexes AI data and supports random access. Doris makes the data filterable, searchable, aggregatable, and understandable by both people and agents through unified SQL.</p>
<p>With this workflow, finding similar scenarios leads directly to questions about which version is affected, how often the issue occurred, whether it is a regression, and which training dataset should include it. Multimodal data can then participate in the closed loop for model iteration and business decision-making.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="61-doris-and-lance-development-roadmap">6.1 Doris and Lance development roadmap<a href="https://doris.apache.org/ko/blog/apache-doris-lance-physical-ai-analytics/#61-doris-and-lance-development-roadmap" class="hash-link" aria-label="6.1 Doris and Lance development roadmap &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="6.1 Doris and Lance development roadmap &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>The multimodal lakehouse capabilities for Iceberg, Paimon, Lance, and other formats have currently been merged into the Doris 4.2 release branch and are planned for official release with version 4.2 at the end of September.</p>
<p>Future work will focus on the performance, stability, and usability of Doris and Lance in the following areas:</p>
<ul>
<li>Establishing reproducible benchmarks across different data volumes, vector dimensions, Top-K values, filter selectivity, index coverage, concurrency levels, and cold or warm caches.</li>
<li>Measuring P50, P95, and P99 latency, throughput, recall, bytes scanned, object-storage requests, network traffic, peak CPU usage, and peak memory usage.</li>
<li>Continuing to optimize split balancing, large Top-K merges, high-dimensional vectors, lookups of wide result columns, object-storage reads, and cache paths.</li>
<li>Providing scenario-specific recommendations for parameters such as <code>nprobes</code>, <code>refine_factor</code>, <code>ef</code>, and <code>use_index</code>, and developing capacity-planning and troubleshooting guides.</li>
<li>Improving Lance table-management capabilities.</li>
<li>Supporting data export to Lance files.</li>
</ul></div>]]></content:encoded>
            <category>Tech Sharing</category>
        </item>
        <item>
            <title><![CDATA[Apache Doris 5.0 Preview(1): A Unified Multimodal Lakehouse for Real-Time Analytics]]></title>
            <link>https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/</link>
            <guid>https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/</guid>
            <pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Explore the Apache Doris 5.0 multimodal lakehouse preview, including open-format integration, Variant and vector analytics, Physical AI, and agent use cases.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Tech Sharing</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">Apache Doris 5.0 Preview(1): A Unified Multimodal Lakehouse for Real-Time Analytics</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">Apache Doris &#xB7; Mingyu Chen</span></span><time datetime="2026-09-04T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 9&#xC6D4; 4&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<p>Overview</p>
<p>This article covers the core changes planned for Apache Doris 5.0 for the multimodal lakehouse:</p>
<ol>
<li>
<p>Core concept: Extend unified search to the open lakehouse and use Doris to build a unified platform for multimodal data analytics.</p>
</li>
<li>
<p>Integration with open formats: Provide read and write integration with mainstream open formats such as Iceberg, Paimon, and Lance.</p>
</li>
<li>
<p>Multimodal data analytics: Adapt Doris to multimodal data types such as Variant, Vector, GEO, and Blob.</p>
</li>
<li>
<p>Use cases: Build a unified real-time multimodal data analytics platform for more AI scenarios, including real-time context for agents and embodied intelligence.</p>
</li>
</ol>
</blockquote>
<hr>
<p>For more than a decade, most data platforms have been organized around structured tables and SQL. Data is consolidated in a data warehouse, where stable batch processing and OLAP queries support reporting and business analysis.</p>
<p>AI changes the assumptions behind this architecture.</p>
<p>Enterprises now need to process business tables, JSON, logs, documents, images, audio, video, embeddings, and model outputs together. The set of data consumers has also grown beyond analysts to include applications and AI agents. A real-world request often combines structured filtering with full-text and vector retrieval, then joins the results with the latest business status, permissions, and historical metrics.</p>
<p>The traditional approach spreads these capabilities across separate systems. Object storage holds raw content, lakehouses hold table data and metadata, search engines handle full-text retrieval, vector databases provide semantic retrieval, OLAP systems perform metric analysis, and the application layer assembles the results. Each system solves a specific problem, but users are responsible for data consistency, version alignment, access governance, and result fusion across them.</p>
<p>Open formats are also expanding beyond structured data. AI workloads now include dynamic attributes, blobs, embeddings, and model results. Iceberg, Paimon, and Lance serve long-term analytical facts, real-time updated data, and AI datasets, respectively, so enterprises can select the appropriate format for each workload. In this article, a multimodal lakehouse refers to structured, semi-structured, and multimodal data stored collectively in these open formats.</p>
<p>For the multimodal lakehouse, Doris 5.0 will focus unification on query and execution instead of requiring users to move all data into one storage system. Data can remain in the open format best suited to it, while Doris provides unified search, analytics, and real-time serving.</p>
<p><img decoding="async" loading="lazy" alt="Apache Doris 5.0 unified query and compute architecture for the multimodal lakehouse" src="https://cdnd.selectdb.com/assets/shared/587dbd2068256c0425d19e7ca812157d.jpg" width="1200" height="630" class="img_ev3q"></p>
<p>Figure 1: Overall architecture of an open-format multimodal lakehouse. Iceberg, Paimon, Lance, and Fluss hold different types of open data assets. At the unified query and compute layer, Doris understands format semantics and connects hybrid search, cross-source joins, MPP OLAP, real-time serving, and access control in one execution pipeline.</p>
<blockquote>
<p>Availability: The Iceberg, Paimon, and Lance capabilities discussed here are in the Doris 4.2 release branch and are scheduled for public release at the end of September. The broader Doris 5.0 work remains a preview.</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="from-4x-to-50-extending-unified-search-to-the-open-lakehouse">From 4.x to 5.0: Extending unified search to the open lakehouse<a href="https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/#from-4x-to-50-extending-unified-search-to-the-open-lakehouse" class="hash-link" aria-label="From 4.x to 5.0: Extending unified search to the open lakehouse &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="From 4.x to 5.0: Extending unified search to the open lakehouse &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Apache Doris 4.x already provides high-performance unified search and analytics for structured, semi-structured, and vector data in internal tables. Users can combine SQL analytics, full-text search, vector search, and real-time updates in one system. For open lake formats such as Iceberg and Paimon, Doris has primarily supported queries and analysis of structured data.</p>
<p>Doris 5.0 will continue this work by extending capabilities already proven on internal tables to the open lakehouse. Variant data in Iceberg and Paimon will become part of a unified read and write pipeline. Paimon and Lance will gain native full-text and vector search. A new Fluss Catalog will support joint queries across real-time data in Fluss and historical data tiered to Paimon, which will further improve data freshness for analytics.</p>
<p><img decoding="async" loading="lazy" alt="Evolution of Doris capabilities from 4.x to 5.0" src="https://cdnd.selectdb.com/assets/shared/4dd13edec3c384121d671bfaa75a7c65.jpg" width="1200" height="630" class="img_ev3q"></p>
<p>Figure 2: Capability evolution from 4.x to 5.0. Doris 4.x provides unified search and OLAP on internal tables, along with structured SQL for Iceberg and Paimon. Doris 5.0 extends unified querying to the open lakehouse with Variant reads and writes, native vector search, and joint queries across real-time Fluss data and historical Paimon data.</p>
<p>Doris 5.0 will provide the following capabilities across open formats and the unified execution layer:</p>
<ul>
<li>Iceberg: Building on mature support for reads, writes, time travel, row-level updates, and table lifecycle management, Doris will add reads and writes for Iceberg V3 Variant data in both plain and shredded layouts.</li>
<li>Paimon: The Paimon Catalog will move from read-only access to full read and write support, including <code>INSERT</code>, <code>INSERT OVERWRITE</code>, <code>UPDATE</code>, <code>DELETE</code>, <code>MERGE</code>, DDL, and reads and writes for Variant, full-text indexes, and vector indexes. It will provide a unified entry point for real-time lakehouses and evolving multimodal data.</li>
<li>Lance: Doris will introduce native read and retrieval capabilities for multimodal AI, including Catalog support, parallel scans, column pruning, predicate pushdown, vector and full-text search, and vector index management.</li>
<li>Fluss: A new Fluss Catalog will support reads from log tables and primary-key tables. Through Union Read, it will jointly query real-time incremental data in Fluss and historical data tiered to Paimon.</li>
<li>Unified Doris execution: Doris will connect internal tables, open lake tables, full-text and vector retrieval, cross-source joins, aggregations, window calculations, and permission filtering in one SQL pipeline.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="from-multiple-systems-to-a-unified-platform">From multiple systems to a unified platform<a href="https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/#from-multiple-systems-to-a-unified-platform" class="hash-link" aria-label="From multiple systems to a unified platform &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="From multiple systems to a unified platform &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>The difficulty of assembling multiple systems goes beyond the number of systems involved. The same business entity may have different update times, versions, and permission boundaries in each system. A product that has been delisted, a device currently under maintenance, or a document that has been withdrawn may still appear in a stale vector index and be passed to an agent.</p>
<p>Placing unification at the query and execution layer makes the division of responsibilities clearer. Open formats continue to store long-term data and multimodal assets. Doris internal tables hold real-time business facts that require high concurrency and low latency. The Doris MPP engine performs retrieval, filtering, joins, and analytics in one query, so applications no longer need to move and assemble results across multiple systems. The same layer evaluates business state and applies permission filters for each entity, preventing stale candidates from bypassing these checks and reaching an agent.</p>
<p><img decoding="async" loading="lazy" alt="Evolution from a traditional multi-system architecture to unified execution with Apache Doris" src="https://cdnd.selectdb.com/assets/shared/3ec9ea36ad34fe9149962312b258d87d.jpg" width="1200" height="630" class="img_ev3q"></p>
<p>Figure 3: Evolution of the multimodal lakehouse data architecture. The architecture moves from traditional multi-system assembly to unified execution with Doris. Data remains in the appropriate open formats, while Doris unifies querying, computing, and serving.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="olap-from-retrieving-candidates-to-determining-business-outcomes">OLAP: From retrieving candidates to determining business outcomes<a href="https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/#olap-from-retrieving-candidates-to-determining-business-outcomes" class="hash-link" aria-label="OLAP: From retrieving candidates to determining business outcomes &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="OLAP: From retrieving candidates to determining business outcomes &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Vector or full-text search discovers candidates. Answering the business question usually requires joins, aggregations, window calculations, and multidimensional ranking as well.</p>
<p>For example, image-based product search cannot return products based only on visual similarity. It must also account for inventory, regional availability, price, conversion rate, and return rate. Equipment fault diagnosis cannot stop at finding similar logs. It must compare models, firmware versions, sensor metrics, and repair outcomes.</p>
<p>Whether candidates come from Doris internal tables or open lake tables, Doris can pass search results directly into its MPP OLAP execution pipeline. This allows the query to turn a &quot;similar&quot; result into a business conclusion that is currently valid, complies with the relevant rules, and is worth acting on.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="variant-full-text-and-vector-combining-different-forms-of-evidence-in-one-sql-query">Variant, full text, and vector: Combining different forms of evidence in one SQL query<a href="https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/#variant-full-text-and-vector-combining-different-forms-of-evidence-in-one-sql-query" class="hash-link" aria-label="Variant, full text, and vector: Combining different forms of evidence in one SQL query &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Variant, full text, and vector: Combining different forms of evidence in one SQL query &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Model-generated data rarely fits a stable wide-table schema. OCR results, captions, labels, tool-call parameters, and evaluation results change as model versions evolve. Variant provides a flexible way to store semi-structured data. Full-text search supports precise keyword and rule matching, while vector search broadens semantic recall. Structured conditions constrain time, status, permissions, and business scope.</p>
<p>Doris 5.0 will make Variant data, full-text indexes, and vector indexes in open lake tables available within the same SQL query. Users will not need to copy multimodal data into additional indexing systems solely to make it searchable.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="physical-ai-from-a-single-record-to-a-complete-episode">Physical AI: From a single record to a complete episode<a href="https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/#physical-ai-from-a-single-record-to-a-complete-episode" class="hash-link" aria-label="Physical AI: From a single record to a complete episode &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Physical AI: From a single record to a complete episode &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Data generated by autonomous driving systems, robots, and industrial equipment records a continuous process of observation, decision, action, and feedback rather than a collection of static documents. The smallest unit of analysis is therefore no longer an image. It is an Episode that contains time, space, device state, model version, and business outcome.</p>
<p>An Episode involving a robotic arm&apos;s failed grasp might contain RGB-D images, 3D poses, joint and torque data, planned trajectories, control commands, model outputs, device logs, and the final sorting result. Images describe the environment, trajectories describe the action, sensor data records the execution process, and the business outcome shows whether the task succeeded.</p>
<p>Open formats allow teams to retain this data over the long term, evolve it, and share it among different tools. Doris organizes these forms of evidence by Episode into an interactive query. The query first filters by time, device, and status, then retrieves similar situations through full-text and vector search, and finally joins model versions with business outcomes to compare failure rates, retry rates, and task duration.</p>
<p><img decoding="async" loading="lazy" alt="Closed-loop Physical AI Episode analysis" src="https://cdnd.selectdb.com/assets/shared/5c87054fd05edd259b81abfc0cda6739.jpg" width="1200" height="630" class="img_ev3q"></p>
<p>Figure 4: Closed-loop Physical AI Episode analysis. Doris organizes multisensor evidence, model context, and business outcomes into a reusable data feedback loop.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="agentic-ai-using-real-time-analytics-to-connect-models-with-business-context">Agentic AI: Using real-time analytics to connect models with business context<a href="https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/#agentic-ai-using-real-time-analytics-to-connect-models-with-business-context" class="hash-link" aria-label="Agentic AI: Using real-time analytics to connect models with business context &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Agentic AI: Using real-time analytics to connect models with business context &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Large language models can understand general knowledge, but they do not inherently know the enterprise&apos;s current state. They cannot know whether an order has been canceled, whether inventory is sufficient, whether a device is online, whether a customer still has permission, or whether a particular anomaly is currently surging without access to current enterprise data.</p>
<p>The challenge for an agent is therefore broader than generating SQL. It needs a continuous supply of fresh, trustworthy, explainable, and permission-compliant data context.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="real-time-writes-bringing-business-changes-directly-into-the-open-lakehouse">Real-time writes: Bringing business changes directly into the open lakehouse<a href="https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/#real-time-writes-bringing-business-changes-directly-into-the-open-lakehouse" class="hash-link" aria-label="Real-time writes: Bringing business changes directly into the open lakehouse &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Real-time writes: Bringing business changes directly into the open lakehouse &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Doris integration with Iceberg has already progressed from querying a data source to writing efficiently to an open data foundation. <code>INSERT</code>, <code>INSERT OVERWRITE</code>, CTAS, and row-level updates are already available. Doris 5.0 will bring the same write capabilities to Paimon and add Variant writes for both Iceberg and Paimon.</p>
<p>Users will be able to use unified SQL to write structured and Variant data directly to open tables. They will not need to write the data to Doris internal tables first or build another synchronization pipeline. Real-time business events, tool-call parameters, and continuously changing model results can be stored directly as open data assets.</p>
<p>Within the execution pipeline, Doris BEs generate data files through distributed parallel execution. The FE coordinates snapshots and atomic commits, and it handles idempotent retries and failure cleanup. Doris manages efficient writes, commit consistency, and schema evolution through a common implementation, so applications do not need to assemble open-table transactions themselves.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="real-time-analytics-building-agent-context-from-the-latest-open-data">Real-time analytics: Building agent context from the latest open data<a href="https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/#real-time-analytics-building-agent-context-from-the-latest-open-data" class="hash-link" aria-label="Real-time analytics: Building agent context from the latest open data &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Real-time analytics: Building agent context from the latest open data &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Orders, device states, behavioral events, and model-derived results written to Iceberg or Paimon can be shared among different compute engines. Doris queries the latest data directly, combines it with real-time business facts in internal tables, and applies cross-table joins and permission filtering to construct fresh, verifiable business context for agents.</p>
<p>For event streams with stricter freshness requirements, the new Fluss Catalog uses Union Read to combine real-time increments in Fluss with historical data tiered to Paimon and queries them as a single table. The resulting agent context includes both the complete history and changes that have just occurred.</p>
<p><img decoding="async" loading="lazy" alt="Real-time feedback loop for Agentic AI" src="https://cdnd.selectdb.com/assets/shared/47b40c4da5f6727fcc520cec9e8c1646.jpg" width="1200" height="630" class="img_ev3q"></p>
<p>Figure 5: A real-time Agentic AI feedback loop using open formats selected according to workload requirements. Doris provides read, write, and Variant capabilities for Iceberg or Paimon selected by the user, along with read and multimodal search capabilities for Lance. It then constructs agent context through unified SQL and MPP OLAP.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="multimodal-lakehouse-use-cases-with-doris">Multimodal lakehouse use cases with Doris<a href="https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/#multimodal-lakehouse-use-cases-with-doris" class="hash-link" aria-label="Multimodal lakehouse use cases with Doris &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Multimodal lakehouse use cases with Doris &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="scenario-1-real-time-decision-making-for-customer-service-agents">Scenario 1: Real-time decision-making for customer service agents<a href="https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/#scenario-1-real-time-decision-making-for-customer-service-agents" class="hash-link" aria-label="Scenario 1: Real-time decision-making for customer service agents &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Scenario 1: Real-time decision-making for customer service agents &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Knowledge documents, product images, and samples of similar faults are stored in Lance. Orders, support tickets, and historical service data are stored in Iceberg and Paimon. The latest inventory, warranty, and customer status data is loaded into Doris internal tables.</p>
<p>After an agent receives a customer question, Doris performs semantic retrieval, keyword matching, permission and status filtering, then joins the results with repair success rates and inventory data. The result is more than &quot;the most similar document.&quot; It is a resolution that the current customer can act on.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="scenario-2-selecting-high-value-episodes-for-physical-ai">Scenario 2: Selecting high-value Episodes for Physical AI<a href="https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/#scenario-2-selecting-high-value-episodes-for-physical-ai" class="hash-link" aria-label="Scenario 2: Selecting high-value Episodes for Physical AI &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Scenario 2: Selecting high-value Episodes for Physical AI &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Autonomous driving or robotics teams store video, point clouds, and embeddings in Lance. They write continuously changing model outputs and task results to Paimon as Variant data, while retaining historical evaluation results in Iceberg. These teams need to answer a question beyond &quot;Which Episodes are similar?&quot; They need to know, &quot;Which Episodes are worth investing in for annotation, training, and review?&quot;</p>
<p>After the query pipeline described above filters the Episodes, high-confidence anomalies enter training and regression datasets. Episodes with inconsistent evidence go to manual review. Failure and intervention rates aggregated by model version then show whether a new strategy has improved a specific scenario.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="scenario-3-from-similar-defects-to-root-cause-analysis-in-industrial-quality-inspection">Scenario 3: From similar defects to root-cause analysis in industrial quality inspection<a href="https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/#scenario-3-from-similar-defects-to-root-cause-analysis-in-industrial-quality-inspection" class="hash-link" aria-label="Scenario 3: From similar defects to root-cause analysis in industrial quality inspection &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Scenario 3: From similar defects to root-cause analysis in industrial quality inspection &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>A quality engineer uploads an image of a defect. Doris retrieves visually similar samples from Lance, matches defect descriptions in Variant and full-text fields, and joins the results with continuously updated equipment events in Paimon and with batch, process, and repair history in Iceberg.</p>
<p>The system then determines whether defects are occurring in clusters, which equipment and batches are affected, how accurately different model versions identify the defect, and whether yields recover in subsequent batches. This expands a similar-image search into a complete closed-loop quality analysis.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion-keep-data-in-open-formats-and-use-doris-for-search-and-analytics">Conclusion: Keep data in open formats and use Doris for search and analytics<a href="https://doris.apache.org/ko/blog/apache-doris-5-multimodal-lakehouse-preview/#conclusion-keep-data-in-open-formats-and-use-doris-for-search-and-analytics" class="hash-link" aria-label="Conclusion: Keep data in open formats and use Doris for search and analytics &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Conclusion: Keep data in open formats and use Doris for search and analytics &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Doris has one primary direction for the multimodal lakehouse: extend the unified search and real-time analytics capabilities already proven on internal tables to data in Iceberg, Paimon, Lance, and Fluss. Data can remain in open formats for search and analytics. Structured data, Variant data, full-text data, and vectors do not need to reside in separate systems. Doris will provide the unified execution and serving layer above this data:</p>
<ul>
<li>Use unified SQL to access Doris internal tables and multiple open formats.</li>
<li>Use Variant, full-text search, vector search, and structured filtering to query different forms of data.</li>
<li>Use MPP OLAP to turn retrieved results into business metrics and decisions.</li>
<li>Use real-time writes to supply the latest business state that agents otherwise lack.</li>
<li>Use unified permission filtering so applications and agents see only the data they are authorized to access.</li>
</ul>
<p>A series of articles about Doris 5.0 will examine these capabilities for open formats such as Iceberg, Paimon, Lance, and Fluss. The articles will cover their technical principles, performance benchmarks, and representative implementation scenarios.</p>
<p>The multimodal lakehouse capabilities for Iceberg, Paimon, and Lance have been merged into the Doris 4.2 release branch and are scheduled for official release with version 4.2 at the end of September. Additional capabilities, including Fluss support, have also entered the Doris main branch and are planned for release with Doris 5.0 at the end of the year.</p></div>]]></content:encoded>
            <category>Tech Sharing</category>
        </item>
        <item>
            <title><![CDATA[dbt-for-apache-doris 1.1.0 Released: Five Business Demos to Get Started with Doris Data Engineering]]></title>
            <link>https://doris.apache.org/ko/blog/dbt-for-apache-doris-1.1.0-five-demos/</link>
            <guid>https://doris.apache.org/ko/blog/dbt-for-apache-doris-1.1.0-five-demos/</guid>
            <pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[dbt-for-apache-doris 1.1.0 targets dbt Core 1.12, manages Apache Doris asynchronous materialized views through the standard dbt materialized_view, and covers Table, View, Incremental, Snapshot, Seed, and Data Test workflows. Five business demos show how dbt and Apache Doris handle daily order summaries, late-arriving orders, and more.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Tech Sharing</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">dbt-for-apache-doris 1.1.0 Released: Five Business Demos to Get Started with Doris Data Engineering</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">Junwei Chen</span></span><time datetime="2026-09-01T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 9&#xC6D4; 1&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><p><a href="https://github.com/velodb/dbt-for-apache-doris" target="_blank" rel="noopener noreferrer">dbt-for-apache-doris</a> 1.1.0 was released on August 12, 2026. It targets dbt Core 1.12, manages Apache Doris asynchronous materialized views through the standard dbt <code>materialized_view</code> materialization, and covers the everyday workflows: Table, View, Incremental, Snapshot, Seed, and Data Test.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">python -m pip install &quot;dbt-for-apache-doris==1.1.0&quot;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<p>The rest of this post covers what each of the two systems is responsible for, what the adapter supports today, and five demos that run a full pipeline in Doris.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="1-dbt-doris-and-what-110-adds">1. dbt, Doris, and what 1.1.0 adds<a href="https://doris.apache.org/ko/blog/dbt-for-apache-doris-1.1.0-five-demos/#1-dbt-doris-and-what-110-adds" class="hash-link" aria-label="1. dbt, Doris, and what 1.1.0 adds &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1. dbt, Doris, and what 1.1.0 adds &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="11-what-is-dbt">1.1 What is dbt<a href="https://doris.apache.org/ko/blog/dbt-for-apache-doris-1.1.0-five-demos/#11-what-is-dbt" class="hash-link" aria-label="1.1 What is dbt &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1.1 What is dbt &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>dbt (data build tool) is an open-source data transformation framework that handles the T of ELT inside a data warehouse. Every model is a SQL <code>SELECT</code> statement, and models reference each other with <code>ref()</code>. dbt compiles them into the target database&apos;s table creation and write statements, runs them in dependency order, and materializes each one as a table, view, incremental table, or snapshot according to its configuration.</p>
<p>It exists because the transformation layer spent years without much engineering discipline:</p>
<ul>
<li>SQL is scattered across schedulers, repos, and personal machines. Dependencies are maintained by hand, and nobody can say for certain what a change will break.</li>
<li>Nothing is tested automatically, so a wrong metric usually surfaces when someone in the business questions a number on a report.</li>
<li>There is no version control, no code review, and no separation between development and production, which makes changes hard to trace afterwards.</li>
<li>The same boilerplate for creating tables, writing incrementally, and keeping history gets rewritten in every project.</li>
</ul>
<p>dbt&apos;s answer is models as code, a dependency graph derived from <code>ref()</code>, declarative Data Tests, built-in materializations (Table, View, Incremental, Snapshot), generated documentation and lineage, and a package ecosystem of Jinja macros such as <code>dbt_utils</code>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="12-what-dbt-and-doris-solve-together">1.2 What dbt and Doris solve together<a href="https://doris.apache.org/ko/blog/dbt-for-apache-doris-1.1.0-five-demos/#12-what-dbt-and-doris-solve-together" class="hash-link" aria-label="1.2 What dbt and Doris solve together &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1.2 What dbt and Doris solve together &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>dbt does not compute anything itself. Every transformation is pushed down to the target database, so that database sets the ceiling for the project. Apache Doris is an MPP real-time analytical database that speaks the MySQL protocol and runs aggregations, multi-table JOINs, and window functions in place. <code>dbt-for-apache-doris</code> connects the two: dbt organizes, orchestrates, and validates the transformation logic; Doris stores the data and executes the SQL.</p>
<p>Putting them together settles a few things that data teams otherwise handle by convention. Table conventions become part of the code, since Doris Key models, partitions, buckets, and table properties are declared in the model&apos;s <code>config()</code> and go through version control and code review with everything else, rather than living in someone&apos;s memory. Late-arriving data gets a defined path too: a write to a Doris Unique Key table is an Upsert, and dbt Incremental <code>merge</code> sits directly on that semantic, so replaying the same batch produces the same table and a failed job can simply be run again.</p>
<p>Pre-aggregation stops being a separate system. Doris asynchronous materialized views join the dbt dependency graph through the standard <code>materialized_view</code> materialization, with build and refresh strategy in the model configuration, so they change and get tested alongside the models they read from. The computation never leaves Doris. dbt only ships SQL, so no second engine is needed to move data around. Quality checks run in the same place: Data Tests, Unit Tests, and Model Contracts all execute against Doris at build time, which is a better moment to catch a broken metric than the morning after a report goes out.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="13-adapter-feature-support">1.3 Adapter feature support<a href="https://doris.apache.org/ko/blog/dbt-for-apache-doris-1.1.0-five-demos/#13-adapter-feature-support" class="hash-link" aria-label="1.3 Adapter feature support &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1.3 Adapter feature support &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<ol>
<li>
<p><strong>Materializations</strong></p>













































<table><thead><tr><th>Capability</th><th>Status</th><th>Current scope and boundaries</th></tr></thead><tbody><tr><td>Table</td><td>&#x2705;</td><td>Duplicate Key CTAS; configurable HASH bucketing and bucket count, RANGE / LIST partitioning, table properties, Contracts, docs, Grants, and Hooks. Unique Key tables are created by Incremental <code>merge</code></td></tr><tr><td>View</td><td>&#x2705;</td><td>Standard lifecycle, Contracts, docs, Grants, and Hooks; switching relation types is not zero-downtime</td></tr><tr><td>Incremental</td><td>&#x2705;</td><td>Four strategies, <code>append</code>, <code>merge</code>, <code>insert_overwrite</code>, and <code>microbatch</code>, plus every <code>on_schema_change</code> mode (strategy details in the next table)</td></tr><tr><td>Snapshot</td><td>&#x2705;</td><td><code>check</code> / <code>timestamp</code> strategies, hard-delete handling, schema evolution, atomic replacement and recovery; jobs targeting the same relation must be serialized by the scheduler</td></tr><tr><td>Materialized view</td><td>&#x2705;</td><td>Standard dbt <code>materialized_view</code>, implemented as a Doris Async MV; covers the build / refresh lifecycle, task waiting, configuration changes, atomic replacement and recovery; dbt jobs targeting the same relation must be serialized</td></tr><tr><td>Seed</td><td>&#x2705;</td><td>CSV loading, type inference, <code>column_types</code>, and <code>ref()</code></td></tr><tr><td>Ephemeral</td><td>&#x2705;</td><td>Compiled and inlined by dbt Core</td></tr></tbody></table>
</li>
<li>
<p><strong>Incremental strategies and Doris target tables</strong>. When no strategy is specified explicitly, models configured with a <code>unique_key</code> use <code>merge</code> and all others use <code>append</code>.</p>






























<table><thead><tr><th>Strategy</th><th>Doris target table</th><th>Behavior</th></tr></thead><tbody><tr><td><code>append</code></td><td>Duplicate Key table</td><td>Appends rows with <code>INSERT INTO</code></td></tr><tr><td><code>merge</code></td><td>Unique Key table (MoW or MoR)</td><td>Full-row <code>INSERT INTO</code> Upsert based on Unique Key semantics; requires <code>unique_key</code>, does not generate <code>MERGE INTO</code></td></tr><tr><td><code>insert_overwrite</code></td><td>Any writable Doris table</td><td><code>INSERT OVERWRITE</code> of the whole table, specified partitions, or dynamic partitions; does not accept <code>unique_key</code></td></tr><tr><td><code>microbatch</code></td><td>Duplicate Key table with exact RANGE partitions</td><td>Each dbt time window overwrites one named partition; supports hour / day / month / year windows, and batches run serially</td></tr></tbody></table>
</li>
<li>
<p><strong>dbt engineering capabilities</strong></p>























































<table><thead><tr><th>Capability</th><th>Status</th><th>Current scope and boundaries</th></tr></thead><tbody><tr><td>Sources and freshness</td><td>&#x2705;</td><td><code>loaded_at_field</code>, filter, and <code>loaded_at_query</code>; cross-database access is implemented as database-as-schema, not through an External Catalog</td></tr><tr><td>Data Test</td><td>&#x2705;</td><td>Singular, Generic, and Ephemeral tests, plus <code>store_failures</code></td></tr><tr><td>Unit Test</td><td>&#x2705;</td><td>Inline and CSV fixtures, case-insensitive column names, invalid-input validation, reserved-word quoting, and data type fixtures adapted to Doris</td></tr><tr><td>Model Contract</td><td>&#x2705;</td><td>Column name and type constraints for Table, View, and Incremental; not mapped to database primary keys or NOT NULL constraints</td></tr><tr><td>Persisted docs</td><td>&#x2705;</td><td>Table / column comments for Table, View, Incremental, Snapshot, Seed, and Async MV; updating a View comment, or a comment that contains both kinds of quotes, may require a rebuild or full refresh</td></tr><tr><td>Grants</td><td>&#x2705;</td><td>Reconciles Doris table-level privileges for Table, View, Incremental, Seed, Snapshot, and Async MV, supporting <code>user</code> and <code>user@host</code> grantees; role grantees are not handled</td></tr><tr><td>Hooks</td><td>&#x2705;</td><td>pre-hook and post-hook for every materialization; Doris does not provide transactional rollback for hook side effects</td></tr><tr><td>Metadata and dbt docs catalog</td><td>&#x2705;</td><td>Relation discovery and documentation catalog for Doris databases, tables, views, columns, comments, and Async MVs</td></tr><tr><td>Cross-database Sources</td><td>&#x2705;</td><td>References Sources in other Doris databases, including definitions that only declare a database; three-part External Catalog names are not supported</td></tr></tbody></table>
</li>
</ol>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="14-whats-new-in-110">1.4 What&apos;s new in 1.1.0<a href="https://doris.apache.org/ko/blog/dbt-for-apache-doris-1.1.0-five-demos/#14-whats-new-in-110" class="hash-link" aria-label="1.4 What&apos;s new in 1.1.0 &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="1.4 What&apos;s new in 1.1.0 &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>1.1.0 is the first release of <code>dbt-for-apache-doris</code> from its own repository, and the first published to PyPI. It targets dbt Core 1.12 on Python 3.10 and above, manages Doris Async Materialized Views through the standard dbt <code>materialized_view</code> materialization, and ships with explicit version constraints and a stated support boundary.</p>
<p>A <code>materialized_view</code> model maps to a Doris Async MV, and the build mode, refresh strategy, and task waiting are all written in the model configuration:</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">{{ config</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    materialized</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;materialized_view&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    refresh_trigger</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;manual&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">    wait_for_refresh</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token boolean" style="color:hsl(35, 99%, 36%)">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> }}</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">select</span><span class="token plain"> order_date</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">sum</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">amount</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">as</span><span class="token plain"> sales</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">from</span><span class="token plain"> {{ ref</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">&apos;orders&apos;</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> }}</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">group</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">by</span><span class="token plain"> order_date</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="&#xD074;&#xB9BD;&#xBCF4;&#xB4DC;&#xC5D0; &#xCF54;&#xB4DC; &#xBCF5;&#xC0AC;" title="&#xBCF5;&#xC0AC;" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="2-five-demos">2. Five demos<a href="https://doris.apache.org/ko/blog/dbt-for-apache-doris-1.1.0-five-demos/#2-five-demos" class="hash-link" aria-label="2. Five demos &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2. Five demos &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Each demo starts from a business question:</p>















































<table><thead><tr><th>#</th><th>Demo</th><th>Business question</th><th>Transformation and result</th><th>Key capabilities</th></tr></thead><tbody><tr><td>01</td><td>Daily order summary</td><td>How many valid orders and how much revenue per day and per month?</td><td>Filter out cancelled, returned, and failed orders; produce a daily Table and a monthly Async MV</td><td>Source, Table, Data Test, partitioning and bucketing, Async MV</td></tr><tr><td>02</td><td>Customer geography analysis</td><td>Which states are customers, orders, and revenue concentrated in?</td><td>Read addresses and orders from two Doris databases; output state-level business metrics</td><td>Cross-database Source, View, <code>ref()</code>, Table</td></tr><tr><td>03</td><td>Ad data integration</td><td>How to unify Google, Meta, and TikTok data?</td><td>Load three kinds of CSV with Seeds, align fields, and deduplicate; output daily channel details</td><td>Seed, <code>dbt_utils</code>, <code>QUALIFY</code>, Data Test</td></tr><tr><td>04</td><td>Late-arriving orders</td><td>How to absorb late corrections and avoid duplicate orders?</td><td>Identify order versions and maintain the current state with Incremental <code>merge</code></td><td>Incremental, Unique Key, idempotency</td></tr><tr><td>05</td><td>Customer history tracking</td><td>How to keep the history of attribute changes and hard deletes?</td><td>Two Snapshot rounds produce SCD Type 2 history and a current customer dimension table</td><td>Snapshot, Hard Delete, <code>ref()</code>, Data Test</td></tr></tbody></table>
<blockquote>
<p>The demos are selected and adapted from the Snowflake Labs <a href="https://github.com/Snowflake-Labs/data-eng-bench" target="_blank" rel="noopener noreferrer"><code>data-eng-bench</code></a> scenarios (the original project is licensed under the Apache License 2.0). We rewrote the profiles, SQL, fixtures, verifiers, and notebooks for Apache Doris and <code>dbt-for-apache-doris</code>.</p>
<p>Demo repository: <a href="https://github.com/velodb/dbt-for-apache-doris/tree/main/examples" target="_blank" rel="noopener noreferrer">https://github.com/velodb/dbt-for-apache-doris/tree/main/examples</a></p>
</blockquote>
<p>Two of them are walked through below. For the other three, customer geography analysis, ad data integration, and customer history tracking, the <a href="https://github.com/velodb/dbt-for-apache-doris/tree/main/examples/doris-demos" target="_blank" rel="noopener noreferrer">Doris dbt demos README</a> has the business description, the model list, and the exact commands.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="21-demo-01-order-summary-and-asynchronous-materialized-views">2.1 Demo 01: Order summary and asynchronous materialized views<a href="https://doris.apache.org/ko/blog/dbt-for-apache-doris-1.1.0-five-demos/#21-demo-01-order-summary-and-asynchronous-materialized-views" class="hash-link" aria-label="2.1 Demo 01: Order summary and asynchronous materialized views &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2.1 Demo 01: Order summary and asynchronous materialized views &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>The demo starts from 6 orders in Doris, drops the <code>CANCELLED</code>, <code>RETURNED</code>, and <code>FAILED</code> ones, and builds <code>daily_order_summary</code>. Data Tests check that dates are unique and key columns are not null, and <code>monthly_order_summary_mv</code> then aggregates the daily table through <code>ref()</code>.</p>
<p><img decoding="async" loading="lazy" alt="Demo 01 transformation flow: on the dbt side, source(), Table, ref(), and materialized_view; the orders source is filtered into daily_order_summary, checked by Data Tests, and aggregated into monthly_order_summary_mv; on the Doris side, Duplicate Key, Range Partition, Hash Bucket, and Async MV" src="https://cdnd.selectdb.com/assets/shared/85d79f22e1996d42f084ea796ccb01a1.jpg" width="1731" height="909" class="img_ev3q"></p>
<p><em>Figure 1: The chain from raw orders to the monthly asynchronous materialized view. The top row is what dbt handles: model dependencies, materialization, and tests. The bottom row is what Doris provides for the table model and the materialized view.</em></p>
<p>Three orders survive the filter, for a monthly revenue of <code>220.20</code>. dbt owns the model dependencies (<code>source()</code> through <code>ref()</code>), the materializations, and the Data Tests. Doris decides how the two result tables are stored and how fast they answer:</p>

























<table><thead><tr><th>Doris capability</th><th>What it does here</th></tr></thead><tbody><tr><td>Duplicate Key model</td><td><code>daily_order_summary</code> is created with <code>order_date</code> as its sort key. Rows are stored as written, with no aggregation or merging. Date range queries use the prefix index, so daily report queries hit it directly. dbt <code>table</code> rebuilds the whole table with CTAS on every run, so the result is reproducible</td></tr><tr><td>RANGE partitioning (by <code>order_date</code>)</td><td>The model pre-creates the <code>p202608</code> partition and the catch-all <code>pmax</code> partition through <code>partition_by_init</code>. A monthly query scans one partition, and old data can be archived or dropped by month</td></tr><tr><td>HASH bucketing (by <code>order_date</code>)</td><td>Data is distributed across BE nodes by the bucket key and computed in parallel. The demo runs on a single node with 1 bucket; production raises the bucket count as data grows</td></tr><tr><td>Asynchronous materialized view (Async MV)</td><td><code>monthly_order_summary_mv</code> pre-aggregates on top of the daily table, so the monthly dashboard reads precomputed results and does not re-aggregate on every open. <code>build_mode=&apos;immediate&apos;</code> produces data as soon as the view is built, <code>refresh_method=&apos;auto&apos;</code> lets Doris choose between a full refresh and a partition-level one, and <code>refresh_trigger=&apos;manual&apos;</code> makes each dbt run trigger a refresh and wait for it; a scheduled refresh (<code>schedule</code>) or a refresh on base table commit (<code>commit</code>) works as well. The materialized view itself also takes Keys, bucketing, and table properties</td></tr></tbody></table>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="22-demo-04-incremental-updates-for-late-arriving-orders">2.2 Demo 04: Incremental updates for late-arriving orders<a href="https://doris.apache.org/ko/blog/dbt-for-apache-doris-1.1.0-five-demos/#22-demo-04-incremental-updates-for-late-arriving-orders" class="hash-link" aria-label="2.2 Demo 04: Incremental updates for late-arriving orders &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="2.2 Demo 04: Incremental updates for late-arriving orders &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>The demo writes orders 101, 102, and 103, then receives two late events: the amount of order 101 is corrected from <code>100.00</code> to <code>125.00</code>, and a new order 104 arrives.</p>
<p>Two steps absorb them:</p>
<ol>
<li><code>order_version_history</code> uses window functions to identify the current version of each order.</li>
<li><code>incremental_daily_sales</code> takes <code>order_id</code> as its business key and runs Incremental <code>merge</code> on top of the Upsert semantics of the Doris Unique Key model.</li>
</ol>
<p><img decoding="async" loading="lazy" alt="Demo 04 transformation flow: late events for orders 101 and 104 enter the order events table, order_version_history identifies order versions, incremental_daily_sales is updated by Incremental merge with unique_key = order_id and stays unchanged on re-run, and reconciliation models are checked by Data Tests; on the Doris side, window functions, Unique Key upsert, and Hash Bucket" src="https://cdnd.selectdb.com/assets/shared/8392180d4202d9e0b321ad5002d31e38.jpg" width="1728" height="910" class="img_ev3q"></p>
<p><em>Figure 2: Late events reach the source table, then version identification and Incremental <code>merge</code> update the current orders; a re-run with no new data leaves the result alone. The top row is what dbt handles, the bottom row is what Doris provides.</em></p>
<p>Run it again with no new data and nothing moves. <code>incremental_daily_sales</code> holds 4 orders, order 101 now at <code>125.00</code>, and revenue for August 1 in the downstream <code>daily_sales_summary</code> becomes <code>245.00</code>. The same project also builds data quality, arrival latency, and revenue reconciliation models. dbt&apos;s part is the incremental model definition, the <code>is_incremental()</code> filter, and the uniqueness test on <code>order_id</code>. The &quot;no duplicates, safe to re-run&quot; property comes from Doris:</p>





























<table><thead><tr><th>Doris capability</th><th>What it does here</th></tr></thead><tbody><tr><td>Unique Key model</td><td><code>incremental_daily_sales</code> is created with <code>order_id</code> as its Unique Key. A new version of an order overwrites the old one on write, so the table always holds exactly one row per order and the <code>unique</code> test passes. The adapter enables Merge-on-Write by default, so deduplication happens at write time and queries have nothing left to merge</td></tr><tr><td>Upsert on write (Incremental <code>merge</code>)</td><td>The adapter performs a full-row Upsert with a plain <code>INSERT INTO</code>, with no <code>MERGE INTO</code> and no delete-then-insert. The correction to order 101 and the new order 104 take the same write path, and re-running with no new data leaves the result unchanged, which is what makes backfills and retries safe</td></tr><tr><td>HASH bucketing (by <code>order_id</code>)</td><td>The bucket key matches the primary key, so every version of an order lands in the same tablet, and primary key deduplication and updates complete inside it without comparing across nodes</td></tr><tr><td>Window functions</td><td><code>order_version_history</code> uses <code>row_number()</code> and <code>lead()</code> inside Doris to mark the current version of each order and compute <code>valid_from</code> / <code>valid_to</code>. The version history is auditable, and no external program is involved</td></tr><tr><td>Online schema change</td><td>The model sets <code>on_schema_change=&apos;append_new_columns&apos;</code>. When an upstream model adds a column, the adapter syncs the table structure with <code>ALTER TABLE ... ADD COLUMN</code> and waits for the change to finish, so the incremental table never needs a rebuild</td></tr></tbody></table>
<p>All five demos run as JupyterLab notebooks, one step per cell, so you can stop at any cell and look at what Doris wrote. They live in the repository&apos;s <code>examples/</code> directory, with <a href="https://github.com/velodb/dbt-for-apache-doris/tree/main/examples/doris-demos" target="_blank" rel="noopener noreferrer"><code>examples/doris-demos</code></a> as the entry point; its README has the full run instructions.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="links">Links<a href="https://doris.apache.org/ko/blog/dbt-for-apache-doris-1.1.0-five-demos/#links" class="hash-link" aria-label="Links &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Links &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<ul>
<li>GitHub repository: <a href="https://github.com/velodb/dbt-for-apache-doris" target="_blank" rel="noopener noreferrer">https://github.com/velodb/dbt-for-apache-doris</a></li>
<li>1.1.0 release: <a href="https://github.com/velodb/dbt-for-apache-doris/releases/tag/v1.1.0" target="_blank" rel="noopener noreferrer">https://github.com/velodb/dbt-for-apache-doris/releases/tag/v1.1.0</a></li>
<li>PyPI: <a href="https://pypi.org/project/dbt-for-apache-doris/1.1.0/" target="_blank" rel="noopener noreferrer">https://pypi.org/project/dbt-for-apache-doris/1.1.0/</a></li>
<li>Demo entry point: <a href="https://github.com/velodb/dbt-for-apache-doris/tree/main/examples/doris-demos" target="_blank" rel="noopener noreferrer">https://github.com/velodb/dbt-for-apache-doris/tree/main/examples/doris-demos</a></li>
<li>Apache Doris all-in-one image: <a href="https://doris.apache.org/community/developer-guide/all-in-one-image" target="_blank" rel="noopener noreferrer">https://doris.apache.org/community/developer-guide/all-in-one-image</a></li>
</ul></div>]]></content:encoded>
            <category>Tech Sharing</category>
        </item>
        <item>
            <title><![CDATA[Dynamic JSON in Agent Workloads: Apache Doris vs ClickHouse, Elasticsearch, and OpenSearch]]></title>
            <link>https://doris.apache.org/ko/blog/dynamic-json-in-agent-workloads-apache-doris-clickhouse-elasticsearch-and-opensearch/</link>
            <guid>https://doris.apache.org/ko/blog/dynamic-json-in-agent-workloads-apache-doris-clickhouse-elasticsearch-and-opensearch/</guid>
            <pubDate>Thu, 27 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[AI agent logs create wide, fast-changing JSON payloads that are difficult to analyze with predictable latency. We compare how Apache Doris, ClickHouse, Elasticsearch, and OpenSearch perform in such scenario.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Tech Sharing</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">Dynamic JSON in Agent Workloads: Apache Doris vs ClickHouse, Elasticsearch, and OpenSearch</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">velodb.io &#xB7; Max Li</span></span><time datetime="2026-08-27T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 8&#xC6D4; 27&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<a class="blog-item-link" rel="noopener noreferrer" target="_blank" href="https://www.velodb.io/blog/dynamic-json-in-agent-workloads-apache-doris-clickhouse-elasticsearch-and-opensearch">AI agent logs create wide, fast-changing JSON payloads that are difficult to analyze with predictable latency. We compare how Apache Doris, ClickHouse, Elasticsearch, and OpenSearch perform in such scenario. <span style="color:var(--ifm-color-primary);display:inline-flex;align-items:center;gap:4px">see more <svg width="1rem" height="1rem" viewBox="0 0 18 18" fill="none"><path d="M14.8497 8.99993L14.8497 14.5349C14.8497 14.8332 14.6079 15.0749 14.3097 15.0749H3.68966C3.39142 15.0749 3.14966 14.8332 3.14966 14.5349V3.46493C3.14966 3.16669 3.39142 2.92493 3.68966 2.92493H8.53166" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.4746 2.92493H14.3096C14.6078 2.92493 14.8496 3.16669 14.8496 3.46493V6.29993" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.9944 3.82495L8.90322 8.91612" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span></a>
</blockquote></div>]]></content:encoded>
            <category>Tech Sharing</category>
        </item>
        <item>
            <title><![CDATA[PostgreSQL CDC to Apache Doris: Real-Time Sync with One SQL Statement]]></title>
            <link>https://doris.apache.org/ko/blog/postgresql-cdc-to-apache-doris-real-time-sync-with-one-sql-statement/</link>
            <guid>https://doris.apache.org/ko/blog/postgresql-cdc-to-apache-doris-real-time-sync-with-one-sql-statement/</guid>
            <pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Apache Doris offers native CDC for PostgreSQL, replacing separate CDC, Kafka, Flink, or Spark components with one built-in streaming job.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Tech Sharing</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">PostgreSQL CDC to Apache Doris: Real-Time Sync with One SQL Statement</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">velodb.io &#xB7; Dylan Wu</span></span><time datetime="2026-08-21T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 8&#xC6D4; 21&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<a class="blog-item-link" rel="noopener noreferrer" target="_blank" href="https://www.velodb.io/blog/postgresql-cdc-to-apache-doris-real-time-sync-with-one-sql-statement">Apache Doris offers native CDC for PostgreSQL, replacing separate CDC, Kafka, Flink, or Spark components with one built-in streaming job. <span style="color:var(--ifm-color-primary);display:inline-flex;align-items:center;gap:4px">see more <svg width="1rem" height="1rem" viewBox="0 0 18 18" fill="none"><path d="M14.8497 8.99993L14.8497 14.5349C14.8497 14.8332 14.6079 15.0749 14.3097 15.0749H3.68966C3.39142 15.0749 3.14966 14.8332 3.14966 14.5349V3.46493C3.14966 3.16669 3.39142 2.92493 3.68966 2.92493H8.53166" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.4746 2.92493H14.3096C14.6078 2.92493 14.8496 3.16669 14.8496 3.46493V6.29993" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.9944 3.82495L8.90322 8.91612" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span></a>
</blockquote></div>]]></content:encoded>
            <category>Tech Sharing</category>
        </item>
        <item>
            <title><![CDATA[From Spark to Apache Doris: How Kwai Made A/B Testing Metrics 145x Faster at Scale]]></title>
            <link>https://doris.apache.org/ko/blog/from-spark-to-apache-doris-how-kwai-made-a-b-testing-metrics-145x-faster-at-scale/</link>
            <guid>https://doris.apache.org/ko/blog/from-spark-to-apache-doris-how-kwai-made-a-b-testing-metrics-145x-faster-at-scale/</guid>
            <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Kwai migrated its company-wide A/B testing metrics pipeline from Spark to Apache Doris. The rebuild delivered 145x faster metrics computation and cut resource consumption by 72%.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Best Practice</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">From Spark to Apache Doris: How Kwai Made A/B Testing Metrics 145x Faster at Scale</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">Kwai &#xB7; Siwei Zeng</span></span><time datetime="2026-08-12T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 8&#xC6D4; 12&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<a class="blog-item-link" rel="noopener noreferrer" target="_blank" href="https://www.velodb.io/blog/from-spark-to-apache-doris-how-kwai-made-a-b-testing-metrics-145x-faster-at-scale">Kwai migrated its company-wide A/B testing metrics pipeline from Spark to Apache Doris. The rebuild delivered 145x faster metrics computation and cut resource consumption by 72%. <span style="color:var(--ifm-color-primary);display:inline-flex;align-items:center;gap:4px">see more <svg width="1rem" height="1rem" viewBox="0 0 18 18" fill="none"><path d="M14.8497 8.99993L14.8497 14.5349C14.8497 14.8332 14.6079 15.0749 14.3097 15.0749H3.68966C3.39142 15.0749 3.14966 14.8332 3.14966 14.5349V3.46493C3.14966 3.16669 3.39142 2.92493 3.68966 2.92493H8.53166" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.4746 2.92493H14.3096C14.6078 2.92493 14.8496 3.16669 14.8496 3.46493V6.29993" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.9944 3.82495L8.90322 8.91612" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span></a>
</blockquote></div>]]></content:encoded>
            <category>Best Practice</category>
        </item>
        <item>
            <title><![CDATA[Apache Doris Python UDF: Calling the Python Ecosystem from SQL for Agent-Era]]></title>
            <link>https://doris.apache.org/ko/blog/apache-doris-python-udf-calling-the-python-ecosystem-from-sql/</link>
            <guid>https://doris.apache.org/ko/blog/apache-doris-python-udf-calling-the-python-ecosystem-from-sql/</guid>
            <pubDate>Thu, 06 Aug 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Apache Doris adds Python UDF in 4.1.3. This enables teams to create and call Python functions directly in SQL, bringing Pandas, PyArrow, and the rest of the Python ecosystem into the Doris query path.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Tech Sharing</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">Apache Doris Python UDF: Calling the Python Ecosystem from SQL for Agent-Era</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">velodb.io &#xB7; Haopeng Li &amp; Zhenqi Lin</span></span><time datetime="2026-08-06T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 8&#xC6D4; 6&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<a class="blog-item-link" rel="noopener noreferrer" target="_blank" href="https://www.velodb.io/blog/apache-doris-python-udf-calling-the-python-from-sql-for-agent-era">Apache Doris adds Python UDF in 4.1.3. This enables teams to create and call Python functions directly in SQL, bringing Pandas, PyArrow, and the rest of the Python ecosystem into the Doris query path. <span style="color:var(--ifm-color-primary);display:inline-flex;align-items:center;gap:4px">see more <svg width="1rem" height="1rem" viewBox="0 0 18 18" fill="none"><path d="M14.8497 8.99993L14.8497 14.5349C14.8497 14.8332 14.6079 15.0749 14.3097 15.0749H3.68966C3.39142 15.0749 3.14966 14.8332 3.14966 14.5349V3.46493C3.14966 3.16669 3.39142 2.92493 3.68966 2.92493H8.53166" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.4746 2.92493H14.3096C14.6078 2.92493 14.8496 3.16669 14.8496 3.46493V6.29993" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.9944 3.82495L8.90322 8.91612" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span></a>
</blockquote></div>]]></content:encoded>
            <category>Tech Sharing</category>
        </item>
        <item>
            <title><![CDATA[How Meituan Consolidated Its Analytics Stack on Apache Doris]]></title>
            <link>https://doris.apache.org/ko/blog/how-meituan-consolidated-its-analytics-stack-on-apache-doris/</link>
            <guid>https://doris.apache.org/ko/blog/how-meituan-consolidated-its-analytics-stack-on-apache-doris/</guid>
            <pubDate>Fri, 31 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Meituan replaced a multi-engine analytics stack of Hadoop, Kylin, and Druid with a single Apache Doris platform spanning 300+ clusters and tens of PB of data.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Best Practice</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">How Meituan Consolidated Its Analytics Stack on Apache Doris</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">Apache Doris</span></span><time datetime="2026-07-31T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 7&#xC6D4; 31&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<a class="blog-item-link" rel="noopener noreferrer" target="_blank" href="https://www.velodb.io/blog/how-meituan-consolidated-its-analytics-stack-on-apache-doris">Meituan replaced a multi-engine analytics stack of Hadoop, Kylin, and Druid with a single Apache Doris platform spanning 300+ clusters and tens of PB of data. <span style="color:var(--ifm-color-primary);display:inline-flex;align-items:center;gap:4px">see more <svg width="1rem" height="1rem" viewBox="0 0 18 18" fill="none"><path d="M14.8497 8.99993L14.8497 14.5349C14.8497 14.8332 14.6079 15.0749 14.3097 15.0749H3.68966C3.39142 15.0749 3.14966 14.8332 3.14966 14.5349V3.46493C3.14966 3.16669 3.39142 2.92493 3.68966 2.92493H8.53166" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.4746 2.92493H14.3096C14.6078 2.92493 14.8496 3.16669 14.8496 3.46493V6.29993" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.9944 3.82495L8.90322 8.91612" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span></a>
</blockquote></div>]]></content:encoded>
            <category>Best Practice</category>
        </item>
        <item>
            <title><![CDATA[Meet D-Crew, the Apache Doris Mascot Family]]></title>
            <link>https://doris.apache.org/ko/blog/meet-d-crew-apache-doris-mascot-family/</link>
            <guid>https://doris.apache.org/ko/blog/meet-d-crew-apache-doris-mascot-family/</guid>
            <pubDate>Sun, 26 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Introducing D-Crew, the Apache Doris mascot family: Pip, Dori, and Flux represent query execution, the core engine, and connected data for real-time analytics.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Top News</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">Meet D-Crew, the Apache Doris Mascot Family</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">Apache Doris</span></span><time datetime="2026-07-26T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 7&#xC6D4; 26&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><p>Apache Doris is <strong>the fastest open source database project built for real-time analytics</strong>. People often first encounter Doris through architecture diagrams, SQL, performance benchmarks, and technical documentation. But beyond its technical capabilities, we also want Doris to have a more vivid and approachable identity, one that helps more people understand it, remember it, and connect with the community.</p>
<p>Today, we are excited to introduce three new friends of Apache Doris: the <strong>D-Crew</strong>.</p>
<p><img decoding="async" loading="lazy" alt="This image introduces D-Crew, the new Apache Doris mascot family. At the top, under &#x201C;From the Doris Logo,&#x201D; it shows the three geometric elements in the Apache Doris logo. Arrows point down to &#x201C;...To the D-Crew,&#x201D; where those elements become three lively mascots with expressive faces and limbs: Pip, Dori, and Flux, from left to right. The image clearly shows how the new mascots evolved from the logo." src="https://cdnd.selectdb.com/assets/shared/e2e68cbab6cfe15433f849f6da0d34ef.jpg" width="1672" height="941" class="img_ev3q"></p>
<p>D-Crew is the Apache Doris mascot family, made up of three members: Pip, Dori, and Flux. Each grew out of one of the three geometric elements in the Apache Doris logo. They are three distinct characters, but together they represent the capabilities that make Apache Doris powerful.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="meet-the-d-crew">Meet the D-Crew<a href="https://doris.apache.org/ko/blog/meet-d-crew-apache-doris-mascot-family/#meet-the-d-crew" class="hash-link" aria-label="Meet the D-Crew &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Meet the D-Crew &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>D-Crew offers a lighter, more visual way to get to know Doris, understand how it works, and follow the story of this evolving open source project.</p>
<p><img decoding="async" loading="lazy" alt="This image introduces the three members of D-Crew: Pip, Dori, and Flux. Pip is a purple triangle known as the query runner. Pip gets things moving by executing queries, running SQL, and starting real-time analytics, represented by Query, SQL, and Trigger. Dori is a blue capsule and the core engine. Dori keeps everything fast and reliable, powering high-concurrency workloads and complex analytics, represented by Performance, Reliability, and Compute. Flux is a green pen-shaped data explorer. Flux connects lakehouses, search, vectors, and open data formats to provide data for modern applications and agents, represented by Lakehouse, Search, and AI. Together, they turn real-time data into insights." src="https://cdnd.selectdb.com/assets/shared/3a0c5cf97a77e4096e76814b53f3badb.jpg" width="1448" height="1086" class="img_ev3q"></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="flux">Flux<a href="https://doris.apache.org/ko/blog/meet-d-crew-apache-doris-mascot-family/#flux" class="hash-link" aria-label="Flux &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Flux &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p><strong>Flux</strong> is the streamlined green character and D-Crew&apos;s data explorer.</p>
<p>Flux connects different data worlds, including <strong>lakehouses, search, vectors, open data formats, and more data modalities to come</strong>. Flux makes data discoverable, understandable, and easier to use in different ways. This reflects how Doris is bringing these data capabilities together to provide context and analytics for Agents.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="dori">Dori<a href="https://doris.apache.org/ko/blog/meet-d-crew-apache-doris-mascot-family/#dori" class="hash-link" aria-label="Dori &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Dori &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p><strong>Dori</strong> is the teal capsule and the character closest to the Doris core engine.</p>
<p>Dori is the dependable foundation. <strong>Low-latency queries, high-concurrency access, complex analytics, and multi-tenant workloads</strong> all rely on Dori&apos;s steady support behind the scenes. Dori&apos;s reliability represents the continued evolution of Doris as a powerful foundation for data analytics.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="pip">Pip<a href="https://doris.apache.org/ko/blog/meet-d-crew-apache-doris-mascot-family/#pip" class="hash-link" aria-label="Pip &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Pip &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p><strong>Pip</strong> is the purple triangle. It looks like a play button and the starting point of a query.</p>
<p>Starting queries, running SQL, and launching real-time analytics are all Pip&apos;s domain. Pip represents the interface between Doris and its users and applications. It starts with the <strong>standard SQL interface and extends to capabilities designed for AI Agents, including a semantic layer, CLI, MCP, and Skills</strong>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="explore-apache-doris-with-d-crew">Explore Apache Doris with D-Crew<a href="https://doris.apache.org/ko/blog/meet-d-crew-apache-doris-mascot-family/#explore-apache-doris-with-d-crew" class="hash-link" aria-label="Explore Apache Doris with D-Crew &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Explore Apache Doris with D-Crew &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>Pip, Dori, and Flux are more than three separate characters. Their different roles and the way they work together offer a more intuitive view of how Apache Doris supports a range of use cases.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="real-time-analytics"><strong>Real-time Analytics</strong><a href="https://doris.apache.org/ko/blog/meet-d-crew-apache-doris-mascot-family/#real-time-analytics" class="hash-link" aria-label="real-time-analytics &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="real-time-analytics &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>In a <strong>Real-time Analytics</strong> use case, Flux connects to real-time data, Dori handles high-concurrency and high-throughput data processing and storage, and Pip delivers low-latency query responses. Together, they create an end-to-end, low-latency data analytics pipeline.</p>
<p><img decoding="async" loading="lazy" alt="This image shows the Apache Doris real-time analytics architecture. It focuses on &#x201C;Real-time Analytics&#x201D; with &#x201C;Low Latency, End-to-End&#x201D; and &#x201C;Sub-second Analytics.&#x201D; On the left are four real-time data sources: Events, Apps, IoT, and Database. In the center are the three D-Crew components: Flux, the data explorer; Dori, the core engine; and Pip, the query runner. They connect real-time data, compute quickly, and run instant queries. On the right, a dashboard displays revenue, orders, active users, and other data. The bottom of the image highlights real-time data sources, low-latency compute, instant queries, and live updates." src="https://cdnd.selectdb.com/assets/shared/5c442d325656cc64418a2ff3f4a9082c.jpg" width="1672" height="941" class="img_ev3q"></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="lakehouse-analytics"><strong>Lakehouse Analytics</strong><a href="https://doris.apache.org/ko/blog/meet-d-crew-apache-doris-mascot-family/#lakehouse-analytics" class="hash-link" aria-label="lakehouse-analytics &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="lakehouse-analytics &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>In a <strong>Lakehouse Analytics</strong> use case, Flux connects directly to open data ecosystems such as Iceberg, Paimon, and Delta Lake. Dori efficiently analyzes structured data, text, and vectors through one engine, while Pip presents the resulting hybrid analytics and retrieval results to users.</p>
<p><img decoding="async" loading="lazy" alt="This image shows how Apache Doris works in a Lakehouse Analytics use case. On the left are data lakes such as Iceberg, Paimon, and Delta Lake, with Flux connecting to their data. In the center is Dori, a unified multimodal engine that supports SQL and tabular data, full-text indexes, and vector indexes. On the right, Pip uses SQL to query hybrid analytics and retrieval results. The Lakehouse Insights dashboard in the upper-right corner shows sales trends, total sales, order counts, and other data. The image illustrates the roles of Flux, Dori, and Pip in the Lakehouse Analytics workflow." src="https://cdnd.selectdb.com/assets/shared/49957215668c9e2f95fe8a39521d9eb3.jpg" width="1672" height="941" class="img_ev3q"></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="agent-observability"><strong>Agent Observability</strong><a href="https://doris.apache.org/ko/blog/meet-d-crew-apache-doris-mascot-family/#agent-observability" class="hash-link" aria-label="agent-observability &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="agent-observability &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>In an <strong>Agent Observability</strong> use case, Flux ingests observability data such as Log, Metric, and Trace data. Dori uses Variant and time-series data capabilities to organize and process JSON and time-series data efficiently. Pip presents detected system anomalies and behavioral patterns in real time, helping organizations evaluate Agent performance more efficiently and keep track of system health.</p>
<p><img decoding="async" loading="lazy" alt="In this Agent Observability use case, Flux ingests real-time observability signals from Logs, Metrics, and Traces. Dori organizes and processes the data using Variant, JSON, and time-series data capabilities. Pip displays anomaly detection results, trace latency, and Agent performance on a real-time health dashboard." src="https://cdnd.selectdb.com/assets/shared/e228a1894571ed6053006b53b7797cd7.jpg" width="1672" height="941" class="img_ev3q"></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="agentic-data-engine"><strong>Agentic Data Engine</strong><a href="https://doris.apache.org/ko/blog/meet-d-crew-apache-doris-mascot-family/#agentic-data-engine" class="hash-link" aria-label="agentic-data-engine &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="agentic-data-engine &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h3>
<p>Apache Doris is evolving into a data analytics system for Agents. In an <strong>Agentic Data Engine</strong> use case, Flux connects an Agent to real-time, trusted data and finds the context it needs. Pip receives the Agent&apos;s query and analytics requests, while Dori handles the computation and processing quickly behind the scenes.</p>
<p><img decoding="async" loading="lazy" alt="This image shows how Apache Doris works in an Agentic Data Engine use case. On the left are AI Agent requests from Claude Code Session, Codex Session, Agent Session, and others. In the center are Flux, Pip, and Dori. Flux assembles context and memory, Pip orchestrates queries and analytics, and Dori serves as the high-performance data engine. On the right are trusted answers, real-time metrics, fresh context, and other results. The image illustrates how the three characters work together in the Apache Doris data analytics system for Agents." src="https://cdnd.selectdb.com/assets/shared/e92a8fd667d087e7a283b68eff7a73ae.jpg" width="1672" height="941" class="img_ev3q"></p>
<p>From real-time analytics and lakehouses to hybrid search and Agent-oriented data analytics, the three characters will appear together in different ways. Through these visual stories, we hope to make it easier to understand what Apache Doris can do and how it works with real-world data.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="join-the-community">Join the Community<a href="https://doris.apache.org/ko/blog/meet-d-crew-apache-doris-mascot-family/#join-the-community" class="hash-link" aria-label="Join the Community &#xC9C1;&#xC811; &#xB9C1;&#xD06C;" title="Join the Community &#xC9C1;&#xC811; &#xB9C1;&#xD06C;">&#x200B;</a></h2>
<p>If you see Pip, Dori, and Flux in our documentation, blog posts, Meetups, or on stickers, remember to say hello.</p>
<p><strong>Welcome to the Apache Doris community, D-Crew. And everyone else, you are welcome to join us too</strong>.</p>
<p><img decoding="async" loading="lazy" alt="This image welcomes people to the Apache Doris community. Three cartoon characters, green on the left, blue in the center, and purple on the right, hold signs that read &#x201C;Welcome to Apache Doris&#x201D; and &#x201C;Welcome D-Crew!&#x201D; Colorful streamers and balloons decorate the background as other cartoon figures celebrate around them. The cheerful scene welcomes D-Crew to the Apache Doris community." src="https://cdnd.selectdb.com/assets/shared/8a3bfd70151678e01e5dd01efae14171.jpg" width="1916" height="821" class="img_ev3q"></p></div>]]></content:encoded>
            <category>Top News</category>
        </item>
        <item>
            <title><![CDATA[Search in Apache Doris 4.1: Unifying Full-Text Log Search and Real-Time SQL Analytics]]></title>
            <link>https://doris.apache.org/ko/blog/search-in-apache-doris-4-1-unifying-full-text-log-search-and-real-time-sql-analytics/</link>
            <guid>https://doris.apache.org/ko/blog/search-in-apache-doris-4-1-unifying-full-text-log-search-and-real-time-sql-analytics/</guid>
            <pubDate>Fri, 24 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Apache Doris 4.1 uses search(), inverted indexes, BM25 scoring, and standard SQL to unify full-text log search with real-time analytics for observability, SIEM, and product search workloads.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Tech Sharing</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">Search in Apache Doris 4.1: Unifying Full-Text Log Search and Real-Time SQL Analytics</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">velodb.io &#xB7; Tom Zhang</span></span><time datetime="2026-07-24T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 7&#xC6D4; 24&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<a class="blog-item-link" rel="noopener noreferrer" target="_blank" href="https://www.velodb.io/blog/search-in-apache-doris-4-1-unifying-full-text-log-search-and-real-time-sql-analytics">Apache Doris 4.1 uses search(), inverted indexes, BM25 scoring, and standard SQL to unify full-text log search with real-time analytics for observability, SIEM, and product search workloads. <span style="color:var(--ifm-color-primary);display:inline-flex;align-items:center;gap:4px">see more <svg width="1rem" height="1rem" viewBox="0 0 18 18" fill="none"><path d="M14.8497 8.99993L14.8497 14.5349C14.8497 14.8332 14.6079 15.0749 14.3097 15.0749H3.68966C3.39142 15.0749 3.14966 14.8332 3.14966 14.5349V3.46493C3.14966 3.16669 3.39142 2.92493 3.68966 2.92493H8.53166" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.4746 2.92493H14.3096C14.6078 2.92493 14.8496 3.16669 14.8496 3.46493V6.29993" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.9944 3.82495L8.90322 8.91612" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span></a>
</blockquote></div>]]></content:encoded>
            <category>Tech Sharing</category>
        </item>
        <item>
            <title><![CDATA[Apache Doris Gets Rust-Native Streaming Ingestion with Apache Iggy]]></title>
            <link>https://doris.apache.org/ko/blog/apache-doris-rust-native-streaming-ingestion-with-apache-iggy/</link>
            <guid>https://doris.apache.org/ko/blog/apache-doris-rust-native-streaming-ingestion-with-apache-iggy/</guid>
            <pubDate>Fri, 17 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Apache Doris now supports Rust-native streaming ingestion from Apache Iggy through a new sink connector built with LaserData.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Tech Sharing</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">Apache Doris Gets Rust-Native Streaming Ingestion with Apache Iggy</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">velodb.io &#xB7; VeloDB Product Team &amp; LaserData</span></span><time datetime="2026-07-17T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 7&#xC6D4; 17&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<a class="blog-item-link" rel="noopener noreferrer" target="_blank" href="https://www.velodb.io/blog/velodb-and-apache-doris-get-rust-native-streaming-ingestion-with-apache-iggy">Apache Doris now supports Rust-native streaming ingestion from Apache Iggy through a new sink connector built with LaserData. <span style="color:var(--ifm-color-primary);display:inline-flex;align-items:center;gap:4px">see more <svg width="1rem" height="1rem" viewBox="0 0 18 18" fill="none"><path d="M14.8497 8.99993L14.8497 14.5349C14.8497 14.8332 14.6079 15.0749 14.3097 15.0749H3.68966C3.39142 15.0749 3.14966 14.8332 3.14966 14.5349V3.46493C3.14966 3.16669 3.39142 2.92493 3.68966 2.92493H8.53166" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.4746 2.92493H14.3096C14.6078 2.92493 14.8496 3.16669 14.8496 3.46493V6.29993" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.9944 3.82495L8.90322 8.91612" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span></a>
</blockquote></div>]]></content:encoded>
            <category>Tech Sharing</category>
        </item>
        <item>
            <title><![CDATA[Databricks RT and LTAP are here. How does it fit into OLTP, OLAP, real-time OLAP, and HTAP]]></title>
            <link>https://doris.apache.org/ko/blog/databricks-rt-and-ltap-oltp-olap-real-time-olap-and-htap/</link>
            <guid>https://doris.apache.org/ko/blog/databricks-rt-and-ltap-oltp-olap-real-time-olap-and-htap/</guid>
            <pubDate>Fri, 10 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Real-time database categories now span across OLTP, OLAP, real-time OLAP, HTAP, and Databricks' new LTAP, but each makes different trade-offs across freshness, query latency, concurrency, and updates.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Tech Sharing</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">Databricks RT and LTAP are here. How does it fit into OLTP, OLAP, real-time OLAP, and HTAP</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">velodb.io &#xB7; Kevin Shen</span></span><time datetime="2026-07-10T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 7&#xC6D4; 10&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<a class="blog-item-link" rel="noopener noreferrer" target="_blank" href="https://www.velodb.io/blog/databricks-rt-and-ltap-are-here-how-does-it-fit-into-oltp-olap-real-time-olap-and-htap">Real-time database categories now span across OLTP, OLAP, real-time OLAP, HTAP, and Databricks&apos; new LTAP, but each makes different trade-offs across freshness, query latency, concurrency, and updates. <span style="color:var(--ifm-color-primary);display:inline-flex;align-items:center;gap:4px">see more <svg width="1rem" height="1rem" viewBox="0 0 18 18" fill="none"><path d="M14.8497 8.99993L14.8497 14.5349C14.8497 14.8332 14.6079 15.0749 14.3097 15.0749H3.68966C3.39142 15.0749 3.14966 14.8332 3.14966 14.5349V3.46493C3.14966 3.16669 3.39142 2.92493 3.68966 2.92493H8.53166" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.4746 2.92493H14.3096C14.6078 2.92493 14.8496 3.16669 14.8496 3.46493V6.29993" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.9944 3.82495L8.90322 8.91612" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span></a>
</blockquote></div>]]></content:encoded>
            <category>Tech Sharing</category>
        </item>
        <item>
            <title><![CDATA[How StepFun Built a PB-Scale Agent Observability Platform with Apache Doris]]></title>
            <link>https://doris.apache.org/ko/blog/how-stepfun-built-agent-observability-platform-with-apache-doris/</link>
            <guid>https://doris.apache.org/ko/blog/how-stepfun-built-agent-observability-platform-with-apache-doris/</guid>
            <pubDate>Wed, 08 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[StepFun built StepTrace, a PB-scale agent observability platform on Apache Doris, to analyze agent traces, costs, search, evaluation loops, and infrastructure behavior in real time.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Best Practice</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">How StepFun Built a PB-Scale Agent Observability Platform with Apache Doris</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">StepFun &#xB7; Ric Li</span></span><time datetime="2026-07-08T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 7&#xC6D4; 8&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<a class="blog-item-link" rel="noopener noreferrer" target="_blank" href="https://www.velodb.io/blog/how-stepfun-built-agent-observability-platform-with-apache-doris">StepFun built StepTrace, a PB-scale agent observability platform on Apache Doris, to analyze agent traces, costs, search, evaluation loops, and infrastructure behavior in real time. <span style="color:var(--ifm-color-primary);display:inline-flex;align-items:center;gap:4px">see more <svg width="1rem" height="1rem" viewBox="0 0 18 18" fill="none"><path d="M14.8497 8.99993L14.8497 14.5349C14.8497 14.8332 14.6079 15.0749 14.3097 15.0749H3.68966C3.39142 15.0749 3.14966 14.8332 3.14966 14.5349V3.46493C3.14966 3.16669 3.39142 2.92493 3.68966 2.92493H8.53166" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.4746 2.92493H14.3096C14.6078 2.92493 14.8496 3.16669 14.8496 3.46493V6.29993" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.9944 3.82495L8.90322 8.91612" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span></a>
</blockquote></div>]]></content:encoded>
            <category>Best Practice</category>
        </item>
        <item>
            <title><![CDATA[From Hive, HBase, MySQL, and Trino to Apache Doris: Tuhu Car's Unified OLAP Architecture]]></title>
            <link>https://doris.apache.org/ko/blog/from-hive-hbase-and-trino-to-apache-doris-tuhu-cars-unified-olap-architecture/</link>
            <guid>https://doris.apache.org/ko/blog/from-hive-hbase-and-trino-to-apache-doris-tuhu-cars-unified-olap-architecture/</guid>
            <pubDate>Fri, 03 Jul 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Tuhu Car rebuilt its fragmented Hive, HBase, MySQL, and Trino OLAP stack with Apache Doris, improving audience segmentation, user profiling, BI analysis, and real-time analytics.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Best Practice</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">From Hive, HBase, MySQL, and Trino to Apache Doris: Tuhu Car&apos;s Unified OLAP Architecture</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">Tuhu Car &#xB7; Wenbo Wang</span></span><time datetime="2026-07-03T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 7&#xC6D4; 3&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<a class="blog-item-link" rel="noopener noreferrer" target="_blank" href="https://www.velodb.io/blog/from-hive-hbase-and-trino-to-apache-doris-tuhu-cars-unified-olap-architecture">Tuhu Car rebuilt its fragmented Hive, HBase, MySQL, and Trino OLAP stack with Apache Doris, improving audience segmentation, user profiling, BI analysis, and real-time analytics. <span style="color:var(--ifm-color-primary);display:inline-flex;align-items:center;gap:4px">see more <svg width="1rem" height="1rem" viewBox="0 0 18 18" fill="none"><path d="M14.8497 8.99993L14.8497 14.5349C14.8497 14.8332 14.6079 15.0749 14.3097 15.0749H3.68966C3.39142 15.0749 3.14966 14.8332 3.14966 14.5349V3.46493C3.14966 3.16669 3.39142 2.92493 3.68966 2.92493H8.53166" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.4746 2.92493H14.3096C14.6078 2.92493 14.8496 3.16669 14.8496 3.46493V6.29993" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.9944 3.82495L8.90322 8.91612" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span></a>
</blockquote></div>]]></content:encoded>
            <category>Best Practice</category>
        </item>
        <item>
            <title><![CDATA[Why AI Agents Need Real-Time Analytics and Hybrid Search: The Data Infra for Production Agents]]></title>
            <link>https://doris.apache.org/ko/blog/why-ai-agents-need-real-time-analytics-and-hybrid-search/</link>
            <guid>https://doris.apache.org/ko/blog/why-ai-agents-need-real-time-analytics-and-hybrid-search/</guid>
            <pubDate>Wed, 24 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[AI agents need real-time analytics, not just vector search. Apache Doris unifies both capabilities, offering native hybrid search in one real-time engine built for agent workloads.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Tech Sharing</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">Why AI Agents Need Real-Time Analytics and Hybrid Search: The Data Infra for Production Agents</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">velodb.io &#xB7; Matt Yi</span></span><time datetime="2026-06-24T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 6&#xC6D4; 24&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<a class="blog-item-link" rel="noopener noreferrer" target="_blank" href="https://www.velodb.io/blog/why-ai-agents-need-real-time-analytics-and-hybrid-search">AI agents need real-time analytics, not just vector search. Apache Doris unifies both capabilities, offering native hybrid search in one real-time engine built for agent workloads. <span style="color:var(--ifm-color-primary);display:inline-flex;align-items:center;gap:4px">see more <svg width="1rem" height="1rem" viewBox="0 0 18 18" fill="none"><path d="M14.8497 8.99993L14.8497 14.5349C14.8497 14.8332 14.6079 15.0749 14.3097 15.0749H3.68966C3.39142 15.0749 3.14966 14.8332 3.14966 14.5349V3.46493C3.14966 3.16669 3.39142 2.92493 3.68966 2.92493H8.53166" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.4746 2.92493H14.3096C14.6078 2.92493 14.8496 3.16669 14.8496 3.46493V6.29993" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.9944 3.82495L8.90322 8.91612" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span></a>
</blockquote></div>]]></content:encoded>
            <category>Tech Sharing</category>
        </item>
        <item>
            <title><![CDATA[ASOF JOIN Benchmark: Apache Doris vs ClickHouse and DuckDB]]></title>
            <link>https://doris.apache.org/ko/blog/asof-join-benchmark-apache-doris-vs-clickhouse-and-duckdb/</link>
            <guid>https://doris.apache.org/ko/blog/asof-join-benchmark-apache-doris-vs-clickhouse-and-duckdb/</guid>
            <pubDate>Thu, 11 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Apache Doris 4.1 outperforms ClickHouse and DuckDB on ASOF JOIN across all 11 benchmark scenarios.]]></description>
            <content:encoded><![CDATA[<header><div class="text-center mb-4"><a class="!text-[#8592A6] cursor-pointer hover:no-underline" href="https://doris.apache.org/ko/blog/">Blog</a><span class="px-2 text-[#8592A6]">/</span><span><span class="s-tags"><span class="s-tag">Tech Sharing</span></span></span></div><h1 class="blog-post-title text-[2rem] leading-normal lg:!text-[2.5rem] text-center" itemprop="headline">ASOF JOIN Benchmark: Apache Doris vs ClickHouse and DuckDB</h1><div class="blog-info text-center flex justify-center text-sm text-black"><span class="authors"><span class="s-author text-black">velodb.io &#xB7; Changle Zhao</span></span><time datetime="2026-06-11T00:00:00.000Z" itemprop="datePublished" class="text-black ml-4">2026&#xB144; 6&#xC6D4; 11&#xC77C;</time></div></header><div id="__blog-post-container" class="markdown" itemprop="articleBody"><blockquote>
<a class="blog-item-link" rel="noopener noreferrer" target="_blank" href="https://www.velodb.io/blog/asof-join-benchmark-apache-doris-vs-clickhouse-and-duckdb">Apache Doris 4.1 outperforms ClickHouse and DuckDB on ASOF JOIN across all 11 benchmark scenarios. <span style="color:var(--ifm-color-primary);display:inline-flex;align-items:center;gap:4px">see more <svg width="1rem" height="1rem" viewBox="0 0 18 18" fill="none"><path d="M14.8497 8.99993L14.8497 14.5349C14.8497 14.8332 14.6079 15.0749 14.3097 15.0749H3.68966C3.39142 15.0749 3.14966 14.8332 3.14966 14.5349V3.46493C3.14966 3.16669 3.39142 2.92493 3.68966 2.92493H8.53166" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.4746 2.92493H14.3096C14.6078 2.92493 14.8496 3.16669 14.8496 3.46493V6.29993" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.9944 3.82495L8.90322 8.91612" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></span></a>
</blockquote></div>]]></content:encoded>
            <category>Tech Sharing</category>
        </item>
    </channel>
</rss>