This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris-website.git
The following commit(s) were added to refs/heads/master by this push:
new baf49adf765 [refactor](next) add agent log bench page (#3654)
baf49adf765 is described below
commit baf49adf765b65dac46d18ebbfbae117963707f5
Author: Mingyu Chen (Rayner) <[email protected]>
AuthorDate: Fri May 15 14:49:15 2026 -0700
[refactor](next) add agent log bench page (#3654)
---
scripts/patch-search-tokenize.js | 228 +++++
src/components/why-doris-next/BenchmarkNext.scss | 97 +-
src/components/why-doris-next/BenchmarkNext.tsx | 266 +++--
src/constant/agentlog-benchmark.data.json | 1173 ++++++++++++++++++++++
4 files changed, 1646 insertions(+), 118 deletions(-)
diff --git a/scripts/patch-search-tokenize.js b/scripts/patch-search-tokenize.js
index 44fcb3e8396..dec4cdf14b7 100644
--- a/scripts/patch-search-tokenize.js
+++ b/scripts/patch-search-tokenize.js
@@ -27,6 +27,44 @@ const targetBuildIndexFile = path.join(
"buildIndex.js"
);
+const targetSearchBarFile = path.join(
+ process.cwd(),
+ "node_modules",
+ "@yang1666204",
+ "docusaurus-search-local",
+ "dist",
+ "client",
+ "client",
+ "theme",
+ "SearchBar",
+ "SearchBar.jsx"
+);
+
+const targetPostBuildFactoryFile = path.join(
+ process.cwd(),
+ "node_modules",
+ "@yang1666204",
+ "docusaurus-search-local",
+ "dist",
+ "server",
+ "server",
+ "utils",
+ "postBuildFactory.js"
+);
+
+const targetSearchPageFile = path.join(
+ process.cwd(),
+ "node_modules",
+ "@yang1666204",
+ "docusaurus-search-local",
+ "dist",
+ "client",
+ "client",
+ "theme",
+ "SearchPage",
+ "SearchPage.jsx"
+);
+
function patchTokenizeContent(content) {
if (content.includes("const hasJapaneseKana =
/[\\u3040-\\u30ff]/u.test(text);")) {
return content;
@@ -100,6 +138,180 @@ function patchBuildIndexContent(content) {
return content.replace(needle, replacement);
}
+// On non-default-locale routes (e.g. /zh-CN/docs-next/..., /ja/docs/...) the
+// plugin strips only `baseUrl` before matching `searchContextByPaths`, so the
+// remaining URI keeps the locale prefix and never matches `docs-next` /
`docs`.
+// Combined with `useAllContextsWithNoSearchContext: true`, this collapses the
+// search back to the root index (which contains every version, including the
+// retired v4.x). These two patches strip the non-default locale prefix in both
+// the runtime SearchBar and the build-time context partitioning so each locale
+// gets its own per-context index files and the dropdown stays scoped to the
+// active docs tree.
+function patchSearchBarContent(content) {
+ if (content.includes("PATCH(locale-aware-context)")) {
+ return content;
+ }
+
+ const needle =
+ " if (location.pathname.startsWith(versionUrl)) {\n" +
+ " const uri =
location.pathname.substring(versionUrl.length);\n" +
+ " let matchedPath;\n" +
+ " for (const _path of searchContextByPaths) {\n" +
+ " const path = typeof _path === \"string\" ? _path :
_path.path;\n" +
+ " if (uri === path || uri.startsWith(`${path}/`)) {\n" +
+ " matchedPath = path;\n" +
+ " break;\n" +
+ " }\n" +
+ " }\n";
+
+ const replacement =
+ " if (location.pathname.startsWith(versionUrl)) {\n" +
+ " const uri =
location.pathname.substring(versionUrl.length);\n" +
+ " // PATCH(locale-aware-context): strip non-default locale
prefix so\n" +
+ " // /zh-CN/docs-next/... and /ja/docs/... match the configured
contexts.\n" +
+ " const __localePrefix = currentLocale + \"/\";\n" +
+ " const __ctxUri = uri.startsWith(__localePrefix) ?
uri.substring(__localePrefix.length) : uri;\n" +
+ " let matchedPath;\n" +
+ " for (const _path of searchContextByPaths) {\n" +
+ " const path = typeof _path === \"string\" ? _path :
_path.path;\n" +
+ " if (__ctxUri === path || __ctxUri.startsWith(`${path}/`))
{\n" +
+ " matchedPath = path;\n" +
+ " break;\n" +
+ " }\n" +
+ " }\n";
+
+ if (!content.includes(needle)) {
+ return null;
+ }
+ return content.replace(needle, replacement);
+}
+
+function patchPostBuildFactoryContent(content) {
+ if (content.includes("PATCH(locale-aware-context)")) {
+ return content;
+ }
+
+ const needle1 =
+ " if (searchContextByPaths) {\n" +
+ " const { baseUrl } = buildData;\n" +
+ " const rootAllDocs = [];\n";
+
+ const replacement1 =
+ " if (searchContextByPaths) {\n" +
+ " const { baseUrl } = buildData;\n" +
+ " // PATCH(locale-aware-context): strip non-default
locale prefix so\n" +
+ " // /zh-CN/docs-next/... and /ja/docs/... get assigned
to the\n" +
+ " // configured contexts instead of falling into the
root bucket.\n" +
+ " const __i18n = buildData.i18n;\n" +
+ " const __localePrefix = __i18n && __i18n.currentLocale
&& __i18n.currentLocale !== __i18n.defaultLocale\n" +
+ " ? __i18n.currentLocale + \"/\"\n" +
+ " : \"\";\n" +
+ " const rootAllDocs = [];\n";
+
+ const needle2 =
+ " if (doc.u.startsWith(baseUrl)) {\n" +
+ " const uri =
doc.u.substring(baseUrl.length);\n" +
+ " const matchedPaths = [];\n" +
+ " for (const _path of searchContextByPaths)
{\n" +
+ " const path = typeof _path ===
\"string\" ? _path : _path.path;\n" +
+ " if (uri === path ||
uri.startsWith(`${path}/`)) {\n" +
+ " matchedPaths.push(path);\n" +
+ " }\n" +
+ " }\n";
+
+ const replacement2 =
+ " if (doc.u.startsWith(baseUrl)) {\n" +
+ " const uri =
doc.u.substring(baseUrl.length);\n" +
+ " const __ctxUri = __localePrefix &&
uri.startsWith(__localePrefix)\n" +
+ " ?
uri.substring(__localePrefix.length)\n" +
+ " : uri;\n" +
+ " const matchedPaths = [];\n" +
+ " for (const _path of searchContextByPaths)
{\n" +
+ " const path = typeof _path ===
\"string\" ? _path : _path.path;\n" +
+ " if (__ctxUri === path ||
__ctxUri.startsWith(`${path}/`)) {\n" +
+ " matchedPaths.push(path);\n" +
+ " }\n" +
+ " }\n";
+
+ if (!content.includes(needle1) || !content.includes(needle2)) {
+ return null;
+ }
+ return content.replace(needle1, replacement1).replace(needle2, replacement2);
+}
+
+// The search worker fetches `${versionUrl}search-index-*.json`. `versionUrl`
+// defaults to `siteConfig.baseUrl` (= "/"), which is locale-agnostic, so on
+// /zh-CN/* or /ja/* pages the worker still hits the default-locale index files
+// at the site root and never sees the per-locale indexes that Docusaurus emits
+// under build/{locale}/. These two patches make `versionUrl` carry the active
+// locale prefix in both the SearchBar (live dropdown + `?version=` it writes
+// into the "see all" link) and the SearchPage (direct loads of
/{locale}/search
+// with no explicit `?version=`).
+function patchSearchBarVersionUrlContent(content) {
+ if (content.includes("PATCH(locale-aware-version-url)")) {
+ return content;
+ }
+
+ const needle1 =
+ " const { siteConfig: { baseUrl }, i18n: { currentLocale }, } =
useDocusaurusContext();\n";
+
+ const replacement1 =
+ " const { siteConfig: { baseUrl }, i18n: { currentLocale, defaultLocale
}, } = useDocusaurusContext();\n";
+
+ const needle2 =
+ " }\n" +
+ " }\n" +
+ " const history = useHistory();\n";
+
+ const replacement2 =
+ " }\n" +
+ " }\n" +
+ " // PATCH(locale-aware-version-url): non-default locales serve their
own\n" +
+ " // search-index files under /{locale}/. Prepend the locale to
versionUrl\n" +
+ " // so the worker fetches /{locale}/search-index-*.json instead of the
EN one.\n" +
+ " if (currentLocale && defaultLocale && currentLocale !==
defaultLocale) {\n" +
+ " const __localeSegment = currentLocale + \"/\";\n" +
+ " if (!versionUrl.startsWith(baseUrl + __localeSegment)) {\n" +
+ " versionUrl = baseUrl + __localeSegment +
versionUrl.substring(baseUrl.length);\n" +
+ " }\n" +
+ " }\n" +
+ " const history = useHistory();\n";
+
+ if (!content.includes(needle1) || !content.includes(needle2)) {
+ return null;
+ }
+ return content.replace(needle1, replacement1).replace(needle2, replacement2);
+}
+
+function patchSearchPageVersionUrlContent(content) {
+ if (content.includes("PATCH(locale-aware-version-url)")) {
+ return content;
+ }
+
+ const needle1 =
+ " const { siteConfig: { baseUrl }, i18n: { currentLocale }, } =
useDocusaurusContext();\n";
+
+ const replacement1 =
+ " const { siteConfig: { baseUrl }, i18n: { currentLocale, defaultLocale
}, } = useDocusaurusContext();\n";
+
+ const needle2 = " const versionUrl = `${baseUrl}${searchVersion}`;\n";
+
+ const replacement2 =
+ " // PATCH(locale-aware-version-url): when there is no explicit
?version=\n" +
+ " // and the page is rendered under a non-default locale, fall back to
that\n" +
+ " // locale's index files instead of the default-locale root.\n" +
+ " const versionUrl = searchVersion\n" +
+ " ? `${baseUrl}${searchVersion}`\n" +
+ " : (currentLocale && defaultLocale && currentLocale !==
defaultLocale\n" +
+ " ? `${baseUrl}${currentLocale}/`\n" +
+ " : baseUrl);\n";
+
+ if (!content.includes(needle1) || !content.includes(needle2)) {
+ return null;
+ }
+ return content.replace(needle1, replacement1).replace(needle2, replacement2);
+}
+
function patchOneFile(filePath, patchFn, label) {
if (!fs.existsSync(filePath)) {
console.warn(`[patch-search-tokenize] skip(${label}): file not found:
${filePath}`);
@@ -126,6 +338,22 @@ function patchOneFile(filePath, patchFn, label) {
function main() {
patchOneFile(targetTokenizeFile, patchTokenizeContent, "client-tokenize");
patchOneFile(targetBuildIndexFile, patchBuildIndexContent,
"server-buildIndex");
+ patchOneFile(targetSearchBarFile, patchSearchBarContent,
"client-searchBar-locale");
+ patchOneFile(
+ targetPostBuildFactoryFile,
+ patchPostBuildFactoryContent,
+ "server-postBuildFactory-locale"
+ );
+ patchOneFile(
+ targetSearchBarFile,
+ patchSearchBarVersionUrlContent,
+ "client-searchBar-versionUrl"
+ );
+ patchOneFile(
+ targetSearchPageFile,
+ patchSearchPageVersionUrlContent,
+ "client-searchPage-versionUrl"
+ );
}
main();
diff --git a/src/components/why-doris-next/BenchmarkNext.scss
b/src/components/why-doris-next/BenchmarkNext.scss
index 9a432ae36d7..5bc3d9bc144 100644
--- a/src/components/why-doris-next/BenchmarkNext.scss
+++ b/src/components/why-doris-next/BenchmarkNext.scss
@@ -110,6 +110,24 @@
&:hover { background: var(--bn-paper); }
}
+ // "See Report" CTA that sits in `.b-cmp-head` (cream background section).
+ // Deep-green fill so it reads against cream, with a disabled state that
+ // keeps the green visible (the default `.b-btn:disabled:hover` would fade
+ // it into the cream background).
+ .b-btn-report {
+ margin-top: 28px;
+ background: var(--bn-green-deep);
+ color: var(--bn-cream-light);
+ border-color: var(--bn-green-deep);
+
+ &:hover { background: var(--bn-green-darker); }
+
+ &:disabled:hover,
+ &[aria-disabled='true']:hover {
+ background: var(--bn-green-deep);
+ }
+ }
+
.b-btn:disabled,
.b-btn[aria-disabled='true'] {
cursor: not-allowed;
@@ -299,6 +317,20 @@
color: rgba(15, 26, 20, 0.70);
max-width: 620px;
margin: 0;
+
+ a {
+ color: var(--bn-ink);
+ text-decoration: none;
+ border-bottom: 1px solid rgba(11, 122, 88, 0.45);
+ padding-bottom: 1px;
+ transition: color 0.15s ease, border-color 0.15s ease;
+
+ &:hover {
+ color: var(--bn-green-deep);
+ border-bottom-color: var(--bn-green-deep);
+ text-decoration: none;
+ }
+ }
}
@@ -524,15 +556,6 @@
}
}
- .b-bar-partial {
- display: inline-block;
- font-family: var(--bn-mono);
- font-size: 10.5px;
- font-weight: 700;
- letter-spacing: 0.02em;
- vertical-align: 1px;
- }
-
.b-bar-track {
height: 10px;
background: rgba(15, 26, 20, 0.08);
@@ -570,18 +593,6 @@
color: rgba(15, 26, 20, 0.72);
}
- .b-card-note {
- margin-top: auto;
- margin-bottom: 12px;
- font-family: var(--bn-sans);
- font-size: 12px;
- line-height: 1.5;
- font-style: italic;
- color: rgba(15, 26, 20, 0.55);
- }
-
- .b-card-note + .b-card-desc { margin-top: 0; }
-
.b-card-tip {
margin-top: 16px;
font-family: var(--bn-mono);
@@ -784,26 +795,44 @@
rgba(255, 92, 57, 0.40) 3px 6px
);
min-height: 0;
+ }
- .b-cluster-bar-tip { color: var(--bn-coral); }
+ // Bars whose value exceeds the visible Y-axis cap. Rendered at full
+ // chart height with two horizontal "gap" strips near the top — a
+ // "broken bar" convention that signals "this bar runs off-scale; hover
+ // for the real number." Painted with `background-image` strips in the
+ // surrounding section's color, layered over the bar's own
+ // background-color.
+ &.is-over-cap {
+ border-radius: 0;
+ background-image: linear-gradient(
+ to top,
+ transparent 0,
+ transparent calc(100% - 16px),
+ var(--bn-cream-light) calc(100% - 16px),
+ var(--bn-cream-light) calc(100% - 13px),
+ transparent calc(100% - 13px),
+ transparent calc(100% - 8px),
+ var(--bn-cream-light) calc(100% - 8px),
+ var(--bn-cream-light) calc(100% - 5px),
+ transparent calc(100% - 5px),
+ transparent 100%
+ );
}
&:hover {
filter: brightness(1.06);
z-index: 20;
-
- .b-cluster-bar-tip {
- opacity: 1;
- transform: translate(-50%, -110%);
- }
}
}
- .b-cluster-bar-tip {
- position: absolute;
- left: 50%;
+ // Single floating tooltip rendered at the DetailStrip level. Its position
+ // is set imperatively via a ref on every mousemove, so it tracks the
+ // cursor instead of being anchored above the bar.
+ .b-floating-tip {
+ position: fixed;
+ left: 0;
top: 0;
- transform: translate(-50%, -100%);
background: var(--bn-ink);
color: var(--bn-cream-light);
font-family: var(--bn-mono);
@@ -813,9 +842,10 @@
white-space: nowrap;
pointer-events: none;
opacity: 0;
- transition: opacity 0.15s, transform 0.15s;
+ transition: opacity 0.12s ease;
border: 1px solid rgba(15, 26, 20, 0.40);
- z-index: 10;
+ box-shadow: 0 8px 24px -10px rgba(15, 26, 20, 0.55);
+ z-index: 100;
}
.b-cluster-label {
@@ -1285,6 +1315,5 @@
}
.b-bar-label { letter-spacing: 0; }
.b-card-desc { font-size: 12.5px; padding-top: 12px; }
- .b-card-note { font-size: 11.5px; }
}
}
diff --git a/src/components/why-doris-next/BenchmarkNext.tsx
b/src/components/why-doris-next/BenchmarkNext.tsx
index c42a842e1cd..7eee3aeb3bb 100644
--- a/src/components/why-doris-next/BenchmarkNext.tsx
+++ b/src/components/why-doris-next/BenchmarkNext.tsx
@@ -10,13 +10,14 @@ import React, {
import Link from '@docusaurus/Link';
import { LayoutNext } from '../home-next/LayoutNext';
import benchmarkData from '@site/src/constant/benchmark.data.json';
+import agentlogBenchmarkData from
'@site/src/constant/agentlog-benchmark.data.json';
import './BenchmarkNext.scss';
/* ──────────────────────────────────────────────────────────────────────────
* Types
* ──────────────────────────────────────────────────────────────────────────
*/
-type ProductId = 'doris' | 'clickhouse' | 'redshift' | 'snowflake' | 'trino';
+type ProductId = string;
interface Product {
id: ProductId;
@@ -54,26 +55,37 @@ interface BenchmarkDataset {
* ──────────────────────────────────────────────────────────────────────────
*/
const DATA = benchmarkData as unknown as BenchmarkDataset;
+const AGENTLOG_DATA = agentlogBenchmarkData as unknown as BenchmarkDataset;
const TAB_DESCRIPTIONS: Record<string, string> = {
internal:
- 'Each engine reads and writes data in its own native format, so Doris
and its peers run on their own storage layers.',
+ 'Each engine reads and writes data in its own native format.',
iceberg:
- 'Every engine queries the same Apache Iceberg dataset, so storage is
held constant and only the engine changes.',
+ 'Every engine reads the same Apache Iceberg dataset, so only the
engine changes.',
+ s100m: 'Official leaderboard size. Around 100M rows.',
+ s10m: 'Full validation pass that still fits on a single machine. Around
10M rows.',
+ s1m: 'Quick smoke-test size. Around 1M rows.',
};
const BENCH_DESC: Record<string, string> = {
ssb: 'A star-schema benchmark with 13 queries, heavy on wide joins and
aggregations.',
tpch: 'The classic decision-support benchmark: 22 ad-hoc queries against
a normalized schema.',
- tpcds: 'The most demanding decision-support benchmark: 99 queries that
exercise the full surface of an analytical engine.',
+ tpcds: 'The hardest decision-support benchmark: 99 queries that cover most
of what an analytical engine has to do.',
+ retrieval: 'Observation lookup, trace replay, generation-to-tool chain
expansion, and incident keyword / phrase retrieval over large text bodies.',
+ analytics: 'Trace-level failure and cost summaries, model and
observation-type rollups, tool usage distributions, and operational
diagnostics.',
+ semi: 'Filtering and aggregation over evolving payload fields:
release rings, customer tiers, retrieval strategies, and nested provider / tool
diagnostics.',
};
-const PRODUCT_COLORS: Record<ProductId, string> = {
+const PRODUCT_COLORS: Record<string, string> = {
doris: 'var(--bn-green-deep)',
clickhouse: '#3D4A55',
redshift: '#A4633A',
snowflake: '#3C6CAA',
trino: 'var(--bn-coral)',
+ elastic: '#00BFB3',
+ opensearch: '#005EB8',
+ postgres: '#BA3F66',
+ duckdb: '#FCB232',
};
/* ──────────────────────────────────────────────────────────────────────────
@@ -116,35 +128,10 @@ function Hero(): JSX.Element {
<span className="b-accent">Apache Doris</span> really is.
</h1>
<p className="b-hero-sub" data-reveal data-reveal-delay="1">
- Side-by-side query results: Doris versus ClickHouse,
Redshift, Snowflake, and
- Trino on{' '}
- <a
- className="b-hero-link"
- href="https://www.cs.umb.edu/~poneil/StarSchemaB.PDF"
- target="_blank"
- rel="noopener noreferrer"
- >
- Star Schema Benchmark
- </a>
- ,{' '}
- <a
- className="b-hero-link"
- href="https://www.tpc.org/tpch/"
- target="_blank"
- rel="noopener noreferrer"
- >
- TPC-H
- </a>
- , and{' '}
- <a
- className="b-hero-link"
- href="https://www.tpc.org/tpcds/"
- target="_blank"
- rel="noopener noreferrer"
- >
- TPC-DS
- </a>
- .
+ Two workloads people actually run on Apache Doris: classic
SQL
+ analytics, and AI-agent observability logs. Both compared
against
+ the engines you’d realistically consider. Scripts
and raw
+ timings are public.
</p>
</div>
</section>
@@ -158,7 +145,6 @@ function Hero(): JSX.Element {
function SummaryBar({ product, max }: { product: Product; max: number }):
JSX.Element {
const [w, setW] = useState(0);
const ref = useRef<HTMLDivElement | null>(null);
- const partial = product.queriesCompleted < product.queriesTotal;
const targetW = max > 0 ? (product.totalRuntime / max) * 100 : 0;
useEffect(() => {
@@ -187,14 +173,6 @@ function SummaryBar({ product, max }: { product: Product;
max: number }): JSX.El
<div ref={ref} className={`b-bar ${product.id === 'doris' ? 'is-doris'
: ''}`}>
<div className="b-bar-label">
<span title={product.name}>{product.name}</span>
- {partial ? (
- <span
- className="b-bar-partial"
- title={`completed ${product.queriesCompleted} of
${product.queriesTotal} queries`}
- >
- [1]
- </span>
- ) : null}
</div>
<div className="b-bar-track">
<div className="b-bar-fill" style={{ width: `${w}%` }} />
@@ -230,9 +208,6 @@ function SummaryCard({
() => Math.max(...sortedProducts.map(p => p.totalRuntime || 0)),
[sortedProducts]
);
- const hasPartial = sortedProducts.some(
- p => p.queriesCompleted < p.queriesTotal
- );
useEffect(() => {
if (!cardRef.current) return undefined;
@@ -293,12 +268,6 @@ function SummaryCard({
<SummaryBar key={p.id} product={p} max={max} />
))}
</div>
- {hasPartial ? (
- <div className="b-card-note">
- [1] ClickHouse couldn’t finish some queries without
rewriting the SQL.
- The number above counts only the queries that did finish.
- </div>
- ) : null}
<div className="b-card-desc">{BENCH_DESC[bench.id] || ''}</div>
<div className="b-card-tip">
{active ? <>Hide per-query breakdown ↑</> : <>See per-query
breakdown ↓</>}
@@ -350,7 +319,30 @@ function DetailStrip({ bench }: { bench: Benchmark }):
JSX.Element {
return m;
}, [sortedProducts, bench.queries]);
- const { niceMax, ticks: yticks } = useMemo(() => niceAxis(dataMax),
[dataMax]);
+ // When a few engines run orders of magnitude slower than the rest, a
linear
+ // axis flattens the fast tier into invisibility. Cap the axis at ~10× the
+ // median observation; bars that exceed the cap are rendered at chart
height
+ // with a "broken top" marker and their real value is in the hover tooltip.
+ const cappedMax = useMemo(() => {
+ const vals: number[] = [];
+ sortedProducts.forEach(p => {
+ bench.queries.forEach(q => {
+ const v = p.perQuery[q];
+ if (v != null) vals.push(v);
+ });
+ });
+ if (vals.length < 4) return dataMax;
+ const sorted = [...vals].sort((a, b) => a - b);
+ const median = sorted[Math.floor(sorted.length / 2)] ?? 0;
+ const max = sorted[sorted.length - 1];
+ if (median <= 0) return dataMax;
+ const capValue = median * 10;
+ if (max <= capValue * 1.2) return dataMax;
+ return capValue;
+ }, [sortedProducts, bench.queries, dataMax]);
+
+ const { niceMax, ticks: yticks } = useMemo(() => niceAxis(cappedMax),
[cappedMax]);
+ const isCapped = cappedMax < dataMax;
const [animated, setAnimated] = useState(false);
useEffect(() => {
@@ -365,6 +357,35 @@ function DetailStrip({ bench }: { bench: Benchmark }):
JSX.Element {
const clusterW =
sortedProducts.length * barW + (sortedProducts.length - 1) * barGap +
clusterPad * 2;
+ const tipRef = useRef<HTMLDivElement | null>(null);
+ const placeTip = (clientX: number, clientY: number) => {
+ const el = tipRef.current;
+ if (!el) return;
+ // Keep tip within viewport: flip to the left of the cursor if it would
+ // overflow the right edge.
+ const offset = 14;
+ const w = el.offsetWidth;
+ const vw = window.innerWidth;
+ const left = clientX + offset + w > vw ? clientX - offset - w :
clientX + offset;
+ el.style.left = `${left}px`;
+ el.style.top = `${clientY + offset}px`;
+ };
+ const showTip = (e: React.MouseEvent, content: string) => {
+ const el = tipRef.current;
+ if (!el) return;
+ el.textContent = content;
+ el.style.opacity = '1';
+ placeTip(e.clientX, e.clientY);
+ };
+ const moveTip = (e: React.MouseEvent) => {
+ placeTip(e.clientX, e.clientY);
+ };
+ const hideTip = () => {
+ const el = tipRef.current;
+ if (!el) return;
+ el.style.opacity = '0';
+ };
+
return (
<div className="b-detail">
<div className="b-detail-head">
@@ -411,26 +432,35 @@ function DetailStrip({ bench }: { bench: Benchmark }):
JSX.Element {
{sortedProducts.map((p, pi) => {
const v = p.perQuery[q];
const failed = v == null;
- const h = failed ? 18 : Math.max(2,
((v as number) / niceMax) * 230);
+ const overCap = !failed && (v as
number) > niceMax;
+ const h = failed
+ ? 18
+ : overCap
+ ? 230
+ : Math.max(2, ((v as number) /
niceMax) * 230);
const color = PRODUCT_COLORS[p.id] ||
'rgba(245,239,228,0.4)';
const style: CSSProperties = {
width: barW,
height: animated ? (failed ? 18 :
h) : 0,
- background: failed ? undefined :
color,
+ // Use backgroundColor (not the
`background` shorthand) so the
+ // `.is-over-cap` gradient overlay
in SCSS isn't wiped out.
+ backgroundColor: failed ?
undefined : color,
transitionDelay: `${Math.min(qi *
12 + pi * 30, 1100)}ms`,
};
+ const tipText = `${p.name} · ${q} · ${
+ failed ? 'failed' : `${(v as
number).toFixed(2)}s`
+ }`;
return (
<span
key={p.id}
className={`b-cluster-bar
${p.id === 'doris' ? 'is-doris' : ''} ${
failed ? 'is-failed' : ''
- }`}
+ } ${overCap ? 'is-over-cap' :
''}`}
style={style}
- >
- <span
className="b-cluster-bar-tip">
- {p.name} · {q} · {failed ?
'failed' : `${(v as number).toFixed(2)}s`}
- </span>
- </span>
+ onMouseEnter={e => showTip(e,
tipText)}
+ onMouseMove={moveTip}
+ onMouseLeave={hideTip}
+ />
);
})}
</div>
@@ -467,9 +497,15 @@ function DetailStrip({ bench }: { bench: Benchmark }):
JSX.Element {
</ul>
</div>
<div className="b-detail-foot">
- Hover any bar for its exact runtime. Hatched bars are queries
that didn’t
- finish within the time limit.
+ Hover any bar for its exact runtime. Hatched bars timed out.
+ {isCapped ? (
+ <>
+ {' '}Bars with a broken top run past the visible
scale; hover for
+ the real number.
+ </>
+ ) : null}
</div>
+ <div ref={tipRef} className="b-floating-tip" aria-hidden="true" />
</div>
);
}
@@ -478,11 +514,18 @@ function DetailStrip({ bench }: { bench: Benchmark }):
JSX.Element {
* Comparison section
* ──────────────────────────────────────────────────────────────────────────
*/
-function Comparison(): JSX.Element {
- const [activeTab, setActiveTab] = useState<string>(DATA.tabs[0].id);
+interface ComparisonProps {
+ dataset: BenchmarkDataset;
+ title: string;
+ subtitle: React.ReactNode;
+ reportHref?: string;
+}
+
+function Comparison({ dataset, title, subtitle, reportHref }:
ComparisonProps): JSX.Element {
+ const [activeTab, setActiveTab] = useState<string>(dataset.tabs[0].id);
const [expanded, setExpanded] = useState<string | null>(null);
- const tab = DATA.tabs.find(t => t.id === activeTab) ?? DATA.tabs[0];
+ const tab = dataset.tabs.find(t => t.id === activeTab) ?? dataset.tabs[0];
const expandedBench = tab.benchmarks.find(b => b.id === expanded);
const colsClass = `is-cols-${tab.benchmarks.length}`;
@@ -496,16 +539,31 @@ function Comparison(): JSX.Element {
<div className="b-cmp-bggrid" aria-hidden="true" />
<div className="b-container">
<div className="b-cmp-head" data-reveal>
- <h2 className="b-cmp-title">Direct head-to-head, query by
query.</h2>
- <p className="b-cmp-sub">
- All three benchmarks lean hard on joins and complex
analytical SQL.
- That’s the work Doris is built for. Click any
benchmark to expand
- the per-query breakdown.
- </p>
+ <h2 className="b-cmp-title">{title}</h2>
+ <p className="b-cmp-sub">{subtitle}</p>
+ {reportHref ? (
+ <a
+ className="b-btn b-btn-report"
+ href={reportHref}
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ See Report ↗
+ </a>
+ ) : (
+ <button
+ type="button"
+ className="b-btn b-btn-report"
+ disabled
+ aria-disabled="true"
+ >
+ See Report (Coming Soon)
+ </button>
+ )}
</div>
<div className="b-tabs" role="tablist" data-reveal>
- {DATA.tabs.map(t => (
+ {dataset.tabs.map(t => (
<button
key={t.id}
role="tab"
@@ -779,14 +837,6 @@ function CTA(): JSX.Element {
</svg>
Get Started
</Link>
- <button
- type="button"
- className="b-btn b-btn-primary"
- disabled
- aria-disabled="true"
- >
- See Report (Coming Soon)
- </button>
</div>
</div>
</section>
@@ -801,12 +851,60 @@ export default function BenchmarkNext(): JSX.Element {
useRevealObserver();
return (
<LayoutNext
- title="Apache Doris Benchmarks: SSB, TPC-H, TPC-DS"
- description="Direct query-performance comparisons of Apache Doris
against ClickHouse, Redshift, Snowflake, and Trino across SSB, TPC-H, and
TPC-DS at scale factor 1000."
+ title="Apache Doris Benchmarks: SQL Analytics and Agent
Observability"
+ description="Apache Doris benchmark results against ClickHouse,
Redshift, Snowflake, Trino, Elasticsearch, OpenSearch, PostgreSQL, and DuckDB
on structured analytics (SSB, TPC-H, TPC-DS) and AI-agent observability
workloads."
>
<div className="bench-next">
<Hero />
- <Comparison />
+ <Comparison
+ dataset={DATA}
+ title="Structured analytics, query by query."
+ subtitle={
+ <>
+ Doris versus ClickHouse, Redshift, Snowflake, and
Trino on{' '}
+ <a
+
href="https://www.cs.umb.edu/~poneil/StarSchemaB.PDF"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ Star Schema Benchmark
+ </a>
+ ,{' '}
+ <a
+ href="https://www.tpc.org/tpch/"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ TPC-H
+ </a>
+ , and{' '}
+ <a
+ href="https://www.tpc.org/tpcds/"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ TPC-DS
+ </a>
+ . All three lean heavily on joins and analytical
SQL, which
+ is what Doris was built for. Click any benchmark
to see
+ per-query times.
+ </>
+ }
+ />
+ <Comparison
+ dataset={AGENTLOG_DATA}
+ title="Agent observability, query by query."
+
reportHref="https://www.velodb.io/blog/agentlogsbench-apache-doris-in-ai-observability"
+ subtitle={
+ <>
+ AI-agent observability logs: trace replay,
incident phrase
+ retrieval, and rollups over evolving payload
fields. Doris
+ against ClickHouse, Elasticsearch, OpenSearch,
PostgreSQL,
+ and DuckDB on the same data. Click any workload to
see
+ per-query times.
+ </>
+ }
+ />
{/* <ReproSection /> hidden for now; revisit later */}
<CTA />
</div>
diff --git a/src/constant/agentlog-benchmark.data.json
b/src/constant/agentlog-benchmark.data.json
new file mode 100644
index 00000000000..78dc4644abb
--- /dev/null
+++ b/src/constant/agentlog-benchmark.data.json
@@ -0,0 +1,1173 @@
+{
+ "syncedAt": "2026-05-15T00:00:00.000Z",
+ "source": "https://github.com/velodb/agentlogsbench",
+ "tabs": [
+ {
+ "id": "s100m",
+ "label": "100M rows",
+ "benchmarks": [
+ {
+ "id": "retrieval",
+ "name": "Search & Retrieval",
+ "scale": "8 queries",
+ "queries": [
+ "Q01",
+ "Q03",
+ "Q04",
+ "Q05",
+ "Q11",
+ "Q13",
+ "Q14",
+ "Q15"
+ ],
+ "products": [
+ {
+ "id": "doris",
+ "name": "Apache Doris",
+ "version": "5.7.99",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 2.31,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 0.093,
+ "Q03": 0.02,
+ "Q04": 0.036,
+ "Q05": 1.428,
+ "Q11": 0.134,
+ "Q13": 0.088,
+ "Q14": 0.43,
+ "Q15": 0.081
+ }
+ },
+ {
+ "id": "clickhouse",
+ "name": "ClickHouse",
+ "version": "26.2.13.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 42.115,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 2.351,
+ "Q03": 2.289,
+ "Q04": 2.411,
+ "Q05": 3.517,
+ "Q11": 6.463,
+ "Q13": 9.324,
+ "Q14": 6.224,
+ "Q15": 9.536
+ }
+ },
+ {
+ "id": "elastic",
+ "name": "Elasticsearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 7.097,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 1.505,
+ "Q03": 0.034,
+ "Q04": 0.033,
+ "Q05": 0.283,
+ "Q11": 2.04,
+ "Q13": 1.094,
+ "Q14": 0.716,
+ "Q15": 1.392
+ }
+ },
+ {
+ "id": "opensearch",
+ "name": "OpenSearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 6.081,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 1.013,
+ "Q03": 0.034,
+ "Q04": 0.034,
+ "Q05": 0.262,
+ "Q11": 1.297,
+ "Q13": 1.435,
+ "Q14": 0.682,
+ "Q15": 1.324
+ }
+ },
+ {
+ "id": "postgres",
+ "name": "PostgreSQL",
+ "version": "16.13",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 5607.067,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 9.171,
+ "Q03": 3.593,
+ "Q04": 3.629,
+ "Q05": 3.836,
+ "Q11": 121.77,
+ "Q13": 2761.598,
+ "Q14": 12.07,
+ "Q15": 2691.4
+ }
+ },
+ {
+ "id": "duckdb",
+ "name": "DuckDB",
+ "version": "1.5.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 134.414,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 0.109,
+ "Q03": 0.003,
+ "Q04": 0.742,
+ "Q05": 8.793,
+ "Q11": 18.845,
+ "Q13": 44.623,
+ "Q14": 17.841,
+ "Q15": 43.458
+ }
+ }
+ ]
+ },
+ {
+ "id": "analytics",
+ "name": "Analytics Rollups",
+ "scale": "6 queries",
+ "queries": [
+ "Q02",
+ "Q06",
+ "Q09",
+ "Q18",
+ "Q19",
+ "Q20"
+ ],
+ "products": [
+ {
+ "id": "doris",
+ "name": "Apache Doris",
+ "version": "5.7.99",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 4.278,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 0.84,
+ "Q06": 0.415,
+ "Q09": 0.27,
+ "Q18": 1.166,
+ "Q19": 0.986,
+ "Q20": 0.601
+ }
+ },
+ {
+ "id": "clickhouse",
+ "name": "ClickHouse",
+ "version": "26.2.13.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 42.3,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 2.557,
+ "Q06": 2.479,
+ "Q09": 2.421,
+ "Q18": 2.719,
+ "Q19": 29.569,
+ "Q20": 2.555
+ }
+ },
+ {
+ "id": "elastic",
+ "name": "Elasticsearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 20.979,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 15.613,
+ "Q06": 1.549,
+ "Q09": 0.359,
+ "Q18": 1.114,
+ "Q19": 0.989,
+ "Q20": 1.355
+ }
+ },
+ {
+ "id": "opensearch",
+ "name": "OpenSearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 22.655,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 16.781,
+ "Q06": 1.553,
+ "Q09": 0.414,
+ "Q18": 1.143,
+ "Q19": 1.333,
+ "Q20": 1.431
+ }
+ },
+ {
+ "id": "postgres",
+ "name": "PostgreSQL",
+ "version": "16.13",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 7796.036,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 343.59,
+ "Q06": 284.959,
+ "Q09": 287.064,
+ "Q18": 1037.045,
+ "Q19": 4752.691,
+ "Q20": 1090.687
+ }
+ },
+ {
+ "id": "duckdb",
+ "name": "DuckDB",
+ "version": "1.5.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 13485.67,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 1.082,
+ "Q06": 0.64,
+ "Q09": 0.374,
+ "Q18": 2534.466,
+ "Q19": 5374.306,
+ "Q20": 5574.802
+ }
+ }
+ ]
+ },
+ {
+ "id": "semi",
+ "name": "Semi-Structured Payload",
+ "scale": "6 queries",
+ "queries": [
+ "Q07",
+ "Q08",
+ "Q10",
+ "Q12",
+ "Q16",
+ "Q17"
+ ],
+ "products": [
+ {
+ "id": "doris",
+ "name": "Apache Doris",
+ "version": "5.7.99",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 2.495,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 1.483,
+ "Q08": 0.133,
+ "Q10": 0.312,
+ "Q12": 0.459,
+ "Q16": 0.078,
+ "Q17": 0.03
+ }
+ },
+ {
+ "id": "clickhouse",
+ "name": "ClickHouse",
+ "version": "26.2.13.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 24.253,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 2.866,
+ "Q08": 11.396,
+ "Q10": 2.362,
+ "Q12": 2.656,
+ "Q16": 2.667,
+ "Q17": 2.306
+ }
+ },
+ {
+ "id": "elastic",
+ "name": "Elasticsearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 6.252,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 1.784,
+ "Q08": 0.452,
+ "Q10": 1.948,
+ "Q12": 1.213,
+ "Q16": 0.802,
+ "Q17": 0.053
+ }
+ },
+ {
+ "id": "opensearch",
+ "name": "OpenSearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 6.204,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 1.73,
+ "Q08": 0.4,
+ "Q10": 2.069,
+ "Q12": 1.197,
+ "Q16": 0.762,
+ "Q17": 0.046
+ }
+ },
+ {
+ "id": "postgres",
+ "name": "PostgreSQL",
+ "version": "16.13",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 7795.514,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 981.569,
+ "Q08": 1496.702,
+ "Q10": 863.092,
+ "Q12": 1057.234,
+ "Q16": 1627.072,
+ "Q17": 1769.845
+ }
+ },
+ {
+ "id": "duckdb",
+ "name": "DuckDB",
+ "version": "1.5.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 17795.182,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 271.855,
+ "Q08": 26.942,
+ "Q10": 5056.695,
+ "Q12": 7389.796,
+ "Q16": 2546.002,
+ "Q17": 2503.892
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "s10m",
+ "label": "10M rows",
+ "benchmarks": [
+ {
+ "id": "retrieval",
+ "name": "Search & Retrieval",
+ "scale": "8 queries",
+ "queries": [
+ "Q01",
+ "Q03",
+ "Q04",
+ "Q05",
+ "Q11",
+ "Q13",
+ "Q14",
+ "Q15"
+ ],
+ "products": [
+ {
+ "id": "doris",
+ "name": "Apache Doris",
+ "version": "5.7.99",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 1.65,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 0.043,
+ "Q03": 0.021,
+ "Q04": 0.037,
+ "Q05": 1.168,
+ "Q11": 0.13,
+ "Q13": 0.039,
+ "Q14": 0.172,
+ "Q15": 0.04
+ }
+ },
+ {
+ "id": "clickhouse",
+ "name": "ClickHouse",
+ "version": "26.2.13.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 7.863,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 0.574,
+ "Q03": 0.559,
+ "Q04": 0.861,
+ "Q05": 1.121,
+ "Q11": 0.964,
+ "Q13": 1.419,
+ "Q14": 0.969,
+ "Q15": 1.396
+ }
+ },
+ {
+ "id": "elastic",
+ "name": "Elasticsearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 1.809,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 0.211,
+ "Q03": 0.031,
+ "Q04": 0.03,
+ "Q05": 0.083,
+ "Q11": 0.504,
+ "Q13": 0.624,
+ "Q14": 0.111,
+ "Q15": 0.215
+ }
+ },
+ {
+ "id": "opensearch",
+ "name": "OpenSearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 1.107,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 0.251,
+ "Q03": 0.03,
+ "Q04": 0.03,
+ "Q05": 0.048,
+ "Q11": 0.432,
+ "Q13": 0.067,
+ "Q14": 0.107,
+ "Q15": 0.142
+ }
+ },
+ {
+ "id": "postgres",
+ "name": "PostgreSQL",
+ "version": "16.13",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 305.432,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 0.857,
+ "Q03": 0.267,
+ "Q04": 0.267,
+ "Q05": 1.001,
+ "Q11": 10.937,
+ "Q13": 149.13,
+ "Q14": 1.107,
+ "Q15": 141.866
+ }
+ },
+ {
+ "id": "duckdb",
+ "name": "DuckDB",
+ "version": "1.5.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 13.675,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 0.04,
+ "Q03": 0.003,
+ "Q04": 0.086,
+ "Q05": 3.036,
+ "Q11": 1.46,
+ "Q13": 3.855,
+ "Q14": 1.433,
+ "Q15": 3.762
+ }
+ }
+ ]
+ },
+ {
+ "id": "analytics",
+ "name": "Analytics Rollups",
+ "scale": "6 queries",
+ "queries": [
+ "Q02",
+ "Q06",
+ "Q09",
+ "Q18",
+ "Q19",
+ "Q20"
+ ],
+ "products": [
+ {
+ "id": "doris",
+ "name": "Apache Doris",
+ "version": "5.7.99",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 0.602,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 0.111,
+ "Q06": 0.074,
+ "Q09": 0.071,
+ "Q18": 0.123,
+ "Q19": 0.131,
+ "Q20": 0.092
+ }
+ },
+ {
+ "id": "clickhouse",
+ "name": "ClickHouse",
+ "version": "26.2.13.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 6.852,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 0.638,
+ "Q06": 0.618,
+ "Q09": 0.614,
+ "Q18": 0.689,
+ "Q19": 3.671,
+ "Q20": 0.622
+ }
+ },
+ {
+ "id": "elastic",
+ "name": "Elasticsearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 287.952,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 1.38,
+ "Q06": 0.31,
+ "Q09": 0.099,
+ "Q18": 128.927,
+ "Q19": 156.962,
+ "Q20": 0.274
+ }
+ },
+ {
+ "id": "opensearch",
+ "name": "OpenSearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 2.435,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 1.528,
+ "Q06": 0.181,
+ "Q09": 0.069,
+ "Q18": 0.237,
+ "Q19": 0.238,
+ "Q20": 0.182
+ }
+ },
+ {
+ "id": "postgres",
+ "name": "PostgreSQL",
+ "version": "16.13",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 541.76,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 7.281,
+ "Q06": 2.277,
+ "Q09": 1.855,
+ "Q18": 26.757,
+ "Q19": 454.881,
+ "Q20": 48.709
+ }
+ },
+ {
+ "id": "duckdb",
+ "name": "DuckDB",
+ "version": "1.5.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 1116.084,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 0.119,
+ "Q06": 0.081,
+ "Q09": 0.051,
+ "Q18": 221.609,
+ "Q19": 460.585,
+ "Q20": 433.639
+ }
+ }
+ ]
+ },
+ {
+ "id": "semi",
+ "name": "Semi-Structured Payload",
+ "scale": "6 queries",
+ "queries": [
+ "Q07",
+ "Q08",
+ "Q10",
+ "Q12",
+ "Q16",
+ "Q17"
+ ],
+ "products": [
+ {
+ "id": "doris",
+ "name": "Apache Doris",
+ "version": "5.7.99",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 1.907,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 1.547,
+ "Q08": 0.102,
+ "Q10": 0.1,
+ "Q12": 0.09,
+ "Q16": 0.044,
+ "Q17": 0.024
+ }
+ },
+ {
+ "id": "clickhouse",
+ "name": "ClickHouse",
+ "version": "26.2.13.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 4.753,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 0.787,
+ "Q08": 1.496,
+ "Q10": 0.612,
+ "Q12": 0.646,
+ "Q16": 0.639,
+ "Q17": 0.573
+ }
+ },
+ {
+ "id": "elastic",
+ "name": "Elasticsearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 1.081,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 0.255,
+ "Q08": 0.165,
+ "Q10": 0.243,
+ "Q12": 0.255,
+ "Q16": 0.131,
+ "Q17": 0.032
+ }
+ },
+ {
+ "id": "opensearch",
+ "name": "OpenSearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 0.839,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 0.22,
+ "Q08": 0.069,
+ "Q10": 0.249,
+ "Q12": 0.153,
+ "Q16": 0.117,
+ "Q17": 0.031
+ }
+ },
+ {
+ "id": "postgres",
+ "name": "PostgreSQL",
+ "version": "16.13",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 237.482,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 33.924,
+ "Q08": 95.963,
+ "Q10": 35.072,
+ "Q12": 51.543,
+ "Q16": 12.068,
+ "Q17": 8.912
+ }
+ },
+ {
+ "id": "duckdb",
+ "name": "DuckDB",
+ "version": "1.5.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 1679.682,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 151.526,
+ "Q08": 2.844,
+ "Q10": 441.027,
+ "Q12": 652.14,
+ "Q16": 221.617,
+ "Q17": 210.528
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "s1m",
+ "label": "1M rows",
+ "benchmarks": [
+ {
+ "id": "retrieval",
+ "name": "Search & Retrieval",
+ "scale": "8 queries",
+ "queries": [
+ "Q01",
+ "Q03",
+ "Q04",
+ "Q05",
+ "Q11",
+ "Q13",
+ "Q14",
+ "Q15"
+ ],
+ "products": [
+ {
+ "id": "doris",
+ "name": "Apache Doris",
+ "version": "5.7.99",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 1.797,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 0.032,
+ "Q03": 0.017,
+ "Q04": 0.032,
+ "Q05": 1.17,
+ "Q11": 0.14,
+ "Q13": 0.032,
+ "Q14": 0.342,
+ "Q15": 0.032
+ }
+ },
+ {
+ "id": "clickhouse",
+ "name": "ClickHouse",
+ "version": "26.2.13.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 2.765,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 0.214,
+ "Q03": 0.236,
+ "Q04": 0.253,
+ "Q05": 0.637,
+ "Q11": 0.308,
+ "Q13": 0.422,
+ "Q14": 0.313,
+ "Q15": 0.382
+ }
+ },
+ {
+ "id": "elastic",
+ "name": "Elasticsearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 0.382,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 0.055,
+ "Q03": 0.029,
+ "Q04": 0.028,
+ "Q05": 0.035,
+ "Q11": 0.075,
+ "Q13": 0.065,
+ "Q14": 0.038,
+ "Q15": 0.057
+ }
+ },
+ {
+ "id": "opensearch",
+ "name": "OpenSearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 0.623,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 0.064,
+ "Q03": 0.032,
+ "Q04": 0.032,
+ "Q05": 0.05,
+ "Q11": 0.161,
+ "Q13": 0.119,
+ "Q14": 0.051,
+ "Q15": 0.114
+ }
+ },
+ {
+ "id": "postgres",
+ "name": "PostgreSQL",
+ "version": "16.13",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 31.171,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 0.085,
+ "Q03": 0.029,
+ "Q04": 0.029,
+ "Q05": 0.157,
+ "Q11": 1.688,
+ "Q13": 14.678,
+ "Q14": 0.496,
+ "Q15": 14.009
+ }
+ },
+ {
+ "id": "duckdb",
+ "name": "DuckDB",
+ "version": "1.5.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 3.777,
+ "queriesCompleted": 8,
+ "queriesTotal": 8,
+ "perQuery": {
+ "Q01": 0.007,
+ "Q03": 0.002,
+ "Q04": 0.01,
+ "Q05": 2.666,
+ "Q11": 0.176,
+ "Q13": 0.382,
+ "Q14": 0.167,
+ "Q15": 0.367
+ }
+ }
+ ]
+ },
+ {
+ "id": "analytics",
+ "name": "Analytics Rollups",
+ "scale": "6 queries",
+ "queries": [
+ "Q02",
+ "Q06",
+ "Q09",
+ "Q18",
+ "Q19",
+ "Q20"
+ ],
+ "products": [
+ {
+ "id": "doris",
+ "name": "Apache Doris",
+ "version": "5.7.99",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 0.387,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 0.056,
+ "Q06": 0.053,
+ "Q09": 0.055,
+ "Q18": 0.072,
+ "Q19": 0.073,
+ "Q20": 0.078
+ }
+ },
+ {
+ "id": "clickhouse",
+ "name": "ClickHouse",
+ "version": "26.2.13.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 1.929,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 0.233,
+ "Q06": 0.236,
+ "Q09": 0.248,
+ "Q18": 0.256,
+ "Q19": 0.718,
+ "Q20": 0.238
+ }
+ },
+ {
+ "id": "elastic",
+ "name": "Elasticsearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 5.288,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 0.164,
+ "Q06": 0.064,
+ "Q09": 0.037,
+ "Q18": 2.196,
+ "Q19": 2.769,
+ "Q20": 0.058
+ }
+ },
+ {
+ "id": "opensearch",
+ "name": "OpenSearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 6.447,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 2.696,
+ "Q06": 0.065,
+ "Q09": 0.048,
+ "Q18": 1.266,
+ "Q19": 2.26,
+ "Q20": 0.112
+ }
+ },
+ {
+ "id": "postgres",
+ "name": "PostgreSQL",
+ "version": "16.13",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 53.224,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 0.548,
+ "Q06": 0.228,
+ "Q09": 0.169,
+ "Q18": 2.393,
+ "Q19": 45.263,
+ "Q20": 4.623
+ }
+ },
+ {
+ "id": "duckdb",
+ "name": "DuckDB",
+ "version": "1.5.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 107.25,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q02": 0.014,
+ "Q06": 0.011,
+ "Q09": 0.006,
+ "Q18": 20.775,
+ "Q19": 44.467,
+ "Q20": 41.977
+ }
+ }
+ ]
+ },
+ {
+ "id": "semi",
+ "name": "Semi-Structured Payload",
+ "scale": "6 queries",
+ "queries": [
+ "Q07",
+ "Q08",
+ "Q10",
+ "Q12",
+ "Q16",
+ "Q17"
+ ],
+ "products": [
+ {
+ "id": "doris",
+ "name": "Apache Doris",
+ "version": "5.7.99",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 1.585,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 1.27,
+ "Q08": 0.124,
+ "Q10": 0.066,
+ "Q12": 0.071,
+ "Q16": 0.035,
+ "Q17": 0.019
+ }
+ },
+ {
+ "id": "clickhouse",
+ "name": "ClickHouse",
+ "version": "26.2.13.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 1.839,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 0.51,
+ "Q08": 0.369,
+ "Q10": 0.231,
+ "Q12": 0.25,
+ "Q16": 0.246,
+ "Q17": 0.233
+ }
+ },
+ {
+ "id": "elastic",
+ "name": "Elasticsearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 0.281,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 0.052,
+ "Q08": 0.059,
+ "Q10": 0.049,
+ "Q12": 0.054,
+ "Q16": 0.039,
+ "Q17": 0.028
+ }
+ },
+ {
+ "id": "opensearch",
+ "name": "OpenSearch",
+ "version": "9.3.0",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 0.338,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 0.075,
+ "Q08": 0.072,
+ "Q10": 0.038,
+ "Q12": 0.072,
+ "Q16": 0.049,
+ "Q17": 0.032
+ }
+ },
+ {
+ "id": "postgres",
+ "name": "PostgreSQL",
+ "version": "16.13",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 19.231,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 3.155,
+ "Q08": 9.465,
+ "Q10": 1.031,
+ "Q12": 4.793,
+ "Q16": 0.403,
+ "Q17": 0.384
+ }
+ },
+ {
+ "id": "duckdb",
+ "name": "DuckDB",
+ "version": "1.5.2",
+ "machine": "32C (AWS.m6i.8xlarge)",
+ "clusterSize": 1,
+ "totalRuntime": 173.655,
+ "queriesCompleted": 6,
+ "queriesTotal": 6,
+ "perQuery": {
+ "Q07": 23.307,
+ "Q08": 0.27,
+ "Q10": 42.608,
+ "Q12": 63.286,
+ "Q16": 23.583,
+ "Q17": 20.601
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]