diff --git a/Cargo.lock b/Cargo.lock index 8e547e4..394be9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1128,11 +1128,13 @@ dependencies = [ "cipherstash-client", "criterion", "criterion-table", + "eql-bindings", "fake 4.4.0", "hex", "hex-literal", "ore-rs 0.7.0", "rand 0.8.6", + "rust_decimal", "serde", "serde_json", "sqlx", @@ -1297,6 +1299,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + [[package]] name = "either" version = "1.15.0" @@ -1318,6 +1326,18 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "eql-bindings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a72499029ecc1eac95fafe70747479c49affd5565550339a7183223bca1c0259" +dependencies = [ + "schemars", + "serde", + "serde_json", + "ts-rs", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -3276,6 +3296,26 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "regex" version = "1.12.3" @@ -3638,6 +3678,31 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "schemars" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +dependencies = [ + "dyn-clone", + "ref-cast", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.117", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -3742,6 +3807,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "serde_json" version = "1.0.149" @@ -4288,6 +4364,15 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "terminal_size" version = "0.4.4" @@ -4684,6 +4769,29 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "ts-rs" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e640d9b0964e9d39df633548591090ab92f7a4567bc31d3891af23471a3365c6" +dependencies = [ + "lazy_static", + "thiserror 2.0.18", + "ts-rs-macros", +] + +[[package]] +name = "ts-rs-macros" +version = "10.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e9d8656589772eeec2cf7a8264d9cda40fb28b9bc53118ceb9e8c07f8f38730" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "termcolor", +] + [[package]] name = "typenum" version = "1.20.0" diff --git a/Cargo.toml b/Cargo.toml index 9108765..9797880 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,9 +21,19 @@ rand = "0.8.5" # EQL v2 wire payloads (`k`/`c`/`v`/`i`) byte-identical to the # 0.34.1-alpha.9 pre-release that EQL 2.3.0 targets — the eql wire formats # module is unchanged between the two — so the EQL release pin in -# mise.toml's setup-db task stays at eql-2.3.0. Bump both together. +# mise.toml's setup-db task stays at eql-2.3.0. 0.38.1 adds scalar +# OPE-CLLW `op` term emission via `Index::new_ope()` (CIP-3280), which the +# `_ord_ope` benches require (real OPE ciphertexts). Bump both together. cipherstash-client = { version = "=0.38.1", features = ["tokio"] } stack-profile = "=0.38.1" +# EQL v2.3 -> v3 payload conversion (the supported migration path; the +# converter's docs name these benches as a consumer). eql-bindings::from_v2 +# reshapes the client's v2.3 payloads into the eql_v3 domain payloads. +# Published on crates.io as of 0.4.2 (was a git dep on the eql_v3 branch). +eql-bindings = "=0.4.2" +# Plaintext::Decimal takes rust_decimal::Decimal, which cipherstash-client +# does not re-export — used by the scalar_smoke_v3 numeric-family coverage. +rust_decimal = "1" anyhow = "1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" @@ -76,6 +86,38 @@ path = "src/bin/encrypt_category.rs" name = "encrypt_combo" path = "src/bin/encrypt_combo.rs" +[[bin]] +name = "encrypt_string_v3" +path = "src/bin/encrypt_string_v3.rs" + +[[bin]] +name = "encrypt_int_v3" +path = "src/bin/encrypt_int_v3.rs" + +[[bin]] +name = "encrypt_int_ope_v3" +path = "src/bin/encrypt_int_ope_v3.rs" + +[[bin]] +name = "encrypt_category_v3" +path = "src/bin/encrypt_category_v3.rs" + +[[bin]] +name = "encrypt_combo_v3" +path = "src/bin/encrypt_combo_v3.rs" + +[[bin]] +name = "encrypt_ste_vec_small_v3" +path = "src/bin/encrypt_ste_vec_small_v3.rs" + +[[bin]] +name = "encrypt_scalar_smoke_v3" +path = "src/bin/encrypt_scalar_smoke_v3.rs" + +[[bin]] +name = "decrypt_probe" +path = "src/bin/decrypt_probe.rs" + [[bench]] name = "ore" harness = false @@ -98,4 +140,40 @@ harness = false [[bench]] name = "combo" +harness = false + +[[bench]] +name = "exact_v3" +harness = false + +[[bench]] +name = "ore_v3" +harness = false + +[[bench]] +name = "group_by_v3" +harness = false + +[[bench]] +name = "match_v3" +harness = false + +[[bench]] +name = "ope_v3" +harness = false + +[[bench]] +name = "combo_v3" +harness = false + +[[bench]] +name = "json_v3" +harness = false + +[[bench]] +name = "scalar_smoke_v3" +harness = false + +[[bench]] +name = "plaintext_v3" harness = false \ No newline at end of file diff --git a/README.md b/README.md index 9a6c38e..ca0ef56 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,53 @@ Performance benchmarks for CipherStash's searchable encryption operations using The latest benchmark results are available in the [`report/`](report/) directory: -- **[Benchmark Report](report/BENCHMARK_REPORT.md)** - Comprehensive report with performance tables and charts -- Includes ingest throughput, query performance, SQL statements, and index configurations -- Performance indicators (⚠️) highlight queries exceeding 100ms +- **[Benchmark Report](report/BENCHMARK_REPORT.md)** - the main report (EQL v3): ingest throughput, per-family query performance, SQL/plans/index configs, plus comparison sections vs EQL 2.3 and vs plaintext PostgreSQL +- **[EQL v3 vs v2 Comparison](report/V3_COMPARISON.md)** - full regression tables, index-engagement audit, and docs/marketing charts (`report/v3/`) +- **[EQL 2.3 report archive](report/v2/BENCHMARK_REPORT.md)** - the frozen v2 baseline report + +## 🆕 EQL v3 benches + +The `*_v3` benches target the EQL v3 release (domain-specific types — +`public.text_search`, `public.integer_ord`, … — replacing the single +`eql_v2_encrypted` composite). They live alongside the v2 benches; the +committed v2 results are the regression baseline and are never overwritten +(v3 results land in `results/query/v3/` and `results/ingest/v3/`). + +```bash +# Install the v3 bundle alongside v2. Defaults to the pinned release +# download (eql-3.0.0-alpha.3); override with EQL_V3_VERSION=, +# EQL_V3_SQL=, or EQL_V3_DIR=. +mise run setup-db-v3 + +# Populate all v3 tables at a tier +mise run prepare:v3:all 10000 + +# Query benches: exact | match | ore | ope | group_by | combo | json | plaintext | smoke +mise run bench:v3:query:all 10000 # arg = max tier (10000 | 100000 | 1000000) + +# Ingest benches (hyperfine, same tiers as v2) +mise run bench:v3:ingest + +# Terminal overviews (v3 siblings of report / report:slow / report:ingest, +# which scan only the v2 baseline results) +mise run report:v3 +mise run report:v3:slow [ms] +mise run report:v3:ingest + +# v2-vs-v3 side-by-side on the CLI (medians + delta per scenario/tier) +mise run report:v3-compare + +# Full comparison artifacts: report/V3_COMPARISON.md + report/v3/ charts +mise run report:build:v3-compare + +# Main report (EQL v3 numbers + v2/plaintext comparison sections) +mise run report:build +``` + +v3 payloads are produced by converting the pinned cipherstash-client's v2.3 +output through `eql-bindings::from_v2` (the supported migration path — see +`src/v3.rs` for the details and caveats). The `ope` benches use real +CLLW-OPE `op` terms emitted by cipherstash-client 0.38.1 (`Index::new_ope()`). ### Other benchmarks diff --git a/benches/combo_v3.rs b/benches/combo_v3.rs new file mode 100644 index 0000000..dfa4694 --- /dev/null +++ b/benches/combo_v3.rs @@ -0,0 +1,153 @@ +//! EQL v3 sibling of `benches/combo.rs` — composite-predicate scenarios over +//! `combo_encrypted_v3_` (`name` text_search, `age` integer_ord, +//! `category` text_eq). +//! +//! v2's `name LIKE $1` becomes `name @> $1` (v3 has no LIKE — identical +//! bloom-containment semantics); the extractor references move to the v3 +//! functions (`eql_v3.ord_term(age)`, `eql_v3.eq_term(category)`). Scenario +//! ids are unchanged. + +use cipherstash_client::{ + eql::Identifier, + schema::{column::Index, ColumnConfig, ColumnType}, +}; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use dbbenches::{ + bench_assert, init_scoped_cipher, init_tracing, + v3::{encrypt_stored_v3, V3EncryptedQuery}, + write_metadata_file_in, ScenarioMetadata, +}; +use sqlx::postgres::PgPoolOptions; +use sqlx::types::Json; +use std::sync::Arc; +use tokio::runtime::Runtime; + +static QUERY_TEMPLATES: &[(&str, &str)] = &[ + ( + "SELECT id FROM {TABLE} \ + WHERE name @> $1 \ + ORDER BY eql_v3.ord_term(age) LIMIT 10", + "bloom_ore_order_limit", + ), + ( + "SELECT eql_v3.eq_term(category), count(*) FROM {TABLE} \ + WHERE name @> $1 \ + GROUP BY 1", + "filtered_group_by", + ), + ( + "SELECT eql_v3.eq_term(category), count(*) FROM {TABLE} \ + WHERE name @> $1 \ + GROUP BY 1 ORDER BY count(*) DESC LIMIT 10", + "top_n_filtered_group_by", + ), +]; + +fn criterion_benchmark(c: &mut Criterion) { + init_tracing(); + let rt = Runtime::new().unwrap(); + + let target_rows = std::env::var("TARGET_ROWS").unwrap_or_else(|_| "unknown".to_string()); + let table_suffix = match target_rows.as_str() { + "10000" | "100000" | "1000000" | "10000000" => format!("_{}", target_rows), + _ => String::new(), + }; + let table_name = format!("combo_encrypted_v3{}", table_suffix); + + let (pool, cipher) = rt.block_on(async { + let database_url = + std::env::var("DATABASE_URL").expect("DATABASE_URL environment variable must be set"); + let pool = PgPoolOptions::new() + .max_connections(5) + .connect(&database_url) + .await + .expect("Failed to connect to database"); + let cipher = init_scoped_cipher() + .await + .expect("Failed to initialize ScopedCipher"); + (pool, cipher) + }); + + // Same pattern as the v2 bench (and match_v3). The needle payload + // carries hm+ob+bf of "Bob"; only the bloom term participates in `@>`. + let pattern = "Bob"; + let name_config = ColumnConfig::build("name") + .casts_as(ColumnType::Text) + .add_index(Index::new_unique()) + .add_index(Index::new_match()) + .add_index(Index::new_ore()); + let name_ident = Identifier::new(&table_name, "name"); + + let queries: Vec = rt.block_on(async { + let mut queries = Vec::with_capacity(QUERY_TEMPLATES.len()); + for (query_template, _) in QUERY_TEMPLATES { + let query_str = query_template.replace("{TABLE}", &table_name); + let param = encrypt_stored_v3( + Arc::clone(&cipher), + &name_config, + &name_ident, + pattern.to_string(), + "text_search", + ) + .await + .expect("failed to encrypt+convert name pattern"); + queries.push(V3EncryptedQuery::new(param, query_str, Arc::clone(&cipher))); + } + queries + }); + + // Combo result shapes don't match V3EncryptedQuery::execute's typed + // tuple, so metadata row counts and the iter loop use raw sqlx. + let metadata = rt.block_on(async { + let mut out = Vec::with_capacity(queries.len()); + for (i, query) in queries.iter().enumerate() { + let (_, scenario) = QUERY_TEMPLATES[i]; + let bench_id = format!("COMBO/combo/{}/{}", scenario, target_rows); + let explain = query.explain(&pool).await.expect("EXPLAIN failed"); + let indexes_used = dbbenches::extract_indexes_used(&explain); + let rows = sqlx::query(&query.statement) + .bind(Json(&query.param)) + .fetch_all(&pool) + .await + .expect("execute for row-count failed"); + out.push(ScenarioMetadata { + id: bench_id, + query: query.statement.clone(), + parameters: vec![query.parameter_json().expect("serialise parameter")], + explain, + indexes_used, + rows_returned: rows.len() as u64, + }); + } + out + }); + write_metadata_file_in("results/query/v3", "combo", &target_rows, metadata) + .expect("failed to write bench metadata sidecar"); + + let mut group = c.benchmark_group("COMBO"); + group.sample_size(10); + + for (i, query) in queries.into_iter().enumerate() { + let (_, scenario) = QUERY_TEMPLATES[i]; + let exec_id = format!("COMBO/combo/{}/{}", scenario, target_rows); + + let exec_id_inner = exec_id.clone(); + group.bench_function(format!("combo/{}/{}", scenario, target_rows), |b| { + b.to_async(&rt).iter(|| async { + let rows = bench_assert( + sqlx::query(&query.statement) + .bind(Json(&query.param)) + .fetch_all(&pool) + .await, + &exec_id_inner, + ); + black_box(rows.len()); + }) + }); + } + + group.finish(); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/benches/exact_v3.rs b/benches/exact_v3.rs new file mode 100644 index 0000000..8369c0d --- /dev/null +++ b/benches/exact_v3.rs @@ -0,0 +1,157 @@ +//! EQL v3 sibling of `benches/exact.rs` — equality lookups against +//! `string_encrypted_v3_` (`public.text_search`). +//! +//! Scenario ids are kept IDENTICAL to the v2 bench (`eql_cast`, `eql_hash`) +//! so the comparison report joins v2 vs v3 by (group, scenario, tier); the +//! version dimension is the results directory (`results/query/v3/`). +//! +//! v3 differences worth knowing when reading numbers: +//! * The bound parameter is a STORED-shape v3 payload (encrypt Store + +//! from_v2) — no v3 scalar query wire shape exists. The `=` operator's +//! `(text_search, jsonb)` overload casts it in-plan. +//! * `eql_hash` keeps its id but the index is a functional BTREE on +//! `eql_v3.eq_term(value)` (v2 used hash — see the index DDL comments). + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use dbbenches::{ + bench_assert, + v3::{encrypt_stored_v3, sample_plaintext_string_v3, V3EncryptedQuery}, + init_scoped_cipher, init_tracing, write_metadata_file_in, ScenarioMetadata, +}; +use cipherstash_client::{ + eql::Identifier, + schema::{column::Index, ColumnConfig, ColumnType}, +}; +use sqlx::postgres::PgPoolOptions; +use std::sync::Arc; +use tokio::runtime::Runtime; + +static QUERY_TEMPLATES: &[(&str, &str)] = &[ + ( + "SELECT id, value FROM {TABLE} WHERE value = $1 LIMIT 1", + "eql_cast", + ), + ( + "SELECT id, value FROM {TABLE} WHERE eql_v3.eq_term(value) = eql_v3.eq_term($1::public.text_search) LIMIT 1", + "eql_hash", + ), +]; + +fn criterion_benchmark(c: &mut Criterion) { + init_tracing(); + let rt = Runtime::new().unwrap(); + + let target_rows = std::env::var("TARGET_ROWS").unwrap_or_else(|_| "unknown".to_string()); + let table_suffix = match target_rows.as_str() { + "10000" | "100000" | "1000000" | "10000000" => format!("_{}", target_rows), + _ => String::new(), + }; + let table_name = format!("string_encrypted_v3{}", table_suffix); + + let (pool, cipher) = rt.block_on(async { + let database_url = + std::env::var("DATABASE_URL").expect("DATABASE_URL environment variable must be set"); + let pool = PgPoolOptions::new() + .max_connections(5) + .connect(&database_url) + .await + .expect("Failed to connect to database"); + let cipher = init_scoped_cipher() + .await + .expect("Failed to initialize ScopedCipher"); + (pool, cipher) + }); + + // Sample a real row so the equality scenarios measure index hit + 1-row + // return, not a 0-rows early exit (same rationale as the v2 bench). + let search_term: String = rt.block_on(async { + sample_plaintext_string_v3(&pool, Arc::clone(&cipher), &table_name) + .await + .expect("failed to sample plaintext from table — is it populated?") + }); + eprintln!( + "exact_v3 bench: using sampled search term `{}` from `{}`", + &search_term, &table_name + ); + + // The needle config must match the ingest config (unique+match+ore) so + // the converted payload satisfies text_search's required terms. + let column_config = ColumnConfig::build("value") + .casts_as(ColumnType::Text) + .add_index(Index::new_unique()) + .add_index(Index::new_match()) + .add_index(Index::new_ore()); + let identifier = Identifier::new(&table_name, "value"); + + let queries: Vec = rt.block_on(async { + let mut queries = Vec::with_capacity(QUERY_TEMPLATES.len()); + for (query_template, _) in QUERY_TEMPLATES { + let query_str = query_template.replace("{TABLE}", &table_name); + let param = encrypt_stored_v3( + Arc::clone(&cipher), + &column_config, + &identifier, + search_term.clone(), + "text_search", + ) + .await + .expect("failed to encrypt+convert query needle"); + queries.push(V3EncryptedQuery::new(param, query_str, Arc::clone(&cipher))); + } + queries + }); + + let metadata = rt.block_on(async { + let mut out = Vec::with_capacity(queries.len()); + for (i, query) in queries.iter().enumerate() { + let (_, scenario) = QUERY_TEMPLATES[i]; + let bench_id = format!("EXACT/exact/{}/{}", scenario, target_rows); + let (explain, indexes_used, rows_returned) = query + .capture_metadata(&pool) + .await + .expect("metadata capture failed"); + out.push(ScenarioMetadata { + id: bench_id, + query: query.statement.clone(), + parameters: vec![query.parameter_json().expect("serialise parameter")], + explain, + indexes_used, + rows_returned, + }); + } + out + }); + write_metadata_file_in("results/query/v3", "exact", &target_rows, metadata) + .expect("failed to write bench metadata sidecar"); + + let mut group = c.benchmark_group("EXACT"); + group.sample_size(10); + + for (i, query) in queries.into_iter().enumerate() { + let (_, scenario) = QUERY_TEMPLATES[i]; + let exec_id = format!("EXACT/exact/{}/{}", scenario, target_rows); + let decrypt_id = format!("EXACT/exact_decrypt/{}/{}", scenario, target_rows); + + let exec_id_inner = exec_id.clone(); + group.bench_function(format!("exact/{}/{}", scenario, target_rows), |b| { + b.to_async(&rt).iter(|| async { + let _: Vec<_> = bench_assert(query.execute(&pool).await, &exec_id_inner); + }) + }); + + let decrypt_id_inner = decrypt_id.clone(); + group.bench_function(format!("exact_decrypt/{}/{}", scenario, target_rows), |b| { + b.to_async(&rt).iter(|| async { + let _r: Vec = black_box(bench_assert( + query.execute_and_decrypt(&pool).await, + &decrypt_id_inner, + )); + }) + }); + } + + group.finish(); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/benches/group_by_v3.rs b/benches/group_by_v3.rs new file mode 100644 index 0000000..a52d8d4 --- /dev/null +++ b/benches/group_by_v3.rs @@ -0,0 +1,135 @@ +//! EQL v3 sibling of `benches/group_by.rs` — realistic-cardinality GROUP BY +//! against `category_encrypted_v3_` (`public.text_eq`). The plaintext +//! baselines run against the SAME `category_plaintext_` tables the v2 +//! bench uses (shared baseline — pure-SQL populated, version-independent). +//! +//! v2's `eql_v2.hmac_256(value)` group key becomes `eql_v3.eq_term(value)`; +//! scenario ids are unchanged. No bound parameters (grouping only), so the +//! scenarios run via raw sqlx exactly like the v2 bench. + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use dbbenches::{ + bench_assert, extract_indexes_used, init_tracing, write_metadata_file_in, ScenarioMetadata, +}; +use sqlx::postgres::PgPoolOptions; +use sqlx::types::Json; +use sqlx::Row; +use tokio::runtime::Runtime; + +// (sql_template, scenario_name, base_table_name) +static QUERY_TEMPLATES: &[(&str, &str, &str)] = &[ + ( + "SELECT count(*) FROM \ + (SELECT 1 FROM {TABLE} GROUP BY eql_v3.eq_term(value)) g", + "low_cardinality_groups_encrypted", + "category_encrypted_v3", + ), + ( + "SELECT count(*) FROM \ + (SELECT 1 FROM {TABLE} GROUP BY value) g", + "low_cardinality_groups_plaintext", + "category_plaintext", + ), + ( + "SELECT eql_v3.eq_term(value), count(*) FROM {TABLE} \ + GROUP BY 1 ORDER BY count(*) DESC LIMIT 10", + "top_n_groups_encrypted", + "category_encrypted_v3", + ), + ( + "SELECT value, count(*) FROM {TABLE} \ + GROUP BY 1 ORDER BY count(*) DESC LIMIT 10", + "top_n_groups_plaintext", + "category_plaintext", + ), +]; + +fn criterion_benchmark(c: &mut Criterion) { + init_tracing(); + let rt = Runtime::new().unwrap(); + + let target_rows = std::env::var("TARGET_ROWS").unwrap_or_else(|_| "unknown".to_string()); + let table_suffix = match target_rows.as_str() { + "10000" | "100000" | "1000000" | "10000000" => format!("_{}", target_rows), + _ => String::new(), + }; + + let pool = rt.block_on(async { + let database_url = + std::env::var("DATABASE_URL").expect("DATABASE_URL environment variable must be set"); + PgPoolOptions::new() + .max_connections(5) + .connect(&database_url) + .await + .expect("Failed to connect to database") + }); + + let scenarios: Vec<(String, String)> = QUERY_TEMPLATES + .iter() + .map(|(query_template, scenario, base_table)| { + let table_name = format!("{}{}", base_table, table_suffix); + let query_str = query_template.replace("{TABLE}", &table_name); + let bench_id = format!("GROUP_BY/group_by/{}/{}", scenario, target_rows); + (bench_id, query_str) + }) + .collect(); + + let metadata = rt.block_on(async { + let mut out = Vec::with_capacity(scenarios.len()); + for (bench_id, query_str) in &scenarios { + let explain_sql = format!("EXPLAIN (FORMAT JSON) {}", query_str); + let plan: (Json,) = sqlx::query_as(&explain_sql) + .fetch_one(&pool) + .await + .expect("EXPLAIN failed for bench scenario"); + let explain = plan.0 .0; + let indexes_used = extract_indexes_used(&explain); + let rows = sqlx::query(query_str) + .fetch_all(&pool) + .await + .expect("execute for row-count failed"); + let rows_returned = rows.len() as u64; + out.push(ScenarioMetadata { + id: bench_id.clone(), + query: query_str.clone(), + parameters: Vec::new(), + explain, + indexes_used, + rows_returned, + }); + } + out + }); + + write_metadata_file_in("results/query/v3", "group_by", &target_rows, metadata) + .expect("failed to write bench metadata sidecar"); + + let mut group = c.benchmark_group("GROUP_BY"); + group.sample_size(10); + + for (bench_id, query_str) in scenarios { + let function_name = bench_id + .strip_prefix("GROUP_BY/") + .expect("bench_id missing GROUP_BY/ prefix") + .to_string(); + let scenario_id = bench_id.clone(); + group.bench_function(function_name, |b| { + b.to_async(&rt).iter(|| async { + let rows = bench_assert( + sqlx::query(&query_str).fetch_all(&pool).await, + &scenario_id, + ); + if rows.len() == 1 { + black_box(rows[0].get::(0)); + } else { + black_box(rows.iter().map(|r| r.get::(1)).sum::()); + } + }) + }); + } + + group.finish(); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/benches/json_v3.rs b/benches/json_v3.rs new file mode 100644 index 0000000..e2f261c --- /dev/null +++ b/benches/json_v3.rs @@ -0,0 +1,590 @@ +//! EQL v3 sibling of `benches/json.rs` — encrypted-JSONB (SteVec) queries +//! against `json_ste_vec_small_encrypted_v3_` (`public.json`). +//! +//! Every scenario goes through the **named EQL v3 JSON functions** — the +//! surface a real EQL caller (or the ORM/proxy that rewrites their query) +//! emits — rather than casting the column to raw `jsonb` and using native +//! `@>` / `->`. Scenario ids match the v2 bench so the v2↔v3 comparison +//! joins by id. The SQL surface maps as: +//! +//! contains/functional +//! v2: eql_v2.jsonb_array(value) @> eql_v2.jsonb_array($1::…) +//! v3: eql_v3.jsonb_contains(value, $1::jsonb) +//! `eql_v3.jsonb_contains(a, b)` inlines to +//! `eql_v3.jsonb_array(a) @> eql_v3.jsonb_array(b)`, so it engages the +//! static `GIN (eql_v3.jsonb_array(value))` index (the documented +//! whole-document containment recipe). Needle = the sampled row's whole +//! document, normalised to `s` + term entries. +//! +//! field_eq/bare eql_v3.jsonb_path_query_first(value, '') = $1::jsonb::public.jsonb_entry +//! The "natural" caller form: `jsonb_path_query_first` returns the +//! `public.jsonb_entry` leaf and `=` on that domain inlines to +//! `eql_v3.eq_term(a) = eql_v3.eq_term(b)` — structurally identical to +//! field_eq/functional, so it engages the same per-selector functional +//! index built at startup. +//! +//! field_eq/extractor eql_v3.jsonb_contains(value, $1::jsonb) (single-entry needle) +//! Same containment function/index as contains/functional, but the +//! needle addresses a single selector: `{"sv":[{"s":…,"hm":…}]}`. +//! +//! field_eq/functional eql_v3.eq_term(eql_v3.jsonb_path_query_first(value, '')) +//! = eql_v3.eq_term($1::jsonb::public.jsonb_entry) +//! The explicit per-selector functional form. +//! +//! The field_eq needles cast `$1::jsonb::public.jsonb_entry`, not +//! `$1::public.jsonb_entry` — the `::jsonb` intermediate keeps the bound +//! parameter's type the built-in `jsonb`; a direct bind-cast to the domain +//! makes sqlx try to resolve `public.jsonb_entry` as the *parameter* type and +//! fail with `type "public.jsonb_entry" does not exist`. Don't drop it. +//! +//! field_order/functional +//! ORDER BY eql_v3.ore_cllw(eql_v3.jsonb_path_query_first(value, '')) LIMIT 10 +//! `eql_v3.ore_cllw` returns `eql_v3_internal.ore_cllw`, whose +//! DEFAULT-FOR-TYPE btree opclass turns `ORDER BY … LIMIT` into an index +//! scan on the per-selector functional index. +//! +//! field_gt/functional — the encrypted equivalent of `x -> 'y' > 10` +//! WHERE eql_v3.jsonb_path_query_first(value, '') > $1::jsonb::public.jsonb_entry LIMIT 10 +//! The `>` operator on public.jsonb_entry inlines to +//! `eql_v3.ore_cllw(a) > eql_v3.ore_cllw(b)` (a CLLW-ORE comparison), so +//! the predicate reuses the same `field_order_idx` — no extra index. The +//! threshold `$1` is a sampled oc leaf; an unselective bound may still +//! seq-scan (mirrors the scalar ORE `range_gt` scenarios). +//! +//! Field access is always `eql_v3.jsonb_path_query_first(value, '')` +//! (the scalar EQL path-query — `jsonb_path_query` is SETOF and can't sit in +//! an index expression), never a raw `value -> ''`. The selector is the +//! sv element's deterministic `s` hash, sampled at startup. +//! +//! Per-selector functional indexes (eq_term / ore_cllw over +//! `jsonb_path_query_first(value, sel)`) are built at startup once the +//! selector is sampled, mirroring the v2 bench's create_field_indexes. + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use dbbenches::{ + bench_assert, extract_indexes_used, init_tracing, write_metadata_file_in, ScenarioMetadata, +}; +use serde_json::Value as JsonValue; +use sqlx::postgres::PgPoolOptions; +use sqlx::types::Json; +use sqlx::Row; +use tokio::runtime::Runtime; + +#[derive(Debug)] +struct Needles { + /// `{"sv":[{"s":..,"hm"|"oc":..}, ...]}` — the whole sampled document + /// normalized to the containment-needle shape (drives contains/functional). + document_query: String, + hm_pick: Option, + ore_pick: Option, +} + +#[derive(Debug)] +struct HmPick { + selector: String, + /// `eql_v3.jsonb_path_query_first(value, '')::jsonb` of the + /// sampled row — the merged leaf entry, castable to public.jsonb_entry. + /// Drives the field_eq/bare + field_eq/functional needles. + sample_field_value: JsonValue, + /// Single-entry containment needle for field_eq/extractor. + hmac_term: String, +} + +#[derive(Debug)] +struct OrePick { + selector: String, + /// `eql_v3.jsonb_path_query_first(value, '')::jsonb` of a sampled + /// row — an oc-bearing leaf used as the range threshold for field_gt + /// (`field > this`), castable to public.jsonb_entry. + threshold: JsonValue, +} + +async fn sample_needles(pool: &sqlx::PgPool, table: &str) -> Needles { + // v3 payloads are the public.json jsonb domain — cast to raw jsonb for + // *sampling* (setup, not a measured query) and walk `-> 'sv'` directly. + let rows = sqlx::query(&format!( + "SELECT elem ->> 's' AS sel, + elem ->> 'hm' AS hmac, + elem AS sv_elem + FROM ( + SELECT value::jsonb -> 'sv' AS sv_array + FROM {table} + LIMIT 1 + ) source, + LATERAL jsonb_array_elements(sv_array) WITH ORDINALITY AS j(elem, ord) + ORDER BY ord" + )) + .fetch_all(pool) + .await + .expect("query for sv elements failed"); + + if rows.is_empty() { + panic!("table `{table}` is empty"); + } + + // Normalize every entry to `s` + one term for the whole-document + // containment needle (what eql_v3.jsonb_array reduces the column to). + let mut query_entries: Vec = Vec::with_capacity(rows.len()); + let mut hm_pick: Option = None; + let mut ore_pick: Option = None; + + for row in &rows { + let sel: String = row.get("sel"); + let hmac: Option = row.get("hmac"); + let sv_elem: Json = row.get("sv_elem"); + let obj = sv_elem.0.as_object().expect("sv element is an object"); + + if let Some(h) = obj.get("hm") { + query_entries.push(serde_json::json!({"s": sel, "hm": h})); + } else if let Some(oc) = obj.get("oc") { + query_entries.push(serde_json::json!({"s": sel, "oc": oc})); + } + + if hm_pick.is_none() { + if let Some(h) = hmac.as_deref() { + // Source the leaf needle through the same EQL path-query the + // measured queries use, so needle and column leaf agree + // byte-for-byte under eq_term (guarantees ≥1 match). + let field_row = sqlx::query(&format!( + "SELECT eql_v3.jsonb_path_query_first(value::jsonb, '{sel}')::jsonb + AS sample_field_value + FROM {table} + LIMIT 1" + )) + .fetch_one(pool) + .await + .expect("query for hm sample field value failed"); + let sample_field_value: Json = field_row.get("sample_field_value"); + hm_pick = Some(HmPick { + selector: sel.clone(), + sample_field_value: sample_field_value.0, + hmac_term: format!(r#"{{"sv":[{{"s":"{}","hm":"{}"}}]}}"#, sel, h), + }); + } + } + + if ore_pick.is_none() && obj.contains_key("oc") { + // Sample this row's oc leaf through the same EQL path-query the + // measured queries use, as the field_gt range threshold. + let field_row = sqlx::query(&format!( + "SELECT eql_v3.jsonb_path_query_first(value::jsonb, '{sel}')::jsonb + AS threshold + FROM {table} + LIMIT 1" + )) + .fetch_one(pool) + .await + .expect("query for ore threshold value failed"); + let threshold: Json = field_row.get("threshold"); + ore_pick = Some(OrePick { + selector: sel.clone(), + threshold: threshold.0, + }); + } + } + + Needles { + document_query: serde_json::to_string(&serde_json::json!({"sv": query_entries})) + .expect("serialise document query needle"), + hm_pick, + ore_pick, + } +} + +/// Build per-selector functional indexes (selector known only after +/// sampling). btree for both — see the v2 json bench for the hash-vs-btree +/// build-cost rationale. Both index the EQL path-query expression +/// `eql_v3.jsonb_path_query_first(value, '')` so the field_eq/field_order +/// queries (which call the same function) match. +async fn create_field_indexes(pool: &sqlx::PgPool, table: &str, needles: &Needles) { + eprintln!("json_v3 bench: building per-selector functional indexes..."); + + if let Some(p) = needles.hm_pick.as_ref() { + sqlx::query(&format!("DROP INDEX IF EXISTS {table}_field_eq_idx")) + .execute(pool) + .await + .expect("drop stale field_eq index"); + sqlx::query(&format!( + "CREATE INDEX {table}_field_eq_idx ON {table} \ + USING btree (eql_v3.eq_term(eql_v3.jsonb_path_query_first(value, '{}')))", + p.selector + )) + .execute(pool) + .await + .expect("create field_eq functional index"); + } + + if let Some(p) = needles.ore_pick.as_ref() { + sqlx::query(&format!("DROP INDEX IF EXISTS {table}_field_order_idx")) + .execute(pool) + .await + .expect("drop stale field_order index"); + sqlx::query(&format!( + "CREATE INDEX {table}_field_order_idx ON {table} \ + USING btree (eql_v3.ore_cllw(eql_v3.jsonb_path_query_first(value, '{}')))", + p.selector + )) + .execute(pool) + .await + .expect("create field_order functional index"); + } + + sqlx::query(&format!("ANALYZE {table}")) + .execute(pool) + .await + .expect("ANALYZE after index creation"); +} + +fn criterion_benchmark(c: &mut Criterion) { + init_tracing(); + let rt = Runtime::new().unwrap(); + + let target_rows = std::env::var("TARGET_ROWS").unwrap_or_else(|_| "unknown".to_string()); + let table_suffix = match target_rows.as_str() { + "10000" | "100000" | "1000000" | "10000000" => format!("_{}", target_rows), + _ => String::new(), + }; + let table_name = format!("json_ste_vec_small_encrypted_v3{}", table_suffix); + + let (pool, needles) = rt.block_on(async { + let database_url = + std::env::var("DATABASE_URL").expect("DATABASE_URL environment variable must be set"); + let pool = PgPoolOptions::new() + .max_connections(5) + .connect(&database_url) + .await + .expect("Failed to connect to database"); + + let needles = sample_needles(&pool, &table_name).await; + eprintln!( + "json_v3 bench picked from `{}` — hm: {} | oc: {}", + &table_name, + needles + .hm_pick + .as_ref() + .map(|p| p.selector.as_str()) + .unwrap_or(""), + needles + .ore_pick + .as_ref() + .map(|p| p.selector.as_str()) + .unwrap_or(""), + ); + + create_field_indexes(&pool, &table_name, &needles).await; + + (pool, needles) + }); + + let hm_field_value_json = needles + .hm_pick + .as_ref() + .map(|p| serde_json::to_string(&p.sample_field_value).expect("serialise hm field value")); + + // --- Query strings --- + // Every predicate is a named EQL v3 JSON function. `value` (public.json) + // coerces to the functions' `jsonb` parameter via the domain's base type. + + let q_contains_functional = format!( + "SELECT id FROM {table_name} \ + WHERE eql_v3.jsonb_contains(value, $1::jsonb) LIMIT 10" + ); + + let q_field_eq_bare = needles.hm_pick.as_ref().map(|p| { + let selector = &p.selector; + format!( + "SELECT id FROM {table_name} \ + WHERE eql_v3.jsonb_path_query_first(value, '{selector}') \ + = $1::jsonb::public.jsonb_entry LIMIT 10" + ) + }); + + let q_field_eq_extractor = needles.hm_pick.as_ref().map(|_| { + format!( + "SELECT id FROM {table_name} \ + WHERE eql_v3.jsonb_contains(value, $1::jsonb) LIMIT 10" + ) + }); + + let q_field_eq_functional = needles.hm_pick.as_ref().map(|p| { + let selector = &p.selector; + format!( + "SELECT id FROM {table_name} \ + WHERE eql_v3.eq_term(eql_v3.jsonb_path_query_first(value, '{selector}')) \ + = eql_v3.eq_term($1::jsonb::public.jsonb_entry) LIMIT 10" + ) + }); + + let q_field_order_functional = needles.ore_pick.as_ref().map(|p| { + let selector = &p.selector; + format!( + "SELECT id FROM {table_name} \ + ORDER BY eql_v3.ore_cllw(eql_v3.jsonb_path_query_first(value, '{selector}')) LIMIT 10" + ) + }); + + // Encrypted-JSON field range — the equivalent of `x -> 'y' > 10`. The + // `>` operator on public.jsonb_entry inlines to + // `eql_v3.ore_cllw(a) > eql_v3.ore_cllw(b)`, so the LHS matches the same + // `field_order_idx` (ore_cllw over jsonb_path_query_first) — no extra + // index. Threshold needle is a sampled oc leaf; the planner may still + // prefer a seq scan when the bound is unselective (see `indexes_used`). + let q_field_gt_functional = needles.ore_pick.as_ref().map(|p| { + let selector = &p.selector; + format!( + "SELECT id FROM {table_name} \ + WHERE eql_v3.jsonb_path_query_first(value, '{selector}') \ + > $1::jsonb::public.jsonb_entry LIMIT 10" + ) + }); + + let ore_threshold_json = needles + .ore_pick + .as_ref() + .map(|p| serde_json::to_string(&p.threshold).expect("serialise ore threshold")); + + // --- Metadata sidecar --- + + let has_hm = needles.hm_pick.is_some(); + let has_ore = needles.ore_pick.is_some(); + + let metadata = rt.block_on(async { + let mut out: Vec = Vec::with_capacity(6); + + async fn capture( + pool: &sqlx::PgPool, + id: String, + query: &str, + bind: Option<&str>, + ) -> ScenarioMetadata { + let explain_sql = format!("EXPLAIN (FORMAT JSON) {}", query); + let (Json(explain),): (Json,) = if let Some(b) = bind { + sqlx::query_as(&explain_sql) + .bind(b) + .fetch_one(pool) + .await + .expect("EXPLAIN failed") + } else { + sqlx::query_as(&explain_sql) + .fetch_one(pool) + .await + .expect("EXPLAIN failed") + }; + let indexes_used = extract_indexes_used(&explain); + + let rows: Vec = if let Some(b) = bind { + sqlx::query(query) + .bind(b) + .fetch_all(pool) + .await + .expect("row-count execute failed") + } else { + sqlx::query(query) + .fetch_all(pool) + .await + .expect("row-count execute failed") + }; + + let parameters = bind + .map(|b| vec![JsonValue::String(b.to_string())]) + .unwrap_or_default(); + + ScenarioMetadata { + id, + query: query.to_string(), + parameters, + explain, + indexes_used, + rows_returned: rows.len() as u64, + } + } + + out.push( + capture( + &pool, + format!("JSON/json/contains/functional/{}", target_rows), + &q_contains_functional, + Some(&needles.document_query), + ) + .await, + ); + + if let (Some(hm_pick), Some(q_bare), Some(q_extractor), Some(q_functional)) = ( + needles.hm_pick.as_ref(), + q_field_eq_bare.as_deref(), + q_field_eq_extractor.as_deref(), + q_field_eq_functional.as_deref(), + ) { + let hm_field = hm_field_value_json + .as_deref() + .expect("hm_field_value_json present when hm_pick is Some"); + + out.push( + capture( + &pool, + format!("JSON/json/field_eq/bare/{}", target_rows), + q_bare, + Some(hm_field), + ) + .await, + ); + out.push( + capture( + &pool, + format!("JSON/json/field_eq/extractor/{}", target_rows), + q_extractor, + Some(hm_pick.hmac_term.as_str()), + ) + .await, + ); + out.push( + capture( + &pool, + format!("JSON/json/field_eq/functional/{}", target_rows), + q_functional, + Some(hm_field), + ) + .await, + ); + } else { + eprintln!( + "json_v3 bench: skipping field_eq/* scenarios — no sv element on the \ + sampled row carries `hm`." + ); + } + + if let Some(q) = q_field_order_functional.as_deref() { + out.push( + capture( + &pool, + format!("JSON/json/field_order/functional/{}", target_rows), + q, + None, + ) + .await, + ); + } else { + eprintln!( + "json_v3 bench: skipping field_order/functional — no sv element on the \ + sampled row carries `oc`." + ); + } + + if let (Some(q), Some(threshold)) = + (q_field_gt_functional.as_deref(), ore_threshold_json.as_deref()) + { + out.push( + capture( + &pool, + format!("JSON/json/field_gt/functional/{}", target_rows), + q, + Some(threshold), + ) + .await, + ); + } + + out + }); + write_metadata_file_in("results/query/v3", "json", &target_rows, metadata) + .expect("failed to write bench metadata sidecar"); + + // --- Bench loop --- + + let mut group = c.benchmark_group("JSON"); + group.sample_size(10); + + { + let id = format!("JSON/json/contains/functional/{}", target_rows); + let q = q_contains_functional.clone(); + let needle = needles.document_query.clone(); + group.bench_function(format!("json/contains/functional/{}", target_rows), |b| { + b.to_async(&rt).iter(|| async { + let rows = + bench_assert(sqlx::query(&q).bind(&needle).fetch_all(&pool).await, &id); + black_box(rows.len()) + }) + }); + } + + if has_hm { + let hm_field = hm_field_value_json + .clone() + .expect("hm_field_value_json present when has_hm"); + let hmac_term = needles + .hm_pick + .as_ref() + .expect("hm_pick present when has_hm") + .hmac_term + .clone(); + + if let Some(q) = q_field_eq_bare.clone() { + let id = format!("JSON/json/field_eq/bare/{}", target_rows); + let needle = hm_field.clone(); + group.bench_function(format!("json/field_eq/bare/{}", target_rows), |b| { + b.to_async(&rt).iter(|| async { + let rows = + bench_assert(sqlx::query(&q).bind(&needle).fetch_all(&pool).await, &id); + black_box(rows.len()) + }) + }); + } + + if let Some(q) = q_field_eq_extractor.clone() { + let id = format!("JSON/json/field_eq/extractor/{}", target_rows); + let needle = hmac_term.clone(); + group.bench_function(format!("json/field_eq/extractor/{}", target_rows), |b| { + b.to_async(&rt).iter(|| async { + let rows = + bench_assert(sqlx::query(&q).bind(&needle).fetch_all(&pool).await, &id); + black_box(rows.len()) + }) + }); + } + + if let Some(q) = q_field_eq_functional.clone() { + let id = format!("JSON/json/field_eq/functional/{}", target_rows); + let needle = hm_field.clone(); + group.bench_function(format!("json/field_eq/functional/{}", target_rows), |b| { + b.to_async(&rt).iter(|| async { + let rows = + bench_assert(sqlx::query(&q).bind(&needle).fetch_all(&pool).await, &id); + black_box(rows.len()) + }) + }); + } + } + + if has_ore { + if let Some(q) = q_field_order_functional.clone() { + let id = format!("JSON/json/field_order/functional/{}", target_rows); + group.bench_function( + format!("json/field_order/functional/{}", target_rows), + |b| { + b.to_async(&rt).iter(|| async { + let rows = bench_assert(sqlx::query(&q).fetch_all(&pool).await, &id); + black_box(rows.len()) + }) + }, + ); + } + + if let (Some(q), Some(threshold)) = + (q_field_gt_functional.clone(), ore_threshold_json.clone()) + { + let id = format!("JSON/json/field_gt/functional/{}", target_rows); + group.bench_function(format!("json/field_gt/functional/{}", target_rows), |b| { + b.to_async(&rt).iter(|| async { + let rows = + bench_assert(sqlx::query(&q).bind(&threshold).fetch_all(&pool).await, &id); + black_box(rows.len()) + }) + }); + } + } + + group.finish(); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/benches/match_v3.rs b/benches/match_v3.rs new file mode 100644 index 0000000..aff0f4b --- /dev/null +++ b/benches/match_v3.rs @@ -0,0 +1,235 @@ +//! EQL v3 sibling of `benches/match.rs` — substring/pattern matching against +//! `string_encrypted_v3_` (`public.text_search`, bloom term). +//! +//! v3 has NO `~~`/LIKE operator: bloom matching is exposed as containment. +//! v2's `value LIKE $1` scenarios keep their ids but run `value @> $1` +//! (identical semantics — needle bloom bits contained in the value's bloom; +//! the report's semantics-changed map flags the SQL delta). +//! +//! **The index question.** v3 ships no GIN opclass; the static index DDL +//! creates `GIN (eql_v3.match_term(value))`, which relies on the term's +//! base type (`smallint[]`) resolving native `array_ops`. Whether the +//! planner ENGAGES it for the inlined `@>` is exactly what this bench +//! answers — check `indexes_used` in the metadata sidecar. At the 10k tier +//! the bench additionally runs every scenario with the GIN dropped +//! (`*_noindex` ids) to quantify what the index is worth; the index is +//! recreated afterwards. + +use cipherstash_client::{ + eql::Identifier, + schema::{column::Index, ColumnConfig, ColumnType}, +}; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use dbbenches::{ + bench_assert, init_scoped_cipher, init_tracing, + v3::{encrypt_stored_v3, V3EncryptedQuery}, + write_metadata_file_in, ScenarioMetadata, +}; +use sqlx::postgres::PgPoolOptions; +use std::sync::Arc; +use tokio::runtime::Runtime; + +static QUERY_TEMPLATES: &[(&str, &str, &str)] = &[ + ( + "SELECT id, value FROM {TABLE} WHERE value @> $1 LIMIT 10", + "Bob", + "eql_cast_firstname", + ), + ( + "SELECT id, value FROM {TABLE} WHERE value @> $1 LIMIT 10", + "Johnson", + "eql_cast_lastname", + ), + ( + "SELECT id, value FROM {TABLE} WHERE eql_v3.match_term(value) @> eql_v3.match_term($1::public.text_search) LIMIT 10", + "Johnson", + "eql_bloom", + ), +]; + +async fn capture( + query: &V3EncryptedQuery, + pool: &sqlx::PgPool, + bench_id: String, +) -> ScenarioMetadata { + let (explain, indexes_used, rows_returned) = query + .capture_metadata(pool) + .await + .expect("metadata capture failed"); + ScenarioMetadata { + id: bench_id, + query: query.statement.clone(), + parameters: vec![query.parameter_json().expect("serialise parameter")], + explain, + indexes_used, + rows_returned, + } +} + +fn criterion_benchmark(c: &mut Criterion) { + init_tracing(); + let rt = Runtime::new().unwrap(); + + let target_rows = std::env::var("TARGET_ROWS").unwrap_or_else(|_| "unknown".to_string()); + let table_suffix = match target_rows.as_str() { + "10000" | "100000" | "1000000" | "10000000" => format!("_{}", target_rows), + _ => String::new(), + }; + let table_name = format!("string_encrypted_v3{}", table_suffix); + let gin_index = format!("{}_match_gin_index", table_name); + + let (pool, cipher) = rt.block_on(async { + let database_url = + std::env::var("DATABASE_URL").expect("DATABASE_URL environment variable must be set"); + let pool = PgPoolOptions::new() + .max_connections(5) + .connect(&database_url) + .await + .expect("Failed to connect to database"); + let cipher = init_scoped_cipher() + .await + .expect("Failed to initialize ScopedCipher"); + (pool, cipher) + }); + + // Needle config matches the ingest config so text_search's required + // terms are all present on the converted payload. + let column_config = ColumnConfig::build("value") + .casts_as(ColumnType::Text) + .add_index(Index::new_unique()) + .add_index(Index::new_match()) + .add_index(Index::new_ore()); + let identifier = Identifier::new(&table_name, "value"); + + let queries: Vec = rt.block_on(async { + let mut queries = Vec::with_capacity(QUERY_TEMPLATES.len()); + for (query_template, needle, _) in QUERY_TEMPLATES { + let query_str = query_template.replace("{TABLE}", &table_name); + let param = encrypt_stored_v3( + Arc::clone(&cipher), + &column_config, + &identifier, + needle.to_string(), + "text_search", + ) + .await + .expect("failed to encrypt+convert match needle"); + queries.push(V3EncryptedQuery::new(param, query_str, Arc::clone(&cipher))); + } + queries + }); + + let mut metadata = rt.block_on(async { + let mut out = Vec::with_capacity(queries.len()); + for (i, query) in queries.iter().enumerate() { + let (_, _, scenario) = QUERY_TEMPLATES[i]; + out.push( + capture( + query, + &pool, + format!("MATCH/match/{}/{}", scenario, target_rows), + ) + .await, + ); + } + out + }); + + let mut group = c.benchmark_group("MATCH"); + group.sample_size(10); + + for (i, query) in queries.iter().enumerate() { + let (_, _, scenario) = QUERY_TEMPLATES[i]; + let exec_id = format!("MATCH/match/{}/{}", scenario, target_rows); + let decrypt_id = format!("MATCH/match_decrypt/{}/{}", scenario, target_rows); + + let exec_id_inner = exec_id.clone(); + group.bench_function(format!("match/{}/{}", scenario, target_rows), |b| { + b.to_async(&rt).iter(|| async { + let _: Vec<_> = bench_assert(query.execute(&pool).await, &exec_id_inner); + }) + }); + + let decrypt_id_inner = decrypt_id.clone(); + group.bench_function(format!("match_decrypt/{}/{}", scenario, target_rows), |b| { + b.to_async(&rt).iter(|| async { + let _r: Vec = black_box(bench_assert( + query.execute_and_decrypt(&pool).await, + &decrypt_id_inner, + )); + }) + }); + } + + // ── No-index variants (10k tier only) ── + // Quantifies what the GIN-via-array_ops index is worth (and, if the GIN + // never engages, proves it by matching timings). criterion executes + // bench_functions as they are registered, so the drop → bench → + // recreate sequencing below is safe. + if target_rows == "10000" { + rt.block_on(async { + sqlx::query(&format!("DROP INDEX IF EXISTS {}", gin_index)) + .execute(&pool) + .await + .expect("drop match GIN index"); + sqlx::query(&format!("ANALYZE {}", table_name)) + .execute(&pool) + .await + .expect("ANALYZE after index drop"); + }); + + let noindex_metadata = rt.block_on(async { + let mut out = Vec::with_capacity(queries.len()); + for (i, query) in queries.iter().enumerate() { + let (_, _, scenario) = QUERY_TEMPLATES[i]; + out.push( + capture( + query, + &pool, + format!("MATCH/match/{}_noindex/{}", scenario, target_rows), + ) + .await, + ); + } + out + }); + metadata.extend(noindex_metadata); + + for (i, query) in queries.iter().enumerate() { + let (_, _, scenario) = QUERY_TEMPLATES[i]; + let exec_id = format!("MATCH/match/{}_noindex/{}", scenario, target_rows); + let exec_id_inner = exec_id.clone(); + group.bench_function( + format!("match/{}_noindex/{}", scenario, target_rows), + |b| { + b.to_async(&rt).iter(|| async { + let _: Vec<_> = + bench_assert(query.execute(&pool).await, &exec_id_inner); + }) + }, + ); + } + + rt.block_on(async { + sqlx::query(&format!( + "CREATE INDEX {} ON {} USING GIN (eql_v3.match_term(value))", + gin_index, table_name + )) + .execute(&pool) + .await + .expect("recreate match GIN index"); + sqlx::query(&format!("ANALYZE {}", table_name)) + .execute(&pool) + .await + .expect("ANALYZE after index recreate"); + }); + } + + group.finish(); + + write_metadata_file_in("results/query/v3", "match", &target_rows, metadata) + .expect("failed to write bench metadata sidecar"); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/benches/ope_v3.rs b/benches/ope_v3.rs new file mode 100644 index 0000000..32ebede --- /dev/null +++ b/benches/ope_v3.rs @@ -0,0 +1,189 @@ +//! EQL v3 CLLW-OPE ordering bench — NEW in v3, no v2 counterpart. +//! +//! Runs the SAME scenario shapes as benches/ore_v3.rs against +//! `integer_encrypted_ope_v3_` (`public.integer_ord_ope`) so the report +//! can chart ORE (custom plpgsql btree opclass) vs OPE (native bytea btree, +//! fully inlinable) per scenario — the headline v3 fast-ordering story. +//! +//! The `op` term is REAL OPE-CLLW ciphertext: cipherstash-client 0.38.1 +//! emits it for `Index::new_ope()` columns (CIP-3280/CIP-3348), so both +//! ciphertext sizes and client-side term generation are representative. +//! +//! Startup includes an order-parity assertion: the ordered scenario's +//! decrypt pass must return values sorted ascending — verifying against +//! real crypto that OPE ciphertext byte order agrees with plaintext order +//! end-to-end. + +use cipherstash_client::{ + eql::Identifier, + schema::{column::Index, ColumnConfig, ColumnType}, +}; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use dbbenches::{ + bench_assert, init_scoped_cipher, init_tracing, + v3::{encrypt_stored_v3, V3EncryptedQuery}, + write_metadata_file_in, ScenarioMetadata, +}; +use sqlx::postgres::PgPoolOptions; +use std::sync::Arc; +use tokio::runtime::Runtime; + +static QUERY_TEMPLATES: &[(&str, i32, &str)] = &[ + ( + "SELECT id, value FROM {TABLE} WHERE value > $1 LIMIT 10", + 5000, + "range_gt_10", + ), + ( + "SELECT id, value FROM {TABLE} WHERE value > $1 LIMIT 100", + 5000, + "range_gt_100", + ), + ( + "SELECT id, value FROM {TABLE} WHERE value < $1 LIMIT 10", + 5000, + "range_lt_10", + ), + ( + "SELECT id, value FROM {TABLE} WHERE value < $1 LIMIT 100", + 5000, + "range_lt_100", + ), + ( + "SELECT id, value FROM {TABLE} \ + WHERE value < $1 \ + ORDER BY eql_v3.ord_ope_term(value) LIMIT 10", + 5000, + "range_lt_ordered_10", + ), +]; + +fn criterion_benchmark(c: &mut Criterion) { + init_tracing(); + let rt = Runtime::new().unwrap(); + + let target_rows = std::env::var("TARGET_ROWS").unwrap_or_else(|_| "unknown".to_string()); + let table_suffix = match target_rows.as_str() { + "10000" | "100000" | "1000000" | "10000000" => format!("_{}", target_rows), + _ => String::new(), + }; + let table_name = format!("integer_encrypted_ope_v3{}", table_suffix); + + let (pool, cipher) = rt.block_on(async { + let database_url = + std::env::var("DATABASE_URL").expect("DATABASE_URL environment variable must be set"); + let pool = PgPoolOptions::new() + .max_connections(5) + .connect(&database_url) + .await + .expect("Failed to connect to database"); + let cipher = init_scoped_cipher() + .await + .expect("Failed to initialize ScopedCipher"); + (pool, cipher) + }); + + // Mirror the ingest config: Index::new_ope() so the client emits the + // real `op` term on the Store-shaped needle. + let column_config = ColumnConfig::build("value") + .casts_as(ColumnType::Int) + .add_index(Index::new_ope()); + let identifier = Identifier::new(&table_name, "value"); + + let queries: Vec = rt.block_on(async { + let mut queries = Vec::with_capacity(QUERY_TEMPLATES.len()); + for (query_template, x, _) in QUERY_TEMPLATES { + let query_str = query_template.replace("{TABLE}", &table_name); + let param = encrypt_stored_v3( + Arc::clone(&cipher), + &column_config, + &identifier, + *x, + "integer_ord_ope", + ) + .await + .expect("failed to encrypt+convert OPE threshold"); + queries.push(V3EncryptedQuery::new(param, query_str, Arc::clone(&cipher))); + } + queries + }); + + // Order-parity gate: the ordered scenario's results, decrypted, must be + // ascending — verifies against real crypto that OPE ciphertext byte + // order agrees with plaintext order. + rt.block_on(async { + let ordered = queries + .iter() + .zip(QUERY_TEMPLATES) + .find(|(_, (_, _, s))| *s == "range_lt_ordered_10") + .map(|(q, _)| q) + .expect("ordered scenario present"); + let values: Vec = ordered + .execute_and_decrypt(&pool) + .await + .expect("order-parity decrypt failed"); + assert!( + values.windows(2).all(|w| w[0] <= w[1]), + "OPE ciphertext order does not match plaintext order: {:?}", + values + ); + eprintln!( + "ope_v3 bench: order-parity OK over {} decrypted rows", + values.len() + ); + }); + + let metadata = rt.block_on(async { + let mut out = Vec::with_capacity(queries.len()); + for (i, query) in queries.iter().enumerate() { + let (_, _, scenario) = QUERY_TEMPLATES[i]; + let bench_id = format!("OPE/ope/{}/{}", scenario, target_rows); + let (explain, indexes_used, rows_returned) = query + .capture_metadata(&pool) + .await + .expect("metadata capture failed"); + out.push(ScenarioMetadata { + id: bench_id, + query: query.statement.clone(), + parameters: vec![query.parameter_json().expect("serialise parameter")], + explain, + indexes_used, + rows_returned, + }); + } + out + }); + write_metadata_file_in("results/query/v3", "ope", &target_rows, metadata) + .expect("failed to write bench metadata sidecar"); + + let mut group = c.benchmark_group("OPE"); + group.sample_size(10); + + for (i, query) in queries.into_iter().enumerate() { + let (_, _, scenario) = QUERY_TEMPLATES[i]; + let exec_id = format!("OPE/ope/{}/{}", scenario, target_rows); + let decrypt_id = format!("OPE/ope_decrypt/{}/{}", scenario, target_rows); + + let exec_id_inner = exec_id.clone(); + group.bench_function(format!("ope/{}/{}", scenario, target_rows), |b| { + b.to_async(&rt).iter(|| async { + let _: Vec<_> = bench_assert(query.execute(&pool).await, &exec_id_inner); + }) + }); + + let decrypt_id_inner = decrypt_id.clone(); + group.bench_function(format!("ope_decrypt/{}/{}", scenario, target_rows), |b| { + b.to_async(&rt).iter(|| async { + let _r: Vec = black_box(bench_assert( + query.execute_and_decrypt(&pool).await, + &decrypt_id_inner, + )); + }) + }); + } + + group.finish(); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/benches/ore_v3.rs b/benches/ore_v3.rs new file mode 100644 index 0000000..9ffc0c8 --- /dev/null +++ b/benches/ore_v3.rs @@ -0,0 +1,164 @@ +//! EQL v3 sibling of `benches/ore.rs` — range queries against +//! `integer_encrypted_v3_` (`public.integer_ord`, ORE block term). +//! +//! Scenario ids match the v2 bench exactly. Bound parameters are +//! STORED-shape v3 payloads (see benches/exact_v3.rs — no scalar query wire +//! shape exists in v3); the domain's comparison operators carry +//! `RIGHTARG = jsonb` overloads that cast in-plan. +//! +//! The selective scenarios stay DISABLED, mirroring the v2 bench: the +//! selectivity limitation (planner can't estimate a bound-parameter +//! encrypted comparison, falls back to DEFAULT_INEQ_SEL) is a property of +//! functional-extractor predicates generally — v3's `=`-only RESTRICT +//! hints don't change range estimation. Re-check via the metadata sidecar +//! if a v3 selectivity fix lands (EQL issue #230). + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use dbbenches::{ + bench_assert, + v3::{encrypt_stored_v3, V3EncryptedQuery}, + init_scoped_cipher, init_tracing, write_metadata_file_in, ScenarioMetadata, +}; +use cipherstash_client::{ + eql::Identifier, + schema::{column::Index, ColumnConfig, ColumnType}, +}; +use sqlx::postgres::PgPoolOptions; +use std::sync::Arc; +use tokio::runtime::Runtime; + +static QUERY_TEMPLATES: &[(&str, i32, &str)] = &[ + // ── Non-selective baselines (≈50% selectivity → Seq Scan + LIMIT) ── + ( + "SELECT id, value FROM {TABLE} WHERE value > $1 LIMIT 10", + 5000, + "range_gt_10", + ), + ( + "SELECT id, value FROM {TABLE} WHERE value > $1 LIMIT 100", + 5000, + "range_gt_100", + ), + ( + "SELECT id, value FROM {TABLE} WHERE value < $1 LIMIT 10", + 5000, + "range_lt_10", + ), + ( + "SELECT id, value FROM {TABLE} WHERE value < $1 LIMIT 100", + 5000, + "range_lt_100", + ), + // ── Ordered range (extractor in ORDER BY, matches the functional + // ord_term index expression → Index Scan, no Sort node) ── + ( + "SELECT id, value FROM {TABLE} \ + WHERE value < $1 \ + ORDER BY eql_v3.ord_term(value) LIMIT 10", + 5000, + "range_lt_ordered_10", + ), +]; + +fn criterion_benchmark(c: &mut Criterion) { + init_tracing(); + let rt = Runtime::new().unwrap(); + + let target_rows = std::env::var("TARGET_ROWS").unwrap_or_else(|_| "unknown".to_string()); + let table_suffix = match target_rows.as_str() { + "10000" | "100000" | "1000000" | "10000000" => format!("_{}", target_rows), + _ => String::new(), + }; + let table_name = format!("integer_encrypted_v3{}", table_suffix); + + let (pool, cipher) = rt.block_on(async { + let database_url = + std::env::var("DATABASE_URL").expect("DATABASE_URL environment variable must be set"); + let pool = PgPoolOptions::new() + .max_connections(5) + .connect(&database_url) + .await + .expect("Failed to connect to database"); + let cipher = init_scoped_cipher() + .await + .expect("Failed to initialize ScopedCipher"); + (pool, cipher) + }); + + let column_config = ColumnConfig::build("value") + .casts_as(ColumnType::Int) + .add_index(Index::new_ore()); + let identifier = Identifier::new(&table_name, "value"); + + let queries: Vec = rt.block_on(async { + let mut queries = Vec::with_capacity(QUERY_TEMPLATES.len()); + for (query_template, x, _) in QUERY_TEMPLATES { + let query_str = query_template.replace("{TABLE}", &table_name); + let param = encrypt_stored_v3( + Arc::clone(&cipher), + &column_config, + &identifier, + *x, + "integer_ord", + ) + .await + .expect("failed to encrypt+convert query threshold"); + queries.push(V3EncryptedQuery::new(param, query_str, Arc::clone(&cipher))); + } + queries + }); + + let metadata = rt.block_on(async { + let mut out = Vec::with_capacity(queries.len()); + for (i, query) in queries.iter().enumerate() { + let (_, _, scenario) = QUERY_TEMPLATES[i]; + let bench_id = format!("ORE/ore/{}/{}", scenario, target_rows); + let (explain, indexes_used, rows_returned) = query + .capture_metadata(&pool) + .await + .expect("metadata capture failed"); + out.push(ScenarioMetadata { + id: bench_id, + query: query.statement.clone(), + parameters: vec![query.parameter_json().expect("serialise parameter")], + explain, + indexes_used, + rows_returned, + }); + } + out + }); + write_metadata_file_in("results/query/v3", "ore", &target_rows, metadata) + .expect("failed to write bench metadata sidecar"); + + let mut group = c.benchmark_group("ORE"); + group.sample_size(10); + + for (i, query) in queries.into_iter().enumerate() { + let (_, _, scenario) = QUERY_TEMPLATES[i]; + let exec_id = format!("ORE/ore/{}/{}", scenario, target_rows); + let decrypt_id = format!("ORE/ore_decrypt/{}/{}", scenario, target_rows); + + let exec_id_inner = exec_id.clone(); + group.bench_function(format!("ore/{}/{}", scenario, target_rows), |b| { + b.to_async(&rt).iter(|| async { + let _: Vec<_> = bench_assert(query.execute(&pool).await, &exec_id_inner); + }) + }); + + let decrypt_id_inner = decrypt_id.clone(); + group.bench_function(format!("ore_decrypt/{}/{}", scenario, target_rows), |b| { + b.to_async(&rt).iter(|| async { + let _r: Vec = black_box(bench_assert( + query.execute_and_decrypt(&pool).await, + &decrypt_id_inner, + )); + }) + }); + } + + group.finish(); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/benches/plaintext_v3.rs b/benches/plaintext_v3.rs new file mode 100644 index 0000000..59e454a --- /dev/null +++ b/benches/plaintext_v3.rs @@ -0,0 +1,175 @@ +//! Plaintext baselines for the v3 encrypted-vs-plaintext comparison — the +//! docs/marketing "overhead vs native Postgres" story. Runs the SAME query +//! shapes as the headline encrypted scenarios against plaintext tables with +//! equivalent indexes: +//! +//! plaintext/exact_eq string_plaintext_ WHERE value = $1 LIMIT 1 (btree) +//! plaintext/range_gt_10 integer_plaintext_ WHERE value > $1 LIMIT 10 (btree) +//! plaintext/range_lt_ordered_10 integer_plaintext_ WHERE value < $1 ORDER BY value LIMIT 10 +//! plaintext/json_contains json_small_plaintext_ WHERE value @> $1 LIMIT 10 (jsonb_path_ops GIN) +//! plaintext/json_field_eq json_small_plaintext_ WHERE value -> 'age' = $1 LIMIT 10 +//! +//! (GROUP BY plaintext baselines already live inside benches/group_by_v3.rs, +//! carried over from the v2 bench.) +//! +//! The comparison report maps these onto their encrypted counterparts by +//! scenario name. No encryption client is involved anywhere in this bench. + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use dbbenches::{ + bench_assert, extract_indexes_used, init_tracing, write_metadata_file_in, ScenarioMetadata, +}; +use serde_json::Value as JsonValue; +use sqlx::postgres::PgPoolOptions; +use sqlx::types::Json; +use tokio::runtime::Runtime; + +fn criterion_benchmark(c: &mut Criterion) { + init_tracing(); + let rt = Runtime::new().unwrap(); + + let target_rows = std::env::var("TARGET_ROWS").unwrap_or_else(|_| "unknown".to_string()); + let table_suffix = match target_rows.as_str() { + "10000" | "100000" | "1000000" | "10000000" => format!("_{}", target_rows), + _ => String::new(), + }; + let string_table = format!("string_plaintext{}", table_suffix); + let integer_table = format!("integer_plaintext{}", table_suffix); + let json_table = format!("json_small_plaintext{}", table_suffix); + + let pool = rt.block_on(async { + let database_url = + std::env::var("DATABASE_URL").expect("DATABASE_URL environment variable must be set"); + PgPoolOptions::new() + .max_connections(5) + .connect(&database_url) + .await + .expect("Failed to connect to database") + }); + + // Sample needles from real rows (same guarantee as the encrypted + // benches: equality scenarios hit at least one row). + let (string_needle, json_age_needle): (String, i64) = rt.block_on(async { + let s: (String,) = + sqlx::query_as(&format!("SELECT value FROM {string_table} LIMIT 1")) + .fetch_one(&pool) + .await + .expect("sample from string_plaintext failed — is it prepared?"); + let a: (JsonValue,) = sqlx::query_as(&format!( + "SELECT (value -> 'age')::jsonb FROM {json_table} LIMIT 1" + )) + .fetch_one(&pool) + .await + .expect("sample from json_small_plaintext failed — is it prepared?"); + (s.0, a.0.as_i64().expect("age is an integer")) + }); + let json_contains_needle = format!(r#"{{"age": {}}}"#, json_age_needle); + let json_field_eq_needle = json_age_needle.to_string(); + + // (scenario, statement, bind) + enum Bind { + Text(String), + Int(i32), + Jsonb(String), + } + let scenarios: Vec<(&str, String, Option)> = vec![ + ( + "exact_eq", + format!("SELECT id, value FROM {string_table} WHERE value = $1 LIMIT 1"), + Some(Bind::Text(string_needle)), + ), + ( + "range_gt_10", + format!("SELECT id, value FROM {integer_table} WHERE value > $1 LIMIT 10"), + Some(Bind::Int(5000)), + ), + ( + "range_lt_ordered_10", + format!( + "SELECT id, value FROM {integer_table} WHERE value < $1 ORDER BY value LIMIT 10" + ), + Some(Bind::Int(5000)), + ), + ( + "json_contains", + format!("SELECT id FROM {json_table} WHERE value @> $1::jsonb LIMIT 10"), + Some(Bind::Jsonb(json_contains_needle)), + ), + ( + "json_field_eq", + format!("SELECT id FROM {json_table} WHERE value -> 'age' = $1::jsonb LIMIT 10"), + Some(Bind::Jsonb(json_field_eq_needle)), + ), + ]; + + fn bind_query<'q>( + q: &'q str, + bind: &'q Option, + ) -> sqlx::query::Query<'q, sqlx::Postgres, sqlx::postgres::PgArguments> { + let query = sqlx::query(q); + match bind { + Some(Bind::Text(s)) => query.bind(s), + Some(Bind::Int(i)) => query.bind(i), + Some(Bind::Jsonb(j)) => query.bind(j), + None => query, + } + } + + let metadata = rt.block_on(async { + let mut out = Vec::with_capacity(scenarios.len()); + for (scenario, statement, bind) in &scenarios { + let bench_id = format!("PLAINTEXT/plaintext/{}/{}", scenario, target_rows); + let explain_sql = format!("EXPLAIN (FORMAT JSON) {}", statement); + let (Json(explain),): (Json,) = { + let q = sqlx::query_as(&explain_sql); + match bind { + Some(Bind::Text(s)) => q.bind(s), + Some(Bind::Int(i)) => q.bind(i), + Some(Bind::Jsonb(j)) => q.bind(j), + None => q, + } + .fetch_one(&pool) + .await + .expect("EXPLAIN failed") + }; + let indexes_used = extract_indexes_used(&explain); + let rows = bind_query(statement, bind) + .fetch_all(&pool) + .await + .expect("execute for row-count failed"); + out.push(ScenarioMetadata { + id: bench_id, + query: statement.clone(), + parameters: Vec::new(), + explain, + indexes_used, + rows_returned: rows.len() as u64, + }); + } + out + }); + write_metadata_file_in("results/query/v3", "plaintext", &target_rows, metadata) + .expect("failed to write bench metadata sidecar"); + + let mut group = c.benchmark_group("PLAINTEXT"); + group.sample_size(10); + + for (scenario, statement, bind) in scenarios { + let bench_id = format!("PLAINTEXT/plaintext/{}/{}", scenario, target_rows); + let inner_id = bench_id.clone(); + group.bench_function(format!("plaintext/{}/{}", scenario, target_rows), |b| { + b.to_async(&rt).iter(|| async { + let rows = bench_assert( + bind_query(&statement, &bind).fetch_all(&pool).await, + &inner_id, + ); + black_box(rows.len()); + }) + }); + } + + group.finish(); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/benches/scalar_smoke_v3.rs b/benches/scalar_smoke_v3.rs new file mode 100644 index 0000000..db13fc3 --- /dev/null +++ b/benches/scalar_smoke_v3.rs @@ -0,0 +1,205 @@ +//! New-family smoke bench (v3-only, no v2 counterpart, 10k rows, no tiers). +//! +//! One range scenario + one extractor-ordered scenario per ordered scalar +//! family the v2 benches never covered (date / timestamp / numeric / bigint +//! / double), plus a select-back scenario for storage-only `boolean`. +//! Purpose: catch per-family CHECK / operator-routing / inlining breakage +//! and index engagement — NOT to produce tier curves. Runs against the +//! fixed `scalar_smoke_v3` table populated by `prepare:scalar_smoke_v3`. +//! +//! Startup builds a functional `eql_v3.ord_term(col)` btree per ordered +//! family so the ordered scenario's `indexes_used` proves the family's +//! whole extractor chain inlines. + +use chrono::{Duration, TimeZone, Utc}; +use cipherstash_client::{ + encryption::Plaintext, + eql::Identifier, + schema::{column::Index, ColumnConfig, ColumnType}, +}; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use dbbenches::{ + bench_assert, init_scoped_cipher, init_tracing, + v3::{encrypt_stored_v3, V3EncryptedQuery}, + write_metadata_file_in, ScenarioMetadata, +}; +use rust_decimal::Decimal; +use sqlx::postgres::PgPoolOptions; +use std::sync::Arc; +use tokio::runtime::Runtime; + +const TABLE: &str = "scalar_smoke_v3"; + +fn criterion_benchmark(c: &mut Criterion) { + init_tracing(); + let rt = Runtime::new().unwrap(); + + // Fixed-size table; keep a tier-like id segment for report consistency. + let target_rows = "10000".to_string(); + + let (pool, cipher) = rt.block_on(async { + let database_url = + std::env::var("DATABASE_URL").expect("DATABASE_URL environment variable must be set"); + let pool = PgPoolOptions::new() + .max_connections(5) + .connect(&database_url) + .await + .expect("Failed to connect to database"); + let cipher = init_scoped_cipher() + .await + .expect("Failed to initialize ScopedCipher"); + (pool, cipher) + }); + + let epoch = Utc.with_ymd_and_hms(2000, 1, 1, 0, 0, 0).unwrap(); + + // (family, column, ColumnType, mid-range needle) — needle sits near the + // middle of the ingest distribution (see encrypt_scalar_smoke_v3) so the + // range scenarios return rows. + let families: Vec<(&str, &str, ColumnType, Plaintext)> = vec![ + ( + "date_ord", + "date_val", + ColumnType::Date, + Plaintext::NaiveDate(Some((epoch + Duration::days(5_000)).date_naive())), + ), + ( + "timestamp_ord", + "timestamp_val", + ColumnType::Timestamp, + Plaintext::Timestamp(Some(epoch + Duration::seconds(400_000_000))), + ), + ( + "numeric_ord", + "numeric_val", + ColumnType::Decimal, + Plaintext::Decimal(Some(Decimal::new(5_000_000, 2))), + ), + ( + "bigint_ord", + "bigint_val", + ColumnType::BigInt, + Plaintext::BigInt(Some(i64::MAX / 2)), + ), + ( + "double_ord", + "double_val", + ColumnType::Float, + Plaintext::Float(Some(500_000.0)), + ), + ]; + + // Per-family functional ord_term indexes. + rt.block_on(async { + for (_, col, _, _) in &families { + sqlx::query(&format!("DROP INDEX IF EXISTS {TABLE}_{col}_ord_idx")) + .execute(&pool) + .await + .expect("drop stale smoke index"); + sqlx::query(&format!( + "CREATE INDEX {TABLE}_{col}_ord_idx ON {TABLE} (eql_v3.ord_term({col}))" + )) + .execute(&pool) + .await + .expect("create smoke ord index"); + } + sqlx::query(&format!("ANALYZE {TABLE}")) + .execute(&pool) + .await + .expect("ANALYZE smoke table"); + }); + + // Build queries: (id_segment, statement, param) + let queries: Vec<(String, V3EncryptedQuery)> = rt.block_on(async { + let mut out = Vec::new(); + for (family, col, ty, needle) in families { + let config = ColumnConfig::build(col) + .casts_as(ty) + .add_index(Index::new_ore()); + let ident = Identifier::new(TABLE, col); + let param = encrypt_stored_v3( + Arc::clone(&cipher), + &config, + &ident, + needle, + family, + ) + .await + .unwrap_or_else(|e| panic!("needle encrypt+convert failed for `{family}`: {e:?}")); + + out.push(( + format!("{family}/range_gt_10"), + V3EncryptedQuery::new( + param.clone(), + format!("SELECT id, {col} FROM {TABLE} WHERE {col} > $1 LIMIT 10"), + Arc::clone(&cipher), + ), + )); + out.push(( + format!("{family}/range_gt_ordered_10"), + V3EncryptedQuery::new( + param, + format!( + "SELECT id, {col} FROM {TABLE} WHERE {col} > $1 \ + ORDER BY eql_v3.ord_term({col}) LIMIT 10" + ), + Arc::clone(&cipher), + ), + )); + } + out + }); + + let metadata = rt.block_on(async { + let mut out = Vec::with_capacity(queries.len() + 1); + for (segment, query) in &queries { + let bench_id = format!("SMOKE_V3/smoke/{}/{}", segment, target_rows); + let (explain, indexes_used, rows_returned) = query + .capture_metadata(&pool) + .await + .unwrap_or_else(|e| panic!("metadata capture failed for `{segment}`: {e:?}")); + out.push(ScenarioMetadata { + id: bench_id, + query: query.statement.clone(), + parameters: vec![query.parameter_json().expect("serialise parameter")], + explain, + indexes_used, + rows_returned, + }); + } + out + }); + write_metadata_file_in("results/query/v3", "scalar_smoke", &target_rows, metadata) + .expect("failed to write bench metadata sidecar"); + + let mut group = c.benchmark_group("SMOKE_V3"); + group.sample_size(10); + + for (segment, query) in queries { + let bench_id = format!("SMOKE_V3/smoke/{}/{}", segment, target_rows); + let inner_id = bench_id.clone(); + group.bench_function(format!("smoke/{}/{}", segment, target_rows), |b| { + b.to_async(&rt).iter(|| async { + let _: Vec<_> = bench_assert(query.execute(&pool).await, &inner_id); + }) + }); + } + + // Storage-only boolean: select-back is the entire supported surface. + { + let q = format!("SELECT id, boolean_val FROM {TABLE} LIMIT 10"); + let id = format!("SMOKE_V3/smoke/boolean/select_back/{}", target_rows); + let inner_id = id.clone(); + group.bench_function(format!("smoke/boolean/select_back/{}", target_rows), |b| { + b.to_async(&rt).iter(|| async { + let rows = bench_assert(sqlx::query(&q).fetch_all(&pool).await, &inner_id); + black_box(rows.len()); + }) + }); + } + + group.finish(); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/find_slow_queries.py b/find_slow_queries.py index ac86afd..f152d68 100644 --- a/find_slow_queries.py +++ b/find_slow_queries.py @@ -56,15 +56,19 @@ def format_age(mtime: float, now: float) -> str: return f"{delta // (86400 * 7)}w ago" -def collect_slow(results_dir, threshold_ns, prefix): +def collect_slow(results_dir, threshold_ns, prefix, v3=False): """Walk `results_dir/query/*_rows_*.json`, return events above threshold. + With `v3=True`, scans `results_dir/query/v3/` instead — the EQL v3 bench + results live in a subdirectory so the committed v2 baseline files stay + untouched (see report_v3_compare.py). + Returns a list of `(median_ns, rows, bench_id, mtime)` tuples — unsorted. Bench ids are filtered by `prefix` (str.startswith) when given. """ - query_dir = results_dir / "query" + query_dir = results_dir / "query" / "v3" if v3 else results_dir / "query" if not query_dir.is_dir(): - sys.exit(f"no `query/` subdirectory under {results_dir}") + sys.exit(f"no `{query_dir}` directory") filename_re = re.compile(r"^(.+)_rows_(\d+)\.json$") slow = [] @@ -111,6 +115,8 @@ def main(): help="list every scenario, ignoring the threshold") parser.add_argument("--results-dir", type=Path, default=Path("results"), help="benchmark results root (default ./results)") + parser.add_argument("--v3", action="store_true", + help="scan the EQL v3 results (results/query/v3/) instead of the v2 baseline") parser.add_argument("prefix", nargs="?", default=None, help="if given, only include scenarios whose id starts with this prefix " "(e.g. 'ORE' or 'EXACT/exact_decrypt')") @@ -119,25 +125,26 @@ def main(): # --all lists everything; a -inf threshold admits every (positive) median. threshold_ns = float("-inf") if args.all else args.ms * 1_000_000 - slow = collect_slow(args.results_dir, threshold_ns, args.prefix) + slow = collect_slow(args.results_dir, threshold_ns, args.prefix, v3=args.v3) # Worst offenders first. slow.sort(key=lambda r: r[0], reverse=True) prefix_note = f" matching prefix '{args.prefix}'" if args.prefix else "" + scanned = f"{args.results_dir}/query/v3" if args.v3 else f"{args.results_dir}/query" if not slow: if args.all: - print(f"No benchmark results found under {args.results_dir}/query{prefix_note}.") + print(f"No benchmark results found under {scanned}{prefix_note}.") else: print(f"No queries exceed {args.ms:g} ms{prefix_note}.") return if args.all: print(f"All {len(slow)} benchmark scenarios{prefix_note} " - f"(scanned {args.results_dir}/query), slowest first:") + f"(scanned {scanned}), slowest first:") else: print(f"Queries with median runtime > {args.ms:g} ms{prefix_note} " - f"(scanned {args.results_dir}/query):") + f"(scanned {scanned}):") print() now = time.time() diff --git a/mise.toml b/mise.toml index ec3fb6d..f302d4b 100644 --- a/mise.toml +++ b/mise.toml @@ -169,6 +169,69 @@ psql -v ON_ERROR_STOP=1 -U postgres -d postgres < sql/schema.sql echo "Database setup complete!" """ +[tasks.setup-db-v3] +description = "Install the EQL v3 bundle and create the v3 bench tables (coexists with v2)" +depends = ["postgres"] +run = """ +#!/usr/bin/env bash +set -e + +echo "Waiting for PostgreSQL to be ready..." +until pg_isready -U postgres > /dev/null 2>&1; do + sleep 1 +done + +# EQL v3 is released as of eql-3.0.0-alpha.3 (2026-07-08): the default is to +# download the pinned release bundle (same pattern as setup-db above). +# alpha.3 installs the eql_v3 / eql_v3_internal function schemas AND the +# per-domain types (public.json, public.text_search, public.integer_ord, …) +# — the types moved eql_v3.* -> public.* in this release, which is what the +# v3 schema/index/bench SQL now targets. Overrides: +# EQL_V3_SQL= use a prebuilt bundle +# EQL_V3_DIR= build from a local checkout +# (for testing an unreleased fix before a pre-release is cut) +EQL_V3_VERSION="${EQL_V3_VERSION:-eql-3.0.0-alpha.3}" +if [ -z "${EQL_V3_SQL:-}" ]; then + if [ -n "${EQL_V3_DIR:-}" ]; then + if [ ! -d "$EQL_V3_DIR" ]; then + echo "Error: EQL checkout not found at $EQL_V3_DIR" + exit 1 + fi + echo "Building EQL v3 bundle from local checkout $EQL_V3_DIR..." + (cd "$EQL_V3_DIR" && mise run build --version 3.0.0-dev) + EQL_V3_SQL="$EQL_V3_DIR/release/cipherstash-encrypt.sql" + else + echo "Downloading EQL v3 ($EQL_V3_VERSION)..." + curl -sfLo /tmp/cipherstash-encrypt-v3.sql \ + "https://github.com/cipherstash/encrypt-query-language/releases/download/$EQL_V3_VERSION/cipherstash-encrypt.sql" + EQL_V3_SQL="/tmp/cipherstash-encrypt-v3.sql" + fi +fi + +# The v3 bundle installs the eql_v3 / eql_v3_internal function schemas and the +# public.* domain types, and coexists with the v2.3 install — setup-db and +# setup-db-v3 target the same database. Skip the install if eql_v3 is already +# present; the bundle is not idempotent (bare CREATE FUNCTION). To reinstall +# after a bundle/version change (e.g. upgrading a pre-alpha.3 install that +# still has eql_v3.* types), run the matching v3 uninstaller first +# (cipherstash-encrypt-uninstall.sql from the same release — drops the eql_v3 +# schemas and the public.* domains). +if psql -U postgres -d postgres -tAc "SELECT 1 FROM pg_namespace WHERE nspname = 'eql_v3'" | grep -q 1; then + echo "eql_v3 schema already installed — skipping bundle install." +else + echo "Installing EQL v3 from $EQL_V3_SQL..." + psql -v ON_ERROR_STOP=1 -U postgres -d postgres < "$EQL_V3_SQL" +fi + +echo "Creating v3 bench tables..." +psql -v ON_ERROR_STOP=1 -U postgres -d postgres < sql/schema_v3.sql + +echo "Creating plaintext baseline tables..." +psql -v ON_ERROR_STOP=1 -U postgres -d postgres < sql/plaintext_baselines.sql + +echo "EQL v3 database setup complete!" +""" + [tasks."bench:build"] description = "Build all binaries in release mode" run = """ @@ -209,6 +272,49 @@ echo "Combining results..." echo "Benchmark complete! Results written to results/ingest/${BENCH_NAME}_combined.json" """ +[tasks."bench:v3:ingest:_run"] +description = "Internal: run a v3 ingest benchmark and move results under results/ingest/v3/" +run = """ +#!/usr/bin/env bash +set -e +BENCH_NAME="$1" +TABLE_NAME="$2" +mise run bench:ingest:_run "$BENCH_NAME" "$TABLE_NAME" "${3:-500,1000,10000}" +mkdir -p results/ingest/v3 +mv "results/ingest/${BENCH_NAME}_combined.json" "results/ingest/v3/${BENCH_NAME}_combined.json" +echo "Moved results to results/ingest/v3/${BENCH_NAME}_combined.json" +""" + +[tasks."bench:v3:ingest:encrypt_string"] +description = "Run encrypt_string_v3 ingest benchmark (public.text_search)" +run = "mise run bench:v3:ingest:_run encrypt_string_v3 string_encrypted_v3" + +[tasks."bench:v3:ingest:encrypt_int"] +description = "Run encrypt_int_v3 ingest benchmark (public.integer_ord)" +run = "mise run bench:v3:ingest:_run encrypt_int_v3 integer_encrypted_v3" + +[tasks."bench:v3:ingest:encrypt_int_ope"] +description = "Run encrypt_int_ope_v3 ingest benchmark (public.integer_ord_ope, real op term via client 0.38.1)" +run = "mise run bench:v3:ingest:_run encrypt_int_ope_v3 integer_encrypted_ope_v3" + +[tasks."bench:v3:ingest:encrypt_category"] +description = "Run encrypt_category_v3 ingest benchmark (public.text_eq)" +run = "mise run bench:v3:ingest:_run encrypt_category_v3 category_encrypted_v3" + +[tasks."bench:v3:ingest:json-ste-vec-small"] +description = "Run encrypt_ste_vec_small_v3 ingest benchmark (public.json)" +run = "mise run bench:v3:ingest:_run encrypt_ste_vec_small_v3 json_ste_vec_small_encrypted_v3" + +[tasks."bench:v3:ingest"] +description = "Run all v3 ingest benchmarks" +depends = [ + "bench:v3:ingest:encrypt_int", + "bench:v3:ingest:encrypt_string", + "bench:v3:ingest:encrypt_int_ope", + "bench:v3:ingest:encrypt_category", + "bench:v3:ingest:json-ste-vec-small", +] + [tasks."bench:ingest:encrypt_int"] description = "Run encrypt_int ingest benchmark and combine results" run = "mise run bench:ingest:_run encrypt_int integer_encrypted" @@ -352,7 +458,17 @@ while true; do done echo "Creating indexes..." +# Time the index build and append to the build-times log — index build cost +# is a first-class result for the v3 comparison (the v3 ORE btree opclass +# has a plpgsql comparator; build time at 1M is a named risk to measure). +INDEX_BUILD_START=$(date +%s) psql -U postgres -d postgres < sql/indexes/${TABLE_NAME}_up.sql +INDEX_BUILD_SECS=$(( $(date +%s) - INDEX_BUILD_START )) +mkdir -p results/ingest +# NB: single-quoted printf format — this script lives in a TOML basic +# multiline string, which consumes backslash escapes before bash sees them. +printf '{"table": "%s", "build_seconds": %s, "recorded_at": "%s"}\n' "$TABLE_NAME" "$INDEX_BUILD_SECS" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> results/ingest/index_build_times.jsonl +echo "Index build took ${INDEX_BUILD_SECS}s (logged to results/ingest/index_build_times.jsonl)" # ANALYZE the freshly-loaded table so the planner has accurate # selectivity stats for the functional indexes. Without this, the @@ -387,6 +503,57 @@ run = "mise run prepare:_table category_encrypted encrypt_category $1" description = "Prepare combo_encrypted_ table with three encrypted columns (name + age + category)" run = "mise run prepare:_table combo_encrypted encrypt_combo $1" +[tasks."prepare:string_encrypted_v3"] +description = "Prepare string_encrypted_v3 table (public.text_search) with target row count" +run = "mise run prepare:_table string_encrypted_v3 encrypt_string_v3 $1" + +[tasks."prepare:integer_encrypted_v3"] +description = "Prepare integer_encrypted_v3 table (public.integer_ord) with target row count" +run = "mise run prepare:_table integer_encrypted_v3 encrypt_int_v3 $1" + +[tasks."prepare:integer_encrypted_ope_v3"] +description = "Prepare integer_encrypted_ope_v3 table (public.integer_ord_ope) with target row count" +run = "mise run prepare:_table integer_encrypted_ope_v3 encrypt_int_ope_v3 $1" + +[tasks."prepare:category_encrypted_v3"] +description = "Prepare category_encrypted_v3 table (public.text_eq) with target row count" +run = "mise run prepare:_table category_encrypted_v3 encrypt_category_v3 $1" + +[tasks."prepare:combo_encrypted_v3"] +description = "Prepare combo_encrypted_v3 table (three eql_v3 columns) with target row count" +run = "mise run prepare:_table combo_encrypted_v3 encrypt_combo_v3 $1" + +[tasks."prepare:json_ste_vec_small_v3"] +description = "Prepare json_ste_vec_small_encrypted_v3 table (public.json) with target row count" +run = "mise run prepare:_table json_ste_vec_small_encrypted_v3 encrypt_ste_vec_small_v3 $1" + +[tasks."prepare:scalar_smoke_v3"] +description = "Populate the scalar_smoke_v3 new-family smoke table (10k rows, no tier variants)" +depends = ["postgres", "bench:build"] +run = """ +#!/usr/bin/env bash +set -e +CURRENT=$(psql -U postgres -d postgres -tAc "SELECT COUNT(*) FROM scalar_smoke_v3;") +TARGET="${1:-10000}" +if [ "$CURRENT" -ge "$TARGET" ]; then + echo "scalar_smoke_v3 already has $CURRENT rows (>= $TARGET)." + exit 0 +fi +NUM_RECORDS=$((TARGET - CURRENT)) ./target/release/encrypt_scalar_smoke_v3 +""" + +[tasks."prepare:v3:all"] +description = "Prepare every v3 encrypted table at the given tier (default 10000)" +run = """ +#!/usr/bin/env bash +set -e +TIER="${1:-10000}" +for t in string_encrypted_v3 integer_encrypted_v3 integer_encrypted_ope_v3 category_encrypted_v3 combo_encrypted_v3 json_ste_vec_small_v3; do + mise run "prepare:$t" "$TIER" +done +mise run prepare:scalar_smoke_v3 +""" + [tasks."prepare:category_plaintext"] description = "Prepare category_plaintext_ table with ~250 low-cardinality categorical strings (CAT_001..CAT_250, uniform random)" depends = ["postgres"] @@ -443,6 +610,73 @@ FINAL_ROWS=$(psql -U postgres -d postgres -t -c "SELECT COUNT(*) FROM $TABLE_NAM echo "Preparation complete! Final row count: $FINAL_ROWS" """ +[tasks."prepare:integer_plaintext"] +description = "Prepare integer_plaintext_ table (random ints, btree) — plaintext baseline for ORE/OPE range scenarios" +depends = ["postgres"] +run = """ +#!/usr/bin/env bash +set -e +TARGET_ROWS="$1" +case "$TARGET_ROWS" in + 10000|100000|1000000|10000000) ;; + *) echo "Error: TARGET_ROWS must be one of: 10000, 100000, 1000000, 10000000"; exit 1 ;; +esac +TABLE_NAME="integer_plaintext_${TARGET_ROWS}" +until pg_isready -U postgres > /dev/null 2>&1; do sleep 1; done +CURRENT_ROWS=$(psql -U postgres -d postgres -tAc "SELECT COUNT(*) FROM $TABLE_NAME;") +if [ "$CURRENT_ROWS" -ge "$TARGET_ROWS" ]; then + echo "$TABLE_NAME already has $CURRENT_ROWS rows (>= $TARGET_ROWS)." + psql -U postgres -d postgres -c "CREATE INDEX IF NOT EXISTS ${TABLE_NAME}_value_idx ON $TABLE_NAME (value);" + exit 0 +fi +ROWS_TO_INSERT=$((TARGET_ROWS - CURRENT_ROWS)) +echo "Inserting $ROWS_TO_INSERT rows into $TABLE_NAME..." +# Same distribution as the encrypted integer bench: uniform over the full +# i32 range (Faker.fake::()). +psql -v ON_ERROR_STOP=1 -U postgres -d postgres -c " + INSERT INTO $TABLE_NAME (value) + SELECT (floor(random() * 4294967296) - 2147483648)::int + FROM generate_series(1, $ROWS_TO_INSERT);" +psql -U postgres -d postgres -c "CREATE INDEX IF NOT EXISTS ${TABLE_NAME}_value_idx ON $TABLE_NAME (value);" +psql -U postgres -d postgres -c "ANALYZE $TABLE_NAME;" +echo "Preparation complete." +""" + +[tasks."prepare:json_small_plaintext"] +description = "Prepare json_small_plaintext_ table (FakeJsonSmall-shaped jsonb, jsonb_path_ops GIN) — plaintext baseline for JSON scenarios" +depends = ["postgres"] +run = """ +#!/usr/bin/env bash +set -e +TARGET_ROWS="$1" +case "$TARGET_ROWS" in + 10000|100000|1000000|10000000) ;; + *) echo "Error: TARGET_ROWS must be one of: 10000, 100000, 1000000, 10000000"; exit 1 ;; +esac +TABLE_NAME="json_small_plaintext_${TARGET_ROWS}" +until pg_isready -U postgres > /dev/null 2>&1; do sleep 1; done +CURRENT_ROWS=$(psql -U postgres -d postgres -tAc "SELECT COUNT(*) FROM $TABLE_NAME;") +if [ "$CURRENT_ROWS" -ge "$TARGET_ROWS" ]; then + echo "$TABLE_NAME already has $CURRENT_ROWS rows (>= $TARGET_ROWS)." + psql -U postgres -d postgres -c "CREATE INDEX IF NOT EXISTS ${TABLE_NAME}_gin_idx ON $TABLE_NAME USING GIN (value jsonb_path_ops);" + exit 0 +fi +ROWS_TO_INSERT=$((TARGET_ROWS - CURRENT_ROWS)) +echo "Inserting $ROWS_TO_INSERT rows into $TABLE_NAME..." +psql -v ON_ERROR_STOP=1 -U postgres -d postgres -c " + INSERT INTO $TABLE_NAME (value) + SELECT jsonb_build_object( + 'first_name', md5(random()::text), + 'last_name', md5(random()::text), + 'age', (18 + floor(random() * 82))::int, + 'email', md5(random()::text) || '@example.com' + ) + FROM generate_series(1, $ROWS_TO_INSERT);" +psql -U postgres -d postgres -c "CREATE INDEX IF NOT EXISTS ${TABLE_NAME}_gin_idx ON $TABLE_NAME USING GIN (value jsonb_path_ops);" +psql -U postgres -d postgres -c "ANALYZE $TABLE_NAME;" +echo "Preparation complete." +""" + [tasks."prepare:string_plaintext"] description = "Prepare string_plaintext_ table with random high-cardinality strings (md5)" depends = ["postgres"] @@ -480,7 +714,11 @@ echo "Current rows in $TABLE_NAME: $CURRENT_ROWS" echo "Target rows: $TARGET_ROWS" if [ "$CURRENT_ROWS" -ge "$TARGET_ROWS" ]; then - echo "Table already has $CURRENT_ROWS rows (>= $TARGET_ROWS). No action needed." + echo "Table already has $CURRENT_ROWS rows (>= $TARGET_ROWS)." + # Still ensure the value index exists — older populations predate it, and + # the early exit must not skip it (that's how the 1M plaintext baseline + # ran unindexed the first time). + psql -U postgres -d postgres -c "CREATE INDEX IF NOT EXISTS ${TABLE_NAME}_value_idx ON $TABLE_NAME (value);" exit 0 fi @@ -496,6 +734,13 @@ psql -v ON_ERROR_STOP=1 -U postgres -d postgres -c " FROM generate_series(1, $ROWS_TO_INSERT) g; " +# btree on value: the v3 plaintext baseline bench (benches/plaintext_v3.rs) +# runs `WHERE value = $1` against this table, and the encrypted counterpart +# is btree-indexed — an unindexed plaintext baseline would overstate EQL's +# relative performance. Idempotent; harmless for other consumers. +psql -U postgres -d postgres -c "CREATE INDEX IF NOT EXISTS ${TABLE_NAME}_value_idx ON $TABLE_NAME (value);" +psql -U postgres -d postgres -c "ANALYZE $TABLE_NAME;" + FINAL_ROWS=$(psql -U postgres -d postgres -t -c "SELECT COUNT(*) FROM $TABLE_NAME;" | tr -d ' ') echo "Preparation complete! Final row count: $FINAL_ROWS" """ @@ -701,6 +946,157 @@ TARGET_ROWS="$TARGET_ROWS" cargo criterion --bench json --message-format json > echo "Benchmark complete! Results written to $OUTPUT_FILE" """ +[tasks."bench:v3:query:_run"] +description = "Internal: run one v3 query bench (prepare deps, clean criterion group, write results under results/query/v3/)" +run = """ +#!/usr/bin/env bash +set -e + +# Signature: [prepare tasks...] +# TARGET_ROWS comes LAST: the per-family wrapper tasks are single-line +# commands, and mise appends caller args to those — so the tier the user +# passes lands at the end of the arg list. +BENCH_NAME="$1" # cargo bench target, e.g. exact_v3 +GROUP="$2" # criterion group to clean, e.g. EXACT +shift 2 + +# All-but-last args are prepare task names; the last is the tier. +PREPS="" +while [ $# -gt 1 ]; do + PREPS="$PREPS $1" + shift +done +TARGET_ROWS="${1:-}" + +if [ -z "$BENCH_NAME" ] || [ -z "$GROUP" ] || [ -z "$TARGET_ROWS" ]; then + echo "Usage: mise run bench:v3:query:_run [prepare tasks...] " + exit 1 +fi +if ! [[ "$TARGET_ROWS" =~ ^[0-9]+$ ]]; then + echo "Error: target row count must be a positive integer" + exit 1 +fi + +for prep in $PREPS; do + echo "Preparing via prepare:$prep..." + mise run "prepare:$prep" "$TARGET_ROWS" +done + +echo "Cleaning old criterion data for $GROUP..." +rm -rf "target/criterion/data/main/$GROUP" "target/criterion/reports/$GROUP" + +echo "Running $BENCH_NAME query benchmark..." +mkdir -p results/query/v3 +OUTPUT_FILE="results/query/v3/${BENCH_NAME%_v3}_rows_${TARGET_ROWS}.json" +TARGET_ROWS="$TARGET_ROWS" cargo criterion --bench "$BENCH_NAME" --message-format json > "$OUTPUT_FILE" + +echo "Benchmark complete! Results written to $OUTPUT_FILE" +""" + +[tasks."bench:v3:query:exact"] +description = "Run EXACT v3 query benchmark (public.text_search)" +run = "mise run bench:v3:query:_run exact_v3 EXACT string_encrypted_v3" + +[tasks."bench:v3:query:ore"] +description = "Run ORE v3 query benchmark (public.integer_ord)" +run = "mise run bench:v3:query:_run ore_v3 ORE integer_encrypted_v3" + +[tasks."bench:v3:query:group_by"] +description = "Run GROUP BY v3 query benchmark (public.text_eq + shared plaintext baseline)" +run = "mise run bench:v3:query:_run group_by_v3 GROUP_BY category_encrypted_v3 category_plaintext" + +[tasks."bench:v3:query:match"] +description = "Run MATCH v3 query benchmark (bloom containment; incl. no-index variants at 10k)" +run = "mise run bench:v3:query:_run match_v3 MATCH string_encrypted_v3" + +[tasks."bench:v3:query:ope"] +description = "Run OPE v3 query benchmark (public.integer_ord_ope)" +run = "mise run bench:v3:query:_run ope_v3 OPE integer_encrypted_ope_v3" + +[tasks."bench:v3:query:combo"] +description = "Run COMBO v3 query benchmark (composite predicates)" +run = "mise run bench:v3:query:_run combo_v3 COMBO combo_encrypted_v3" + +[tasks."bench:v3:query:json"] +description = "Run JSON v3 query benchmark (public.json SteVec)" +run = "mise run bench:v3:query:_run json_v3 JSON json_ste_vec_small_v3" + +[tasks."bench:v3:query:smoke"] +description = "Run the new-family scalar smoke bench (fixed 10k table)" +depends = ["postgres", "bench:build"] +run = """ +#!/usr/bin/env bash +set -e +mise run prepare:scalar_smoke_v3 +rm -rf target/criterion/data/main/SMOKE_V3 target/criterion/reports/SMOKE_V3 +mkdir -p results/query/v3 +cargo criterion --bench scalar_smoke_v3 --message-format json > results/query/v3/scalar_smoke_rows_10000.json +echo "Benchmark complete! Results written to results/query/v3/scalar_smoke_rows_10000.json" +""" + +[tasks."bench:v3:query:plaintext"] +description = "Run the plaintext baseline bench (string/integer/json plaintext tables)" +run = "mise run bench:v3:query:_run plaintext_v3 PLAINTEXT string_plaintext integer_plaintext json_small_plaintext" + +[tasks."bench:v3:query:all"] +description = "Run all v3 query benchmarks across tiers up to max_rows (default 1000000)" +run = """ +#!/usr/bin/env bash +set -e +MAX_ROWS="${1:-1000000}" +for rows in 10000 100000 1000000; do + if [ "$rows" -gt "$MAX_ROWS" ]; then break; fi + for fam in exact match ore ope group_by combo json plaintext; do + mise run "bench:v3:query:$fam" "$rows" + done +done +mise run bench:v3:query:smoke +""" + +[tasks."report:v3"] +description = "Overview of EQL v3 query results — median per scenario, slowest first (v3 sibling of `report`). Optional first arg is a bench-id prefix filter." +run = """ +#!/usr/bin/env bash +python3 find_slow_queries.py --all --v3 "$@" +""" + +[tasks."report:v3:slow"] +description = "EQL v3 queries slower than N ms (default 100; v3 sibling of `report:slow`)" +run = """ +#!/usr/bin/env bash +python3 find_slow_queries.py --v3 --ms "${1:-100}" +""" + +[tasks."report:v3:ingest"] +description = "Overview of EQL v3 ingest throughput (v3 sibling of `report:ingest`)" +run = """ +#!/usr/bin/env bash +python3 report_ingest.py --v3 +""" + +[tasks."report:v3-compare"] +description = "Side-by-side v2/v3 comparison on the CLI (medians + delta per scenario/tier). Optional arg = regression threshold percent." +run = """ +#!/usr/bin/env bash +python3 report_v3_compare.py --cli --threshold "${1:-10}" +""" + +[tasks."report:build:v2"] +description = "Rebuild the archived EQL 2.3 report (report/v2/) from the committed v2 baseline results" +run = """ +#!/usr/bin/env bash +set -e +python3 report_benchmarks.py --v2 +""" + +[tasks."report:build:v3-compare"] +description = "Generate the EQL v3 vs v2 comparison report + charts (report/V3_COMPARISON.md, report/v3/*)" +run = """ +#!/usr/bin/env bash +set -e +python3 report_v3_compare.py --threshold "${1:-10}" +""" + [tasks."bench:query:all"] description = "Run all query benchmarks across row-count tiers (10k, 100k, 1M, 10M). Optional arg caps the largest tier, e.g. `mise run bench:query:all 1000000` stops at 1M." run = """ @@ -799,7 +1195,7 @@ python3 find_slow_queries.py --all "$@" """ [tasks."report:build"] -description = "Build the full benchmark report file (Markdown)" +description = "Build the main benchmark report (EQL v3 numbers + v2/plaintext comparison sections)" run = """ #!/usr/bin/env bash set -e diff --git a/report/BENCHMARK_REPORT.md b/report/BENCHMARK_REPORT.md index d214afc..341b025 100644 --- a/report/BENCHMARK_REPORT.md +++ b/report/BENCHMARK_REPORT.md @@ -1,22 +1,27 @@ -# Benchmark Report +# Benchmark Report (EQL v3) This report summarises the performance benchmarks for encrypted database operations. Per-query-type detail lives on its own page — click through from the Query Performance section below. ## Table of Contents 1. [Ingest Throughput](#ingest-throughput) - - [Int](#int) - - [Json Large](#json-large) - - [Json Small](#json-small) - - [Ste Vec Small](#ste-vec-small) - - [String](#string) + - [public.text_eq](#publictext_eq) + - [public.integer_ord](#publicinteger_ord) + - [public.integer_ord_ope](#publicinteger_ord_ope) + - [public.json](#publicjson) + - [public.text_search](#publictext_search) 2. [Query Performance](#query-performance) - [COMBO Queries](combo.md) - [EXACT Queries](exact.md) - [GROUP_BY Queries](group_by.md) - [JSON Queries](json.md) - [MATCH Queries](match.md) + - [OPE Queries](ope.md) - [ORE Queries](ore.md) + - [PLAINTEXT Queries](plaintext.md) + - [SCALAR_SMOKE Queries](scalar_smoke.md) +3. [Comparison vs EQL 2.3](#comparison-vs-eql-23) +4. [Comparison vs plaintext PostgreSQL](#comparison-vs-plaintext-postgresql) --- @@ -34,69 +39,67 @@ Comparing all benchmark types at 10,000 records. ![Total Time Comparison at 10,000 records (excluding ste_vec_large)](ingest_comparison_time_10000_filtered.png) -### Int - -Tests insertion of encrypted integer values. +### public.text_eq | Records | Throughput (records/sec) | Total Time | Avg Memory | |---------|--------------------------|------------|------------| -| 500 | 698.69 | 0.72s | 17.22 MB | -| 1,000 | 1.59K | 0.63s | 20.39 MB | -| 10,000 | 2.13K | 4.70s | 22.25 MB | +| 500 | 911.53 | 0.55s | 18.59 MB | +| 1,000 | 3.96K | 0.25s | 19.91 MB | +| 10,000 | 11.72K | 0.85s | 21.15 MB | -![Ingest Throughput - int](ingest_int_throughput_chart.png) +![Ingest Throughput - category](ingest_category_throughput_chart.png) -![Ingest Total Time - int](ingest_int_time_chart.png) +![Ingest Total Time - category](ingest_category_time_chart.png) -### Json Large +### public.integer_ord -Tests insertion of large encrypted JSON objects with complex nested structures (user info, company, addresses, orders). +Tests insertion of encrypted integer values. | Records | Throughput (records/sec) | Total Time | Avg Memory | |---------|--------------------------|------------|------------| -| 500 | 734.25 | 0.68s | 55.98 MB | -| 1,000 | 2.13K | 0.47s | 95.58 MB | -| 10,000 | 3.59K | 2.79s | 162.06 MB | - -![Ingest Throughput - json_large](ingest_json_large_throughput_chart.png) +| 500 | 604.23 | 0.83s | 19.25 MB | +| 1,000 | 1.55K | 0.64s | 23.65 MB | +| 10,000 | 2.15K | 4.64s | 25.27 MB | -![Ingest Total Time - json_large](ingest_json_large_time_chart.png) +![Ingest Throughput - int](ingest_int_throughput_chart.png) -### Json Small +![Ingest Total Time - int](ingest_int_time_chart.png) -Tests insertion of small encrypted JSON objects (first_name, last_name, age, email). +### public.integer_ord_ope | Records | Throughput (records/sec) | Total Time | Avg Memory | |---------|--------------------------|------------|------------| -| 500 | 665.29 | 0.75s | 16.22 MB | -| 1,000 | 3.68K | 0.27s | 18.05 MB | -| 10,000 | 11.42K | 0.88s | 20.22 MB | +| 500 | 733.76 | 0.68s | 18.60 MB | +| 1,000 | 3.99K | 0.25s | 19.73 MB | +| 10,000 | 11.93K | 0.84s | 21.56 MB | -![Ingest Throughput - json_small](ingest_json_small_throughput_chart.png) +![Ingest Throughput - int_ope](ingest_int_ope_throughput_chart.png) -![Ingest Total Time - json_small](ingest_json_small_time_chart.png) +![Ingest Total Time - int_ope](ingest_int_ope_time_chart.png) -### Ste Vec Small +### public.json Tests insertion of small JSON objects with SteVec (searchable encrypted vector) indexing. | Records | Throughput (records/sec) | Total Time | Avg Memory | |---------|--------------------------|------------|------------| -| 10,000 | 4.03K | 2.48s | 31.90 MB | +| 500 | 821.86 | 0.61s | 24.01 MB | +| 1,000 | 2.43K | 0.41s | 34.58 MB | +| 10,000 | 4.46K | 2.24s | 39.31 MB | ![Ingest Throughput - ste_vec_small](ingest_ste_vec_small_throughput_chart.png) ![Ingest Total Time - ste_vec_small](ingest_ste_vec_small_time_chart.png) -### String +### public.text_search Tests insertion of encrypted string values. | Records | Throughput (records/sec) | Total Time | Avg Memory | |---------|--------------------------|------------|------------| -| 500 | 966.23 | 0.52s | 16.48 MB | -| 1,000 | 3.99K | 0.25s | 18.66 MB | -| 10,000 | 9.65K | 1.04s | 21.23 MB | +| 500 | 565.71 | 0.88s | 23.20 MB | +| 1,000 | 1.04K | 0.96s | 32.66 MB | +| 10,000 | 1.32K | 7.56s | 35.20 MB | ![Ingest Throughput - string](ingest_string_throughput_chart.png) @@ -108,12 +111,79 @@ Per-query-type detail is broken out into separate pages — click into a scenari | Query Type | Scenarios | Tiers | Largest-tier median (no decrypt) | Detail | |-|-|-|-|-| -| COMBO | `bloom_ore_order_limit`, `filtered_group_by`, `top_n_filtered_group_by` | 10,000, 100,000, 1,000,000, 10,000,000 | 86.89ms | [open](combo.md) | -| EXACT | `eql_cast`, `eql_hash` | 10,000, 100,000, 1,000,000, 10,000,000 | 108.58μs | [open](exact.md) | -| GROUP_BY | `low_cardinality_groups_encrypted`, `low_cardinality_groups_plaintext`, `top_n_groups_encrypted`, `top_n_groups_plaintext` | 10,000, 100,000, 1,000,000, 10,000,000 | 568.48ms | [open](group_by.md) | -| JSON | `contains/functional`, `field_eq/bare`, `field_eq/extractor`, `field_eq/functional`, `field_order/functional` | 10,000, 100,000, 1,000,000, 10,000,000 | 370.33μs | [open](json.md) | -| MATCH | `eql_bloom`, `eql_cast_firstname`, `eql_cast_lastname` | 10,000, 100,000, 1,000,000, 10,000,000 | 107.51ms | [open](match.md) | -| ORE | `range_gt_10`, `range_gt_100`, `range_lt_10`, `range_lt_100`, `range_lt_ordered_10` | 10,000, 100,000, 1,000,000, 10,000,000 | 2.01ms | [open](ore.md) | +| COMBO | `bloom_ore_order_limit`, `filtered_group_by`, `top_n_filtered_group_by` | 10,000, 100,000, 1,000,000 | 8.20ms | [open](combo.md) | +| EXACT | `eql_cast`, `eql_hash` | 10,000, 100,000, 1,000,000, 10,000,000 | 124.69μs | [open](exact.md) | +| GROUP_BY | `low_cardinality_groups_encrypted`, `low_cardinality_groups_plaintext`, `top_n_groups_encrypted`, `top_n_groups_plaintext` | 10,000, 100,000, 1,000,000, 10,000,000 | 621.96ms | [open](group_by.md) | +| JSON | `contains/functional`, `field_eq/bare`, `field_eq/extractor`, `field_eq/functional`, `field_gt/functional`, `field_order/functional` | 10,000, 100,000, 1,000,000, 10,000,000 | 434.09μs | [open](json.md) | +| MATCH | `eql_bloom`, `eql_bloom_noindex`, `eql_cast_firstname`, `eql_cast_firstname_noindex`, `eql_cast_lastname`, `eql_cast_lastname_noindex` | 10,000, 100,000, 1,000,000 | 11.57ms | [open](match.md) | +| OPE | `range_gt_10`, `range_gt_100`, `range_lt_10`, `range_lt_100`, `range_lt_ordered_10` | 10,000, 100,000, 1,000,000, 10,000,000 | 215.61μs | [open](ope.md) | +| ORE | `range_gt_10`, `range_gt_100`, `range_lt_10`, `range_lt_100`, `range_lt_ordered_10` | 10,000, 100,000, 1,000,000, 10,000,000 | 685.33μs | [open](ore.md) | +| PLAINTEXT | `exact_eq`, `json_contains`, `json_field_eq`, `range_gt_10`, `range_lt_ordered_10` | 10,000, 100,000, 1,000,000, 10,000,000 | 114.62μs | [open](plaintext.md) | +| SCALAR_SMOKE | `bigint_ord/range_gt_10`, `bigint_ord/range_gt_ordered_10`, `boolean/select_back`, `date_ord/range_gt_10`, `date_ord/range_gt_ordered_10`, `double_ord/range_gt_10`, `double_ord/range_gt_ordered_10`, `numeric_ord/range_gt_10`, `numeric_ord/range_gt_ordered_10`, `timestamp_ord/range_gt_10`, `timestamp_ord/range_gt_ordered_10` | 10,000 | 838.93μs | [open](scalar_smoke.md) | + +## Comparison vs EQL 2.3 + +119 comparable scenario/tier pairs against the committed EQL 2.3 baseline: **4 regressions**, **21 improvements** (beyond ±10%), 33 pairs whose SQL semantics changed between versions (annotated, not flagged). Full table, methodology, and index-engagement audit: [V3_COMPARISON.md](V3_COMPARISON.md). + +| Scenario | Tier | v2 median | v3 median | Δ | | +|-|-|-|-|-|-| +| JSON/json/contains/functional | 10000000 | 848.3 µs | 1.05 ms | +23.3% | 🔴 | +| EXACT/exact/eql_cast | 10000000 | 110.3 µs | 126.6 µs | +14.8% | 🔴 | +| GROUP_BY/group_by/low_cardinality_groups_encrypted | 10000000 | 775.51 ms | 887.48 ms | +14.4% | 🔴 | +| GROUP_BY/group_by/top_n_groups_encrypted | 10000000 | 809.18 ms | 901.04 ms | +11.4% | 🔴 | +| JSON/json/field_order/functional | 100000 | 306.2 µs | 274.8 µs | -10.3% | 🟢 | +| GROUP_BY/group_by/low_cardinality_groups_encrypted | 1000000 | 92.57 ms | 83.05 ms | -10.3% | 🟢 | +| JSON/json/field_eq/functional | 10000000 | 108.8 µs | 97.0 µs | -10.8% | 🟢 | +| JSON/json/field_eq/bare | 10000000 | 108.7 µs | 96.7 µs | -11.0% | 🟢 | +| JSON/json/contains/functional | 100000 | 279.9 µs | 248.8 µs | -11.1% | 🟢 | +| ORE/ore/range_lt_10 | 1000000 | 577.0 µs | 494.6 µs | -14.3% | 🟢 | +| JSON/json/field_order/functional | 10000 | 317.9 µs | 253.3 µs | -20.3% | 🟢 | +| ORE/ore/range_gt_10 | 10000 | 624.6 µs | 497.5 µs | -20.3% | 🟢 | +| ORE/ore/range_gt_10 | 1000000 | 694.1 µs | 542.8 µs | -21.8% | 🟢 | +| ORE/ore/range_lt_10 | 10000 | 595.5 µs | 455.6 µs | -23.5% | 🟢 | +| ORE/ore/range_lt_10 | 100000 | 655.1 µs | 496.4 µs | -24.2% | 🟢 | +| JSON/json/field_order/functional | 1000000 | 356.7 µs | 267.9 µs | -24.9% | 🟢 | +| ORE/ore/range_lt_10 | 10000000 | 748.8 µs | 477.9 µs | -36.2% | 🟢 | +| ORE/ore/range_gt_100 | 10000000 | 4.04 ms | 996.5 µs | -75.3% | 🟢 | +| ORE/ore/range_lt_100 | 100000 | 3.87 ms | 932.2 µs | -75.9% | 🟢 | +| ORE/ore/range_gt_100 | 100000 | 4.16 ms | 972.5 µs | -76.6% | 🟢 | +| ORE/ore/range_gt_100 | 10000 | 4.04 ms | 934.7 µs | -76.9% | 🟢 | +| ORE/ore/range_lt_100 | 10000 | 3.93 ms | 907.0 µs | -76.9% | 🟢 | +| ORE/ore/range_gt_100 | 1000000 | 4.10 ms | 926.7 µs | -77.4% | 🟢 | +| ORE/ore/range_lt_100 | 1000000 | 4.06 ms | 889.4 µs | -78.1% | 🟢 | +| ORE/ore/range_lt_100 | 10000000 | 4.15 ms | 880.5 µs | -78.8% | 🟢 | + +![v3 vs v2 at 10,000 rows](v3/v3_vs_v2_10000.png) + +![v3 vs v2 at 100,000 rows](v3/v3_vs_v2_100000.png) + +![v3 vs v2 at 1,000,000 rows](v3/v3_vs_v2_1000000.png) + +![v3 vs v2 at 10,000,000 rows](v3/v3_vs_v2_10000000.png) + +## Comparison vs plaintext PostgreSQL + +The same query shapes against plaintext tables with equivalent indexes (see `benches/plaintext_v3.rs`). Ratios are encrypted ÷ plaintext median; the JSON plaintext baseline is an unindexed `->` filter, hence ratios below 1. + +| Scenario | 10,000 rows | 100,000 rows | 1,000,000 rows | 10,000,000 rows | +|-|-|-|-|-| +| EXACT/exact/eql_cast | 128.5 µs (1.4×) | 114.8 µs (1.2×) | 124.1 µs (1.3×) | 126.6 µs (1.4×) | +| ORE/ore/range_gt_10 | 497.5 µs (5.2×) | 525.8 µs (6.1×) | 542.8 µs (5.9×) | 539.8 µs (6.1×) | +| ORE/ore/range_lt_ordered_10 | 510.5 µs (5.1×) | 543.5 µs (5.4×) | 518.5 µs (5.2×) | 532.0 µs (5.5×) | +| OPE/ope/range_gt_10 | 122.5 µs (1.3×) | 123.5 µs (1.4×) | 117.6 µs (1.3×) | 126.4 µs (1.4×) | +| OPE/ope/range_lt_ordered_10 | 116.9 µs (1.2×) | 120.3 µs (1.2×) | 118.4 µs (1.2×) | 115.2 µs (1.2×) | +| JSON/json/contains/functional | 231.6 µs (2.1×) | 248.8 µs (1.1×) | 420.5 µs (1.5×) | 1.05 ms (7.1×) | +| JSON/json/field_eq/bare | 111.9 µs (0.5×) | 112.7 µs (0.5×) | 112.0 µs (0.4×) | 96.7 µs (0.7×) | +| GROUP_BY/group_by/low_cardinality_groups_encrypted | 2.11 ms (1.8×) | 19.16 ms (2.0×) | 83.05 ms (2.2×) | 887.48 ms (2.6×) | +| GROUP_BY/group_by/top_n_groups_encrypted | 2.07 ms (1.7×) | 19.90 ms (2.0×) | 85.63 ms (2.2×) | 901.04 ms (2.5×) | + +![encrypted vs plaintext at 10,000 rows](v3/overhead_vs_plaintext_10000.png) + +![encrypted vs plaintext at 100,000 rows](v3/overhead_vs_plaintext_100000.png) + +![encrypted vs plaintext at 1,000,000 rows](v3/overhead_vs_plaintext_1000000.png) + +![encrypted vs plaintext at 10,000,000 rows](v3/overhead_vs_plaintext_10000000.png) --- diff --git a/report/V3_COMPARISON.md b/report/V3_COMPARISON.md new file mode 100644 index 0000000..9fcf8c3 --- /dev/null +++ b/report/V3_COMPARISON.md @@ -0,0 +1,432 @@ +# EQL v3 vs v2.3 — Benchmark Comparison + +Auto-generated by `report_v3_compare.py` (`mise run report:v3-compare`). + +Regression threshold: v3 slower by more than **10%** on a semantics-equivalent scenario. + +Methodology notes: + +- EQL v3 is installed from the pinned release bundle **eql-3.0.0-alpha.3** (`mise run setup-db-v3`). alpha.3 places the per-domain types in `public.*` (`public.text_search`, `public.integer_ord`, `public.json`, …); the raw-jsonb SEM extractors live in `eql_v3_internal`, and the benches call only the public `eql_v3.*` wrappers. +- **Re-baseline status:** the **JSON** tiers (10k–10M) were re-ingested and re-run against alpha.3. The **non-JSON** v3 scenarios below are still the pre-release alpha.2-equivalent measurements and are pending a full alpha.3 re-baseline — treat their absolute numbers accordingly. +- v3 payloads are produced by `eql-bindings::from_v2` over the pinned cipherstash-client's v2.3 output (the supported migration path); conversion cost is inside the measured ingest path. +- The JSON bench queries the encrypted document through the named EQL JSON functions — `eql_v3.jsonb_contains` (GIN over `eql_v3.jsonb_array(value)`) for containment and `eql_v3.jsonb_path_query_first(value, selector)` feeding `eql_v3.eq_term` / `eql_v3.ore_cllw` for field equality/ordering — not raw `jsonb` `@>` / `->`. +- v3 query parameters are stored-shape payloads (no v3 scalar query wire shape exists); server-side timings are unaffected. +- The v3 string column (`text_search`) carries an ORE term v2's unique+match config did not — v3 string rows are wider. +- OPE ciphertexts are real CLLW-OPE terms emitted by cipherstash-client 0.38.1 (Index::new_ope); ordering parity against decrypted plaintext is asserted at bench startup. +- v2 numbers are the committed baseline results (`results/query/`, `results/ingest/`); v3 numbers come from `results/query/v3/`, `results/ingest/v3/`. The baseline was measured in May; same-day v2 re-measurement (2026-07-04) shows ±8-19% cross-session drift at the 10M tier, so 10M flags were re-adjudicated against same-day v2 — see the per-row notes. + +## Query scenarios: v3 vs v2 + +119 comparable scenario/tier pairs — **4 regressions**, 21 improvements beyond ±10%. + +| Scenario | Tier | v2 median | v3 median | Δ | Flag | Note | +|---|---|---|---|---|---|---| +| JSON/json/field_eq/extractor | 1000000 | 463.3 µs | 71.94 ms | +15427.6% | ⚠️ semantics changed | v2 stevec_query GIN → v3 jsonb_contains; every-row-needle plan instability (see notes) | +| JSON/json/field_eq/extractor | 100000 | 466.7 µs | 6.12 ms | +1210.5% | ⚠️ semantics changed | v2 stevec_query GIN → v3 jsonb_contains; every-row-needle plan instability (see notes) | +| JSON/json/field_eq/extractor | 10000 | 496.8 µs | 789.1 µs | +58.8% | ⚠️ semantics changed | v2 stevec_query GIN → v3 jsonb_contains; every-row-needle plan instability (see notes) | +| COMBO/combo/bloom_ore_order_limit | 10000 | 286.9 µs | 440.7 µs | +53.6% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| JSON/json/field_eq/extractor | 10000000 | 418.3 µs | 637.9 µs | +52.5% | ⚠️ semantics changed | v2 stevec_query GIN → v3 jsonb_contains; every-row-needle plan instability (see notes) | +| COMBO/combo/top_n_filtered_group_by | 10000 | 178.4 µs | 244.3 µs | +36.9% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| COMBO/combo/filtered_group_by | 10000 | 178.5 µs | 230.2 µs | +28.9% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| MATCH/match/eql_cast_firstname | 10000 | 152.3 µs | 190.1 µs | +24.8% | ⚠️ semantics changed | v2 LIKE → v3 @> (no LIKE operator in v3; same bloom semantics) | +| JSON/json/contains/functional | 10000000 | 848.3 µs | 1.05 ms | +23.3% | 🔴 REGRESSION | same jsonb_array GIN recipe as v2; 10M delta is posting-list/data-shape | +| COMBO/combo/filtered_group_by | 100000 | 665.2 µs | 783.0 µs | +17.7% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| EXACT/exact/eql_hash | 1000000 | 104.6 µs | 122.1 µs | +16.8% | ⚠️ semantics changed | index type changed: v2 hash → v3 btree on eq_term | +| EXACT/exact/eql_hash | 10000000 | 106.9 µs | 122.8 µs | +14.9% | ⚠️ semantics changed | index type changed: v2 hash → v3 btree on eq_term | +| MATCH/match/eql_cast_lastname | 10000 | 439.7 µs | 504.9 µs | +14.8% | ⚠️ semantics changed | v2 LIKE → v3 @> (no LIKE operator in v3; same bloom semantics) | +| EXACT/exact/eql_cast | 10000000 | 110.3 µs | 126.6 µs | +14.8% | 🔴 REGRESSION | 10M flag adjudicated as baseline drift: v3 is 3.3% FASTER than same-day v2 | +| GROUP_BY/group_by/low_cardinality_groups_encrypted | 10000000 | 775.51 ms | 887.48 ms | +14.4% | 🔴 REGRESSION | 10M flag adjudicated as baseline drift: +6.4% vs same-day v2 | +| EXACT/exact/eql_hash | 100000 | 102.9 µs | 116.4 µs | +13.1% | ⚠️ semantics changed | index type changed: v2 hash → v3 btree on eq_term | +| EXACT/exact/eql_hash | 10000 | 108.7 µs | 121.8 µs | +12.1% | ⚠️ semantics changed | index type changed: v2 hash → v3 btree on eq_term | +| GROUP_BY/group_by/top_n_groups_encrypted | 10000000 | 809.18 ms | 901.04 ms | +11.4% | 🔴 REGRESSION | 10M flag adjudicated as baseline drift: parity (-0.7%) vs same-day v2 | +| MATCH/match/eql_cast_lastname | 100000 | 1.79 ms | 2.00 ms | +11.3% | ⚠️ semantics changed | v2 LIKE → v3 @> (no LIKE operator in v3; same bloom semantics) | +| MATCH/match/eql_bloom | 100000 | 1.75 ms | 1.92 ms | +9.7% | | v3 GIN uses native array_ops on the bloom term (no shipped opclass) | +| MATCH/match/eql_cast_lastname | 1000000 | 14.40 ms | 15.73 ms | +9.2% | ⚠️ semantics changed | v2 LIKE → v3 @> (no LIKE operator in v3; same bloom semantics) | +| MATCH/match/eql_bloom | 1000000 | 14.47 ms | 15.71 ms | +8.6% | | v3 GIN uses native array_ops on the bloom term (no shipped opclass) | +| ORE/ore/range_lt_ordered_10 | 100000 | 502.4 µs | 543.5 µs | +8.2% | | | +| EXACT/exact/eql_cast | 1000000 | 115.1 µs | 124.1 µs | +7.8% | | 10M flag adjudicated as baseline drift: v3 is 3.3% FASTER than same-day v2 | +| EXACT/exact/eql_cast | 10000 | 119.3 µs | 128.5 µs | +7.7% | | 10M flag adjudicated as baseline drift: v3 is 3.3% FASTER than same-day v2 | +| MATCH/match/eql_bloom | 10000 | 405.4 µs | 436.4 µs | +7.6% | | v3 GIN uses native array_ops on the bloom term (no shipped opclass) | +| JSON/json/field_eq/functional | 1000000 | 105.8 µs | 113.3 µs | +7.1% | | same btree plan as v2 (needle matches every row in both versions) | +| JSON/json/field_eq/functional | 10000 | 104.8 µs | 111.8 µs | +6.7% | | same btree plan as v2 (needle matches every row in both versions) | +| JSON/json/field_eq/functional | 100000 | 107.4 µs | 114.3 µs | +6.5% | | same btree plan as v2 (needle matches every row in both versions) | +| ORE/ore/range_lt_ordered_10 | 10000 | 480.9 µs | 510.5 µs | +6.1% | | | +| GROUP_BY/group_by/low_cardinality_groups_plaintext | 100000 | 9.03 ms | 9.57 ms | +6.0% | | | +| MATCH/match_decrypt/eql_bloom | 100000 | 25.70 ms | 27.17 ms | +5.7% | | | +| GROUP_BY/group_by/top_n_groups_plaintext | 100000 | 9.43 ms | 9.96 ms | +5.6% | | | +| JSON/json/field_eq/bare | 100000 | 106.8 µs | 112.7 µs | +5.6% | | same btree plan as v2 (needle matches every row in both versions) | +| EXACT/exact_decrypt/eql_hash | 10000000 | 23.59 ms | 24.83 ms | +5.3% | ⚠️ semantics changed | index type changed: v2 hash → v3 btree on eq_term | +| ORE/ore/range_lt_ordered_10 | 10000000 | 513.3 µs | 532.0 µs | +3.6% | | | +| MATCH/match_decrypt/eql_cast_firstname | 10000 | 24.26 ms | 25.11 ms | +3.5% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| EXACT/exact_decrypt/eql_hash | 100000 | 23.94 ms | 24.67 ms | +3.0% | ⚠️ semantics changed | index type changed: v2 hash → v3 btree on eq_term | +| EXACT/exact_decrypt/eql_cast | 10000000 | 24.10 ms | 24.78 ms | +2.8% | | | +| JSON/json/field_eq/bare | 1000000 | 109.0 µs | 112.0 µs | +2.7% | | same btree plan as v2 (needle matches every row in both versions) | +| GROUP_BY/group_by/top_n_groups_plaintext | 10000 | 1.20 ms | 1.23 ms | +2.7% | | | +| JSON/json/field_eq/bare | 10000 | 109.3 µs | 111.9 µs | +2.4% | | same btree plan as v2 (needle matches every row in both versions) | +| ORE/ore_decrypt/range_gt_10 | 10000000 | 25.44 ms | 26.00 ms | +2.2% | | | +| MATCH/match/eql_cast_firstname | 100000 | 633.3 µs | 645.8 µs | +2.0% | ⚠️ semantics changed | v2 LIKE → v3 @> (no LIKE operator in v3; same bloom semantics) | +| EXACT/exact_decrypt/eql_cast | 10000 | 24.06 ms | 24.53 ms | +2.0% | | | +| EXACT/exact_decrypt/eql_hash | 1000000 | 23.64 ms | 24.08 ms | +1.9% | ⚠️ semantics changed | index type changed: v2 hash → v3 btree on eq_term | +| GROUP_BY/group_by/low_cardinality_groups_plaintext | 10000 | 1.16 ms | 1.18 ms | +1.9% | | | +| MATCH/match_decrypt/eql_cast_firstname | 100000 | 26.41 ms | 26.86 ms | +1.7% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| GROUP_BY/group_by/low_cardinality_groups_plaintext | 10000000 | 339.33 ms | 344.48 ms | +1.5% | | | +| GROUP_BY/group_by/top_n_groups_plaintext | 10000000 | 349.91 ms | 354.84 ms | +1.4% | | | +| EXACT/exact/eql_cast | 100000 | 113.5 µs | 114.8 µs | +1.1% | | 10M flag adjudicated as baseline drift: v3 is 3.3% FASTER than same-day v2 | +| EXACT/exact_decrypt/eql_cast | 1000000 | 23.88 ms | 24.13 ms | +1.0% | | | +| ORE/ore/range_lt_ordered_10 | 1000000 | 513.2 µs | 518.5 µs | +1.0% | | | +| EXACT/exact_decrypt/eql_cast | 100000 | 24.08 ms | 24.30 ms | +0.9% | | | +| ORE/ore_decrypt/range_lt_ordered_10 | 1000000 | 26.86 ms | 26.81 ms | -0.2% | | | +| COMBO/combo/bloom_ore_order_limit | 100000 | 2.08 ms | 2.08 ms | -0.3% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| MATCH/match_decrypt/eql_cast_lastname | 10000 | 26.13 ms | 25.94 ms | -0.7% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| ORE/ore_decrypt/range_gt_10 | 100000 | 25.72 ms | 25.53 ms | -0.7% | | | +| MATCH/match_decrypt/eql_cast_lastname | 100000 | 27.84 ms | 27.51 ms | -1.2% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| EXACT/exact_decrypt/eql_hash | 10000 | 23.96 ms | 23.64 ms | -1.3% | ⚠️ semantics changed | index type changed: v2 hash → v3 btree on eq_term | +| COMBO/combo/top_n_filtered_group_by | 1000000 | 5.29 ms | 5.20 ms | -1.6% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| MATCH/match_decrypt/eql_bloom | 10000 | 26.41 ms | 25.98 ms | -1.6% | | | +| ORE/ore_decrypt/range_lt_10 | 1000000 | 26.97 ms | 26.52 ms | -1.7% | | | +| GROUP_BY/group_by/top_n_groups_encrypted | 100000 | 20.28 ms | 19.90 ms | -1.9% | | 10M flag adjudicated as baseline drift: parity (-0.7%) vs same-day v2 | +| ORE/ore_decrypt/range_lt_ordered_10 | 10000000 | 26.82 ms | 26.24 ms | -2.2% | | | +| JSON/json/contains/functional | 10000 | 237.4 µs | 231.6 µs | -2.4% | | same jsonb_array GIN recipe as v2; 10M delta is posting-list/data-shape | +| JSON/json/contains/functional | 1000000 | 431.5 µs | 420.5 µs | -2.6% | | same jsonb_array GIN recipe as v2; 10M delta is posting-list/data-shape | +| MATCH/match_decrypt/eql_cast_lastname | 1000000 | 39.48 ms | 38.34 ms | -2.9% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| GROUP_BY/group_by/top_n_groups_plaintext | 1000000 | 40.21 ms | 38.59 ms | -4.0% | | | +| ORE/ore_decrypt/range_gt_10 | 1000000 | 27.04 ms | 25.93 ms | -4.1% | | | +| MATCH/match_decrypt/eql_cast_firstname | 1000000 | 30.42 ms | 29.09 ms | -4.4% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| MATCH/match_decrypt/eql_bloom | 1000000 | 39.93 ms | 38.11 ms | -4.6% | | | +| GROUP_BY/group_by/low_cardinality_groups_encrypted | 10000 | 2.22 ms | 2.11 ms | -4.8% | | 10M flag adjudicated as baseline drift: +6.4% vs same-day v2 | +| GROUP_BY/group_by/low_cardinality_groups_plaintext | 1000000 | 39.05 ms | 37.14 ms | -4.9% | | | +| GROUP_BY/group_by/low_cardinality_groups_encrypted | 100000 | 20.24 ms | 19.16 ms | -5.3% | | 10M flag adjudicated as baseline drift: +6.4% vs same-day v2 | +| ORE/ore_decrypt/range_lt_100 | 10000 | 46.05 ms | 42.75 ms | -7.2% | | | +| ORE/ore_decrypt/range_lt_ordered_10 | 10000 | 28.42 ms | 26.33 ms | -7.4% | | | +| ORE/ore_decrypt/range_lt_10 | 10000000 | 28.15 ms | 26.06 ms | -7.4% | | | +| JSON/json/field_order/functional | 10000000 | 367.6 µs | 339.6 µs | -7.6% | | | +| ORE/ore_decrypt/range_gt_100 | 10000 | 46.26 ms | 42.70 ms | -7.7% | | | +| ORE/ore_decrypt/range_gt_10 | 10000 | 29.35 ms | 27.06 ms | -7.8% | | | +| GROUP_BY/group_by/top_n_groups_encrypted | 1000000 | 93.01 ms | 85.63 ms | -7.9% | | 10M flag adjudicated as baseline drift: parity (-0.7%) vs same-day v2 | +| ORE/ore/range_gt_10 | 100000 | 573.5 µs | 525.8 µs | -8.3% | | | +| ORE/ore_decrypt/range_lt_100 | 1000000 | 45.47 ms | 41.65 ms | -8.4% | | | +| ORE/ore_decrypt/range_lt_10 | 10000 | 28.88 ms | 26.32 ms | -8.9% | | | +| ORE/ore/range_gt_10 | 10000000 | 598.2 µs | 539.8 µs | -9.8% | | | +| GROUP_BY/group_by/top_n_groups_encrypted | 10000 | 2.30 ms | 2.07 ms | -10.0% | | 10M flag adjudicated as baseline drift: parity (-0.7%) vs same-day v2 | +| JSON/json/field_order/functional | 100000 | 306.2 µs | 274.8 µs | -10.3% | 🟢 improvement | | +| GROUP_BY/group_by/low_cardinality_groups_encrypted | 1000000 | 92.57 ms | 83.05 ms | -10.3% | 🟢 improvement | 10M flag adjudicated as baseline drift: +6.4% vs same-day v2 | +| JSON/json/field_eq/functional | 10000000 | 108.8 µs | 97.0 µs | -10.8% | 🟢 improvement | same btree plan as v2 (needle matches every row in both versions) | +| JSON/json/field_eq/bare | 10000000 | 108.7 µs | 96.7 µs | -11.0% | 🟢 improvement | same btree plan as v2 (needle matches every row in both versions) | +| JSON/json/contains/functional | 100000 | 279.9 µs | 248.8 µs | -11.1% | 🟢 improvement | same jsonb_array GIN recipe as v2; 10M delta is posting-list/data-shape | +| MATCH/match/eql_cast_firstname | 1000000 | 3.68 ms | 3.26 ms | -11.3% | ⚠️ semantics changed | v2 LIKE → v3 @> (no LIKE operator in v3; same bloom semantics) | +| ORE/ore_decrypt/range_lt_10 | 100000 | 29.44 ms | 26.08 ms | -11.4% | | | +| ORE/ore_decrypt/range_lt_ordered_10 | 100000 | 29.32 ms | 25.49 ms | -13.0% | | | +| ORE/ore/range_lt_10 | 1000000 | 577.0 µs | 494.6 µs | -14.3% | 🟢 improvement | | +| COMBO/combo/bloom_ore_order_limit | 1000000 | 16.64 ms | 14.13 ms | -15.1% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| COMBO/combo/filtered_group_by | 1000000 | 6.40 ms | 5.28 ms | -17.4% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| ORE/ore_decrypt/range_gt_100 | 100000 | 42.13 ms | 33.94 ms | -19.4% | | | +| JSON/json/field_order/functional | 10000 | 317.9 µs | 253.3 µs | -20.3% | 🟢 improvement | | +| ORE/ore/range_gt_10 | 10000 | 624.6 µs | 497.5 µs | -20.3% | 🟢 improvement | | +| ORE/ore_decrypt/range_lt_100 | 10000000 | 46.70 ms | 36.93 ms | -20.9% | | | +| ORE/ore/range_gt_10 | 1000000 | 694.1 µs | 542.8 µs | -21.8% | 🟢 improvement | | +| ORE/ore_decrypt/range_gt_100 | 10000000 | 47.88 ms | 37.38 ms | -21.9% | | | +| ORE/ore_decrypt/range_gt_100 | 1000000 | 47.06 ms | 36.18 ms | -23.1% | | | +| ORE/ore/range_lt_10 | 10000 | 595.5 µs | 455.6 µs | -23.5% | 🟢 improvement | | +| ORE/ore/range_lt_10 | 100000 | 655.1 µs | 496.4 µs | -24.2% | 🟢 improvement | | +| JSON/json/field_order/functional | 1000000 | 356.7 µs | 267.9 µs | -24.9% | 🟢 improvement | | +| COMBO/combo/top_n_filtered_group_by | 100000 | 1.03 ms | 771.8 µs | -25.3% | ⚠️ semantics changed | v2 LIKE → v3 @> | +| ORE/ore_decrypt/range_lt_100 | 100000 | 46.19 ms | 33.61 ms | -27.2% | | | +| ORE/ore/range_lt_10 | 10000000 | 748.8 µs | 477.9 µs | -36.2% | 🟢 improvement | | +| ORE/ore/range_gt_100 | 10000000 | 4.04 ms | 996.5 µs | -75.3% | 🟢 improvement | | +| ORE/ore/range_lt_100 | 100000 | 3.87 ms | 932.2 µs | -75.9% | 🟢 improvement | | +| ORE/ore/range_gt_100 | 100000 | 4.16 ms | 972.5 µs | -76.6% | 🟢 improvement | | +| ORE/ore/range_gt_100 | 10000 | 4.04 ms | 934.7 µs | -76.9% | 🟢 improvement | | +| ORE/ore/range_lt_100 | 10000 | 3.93 ms | 907.0 µs | -76.9% | 🟢 improvement | | +| ORE/ore/range_gt_100 | 1000000 | 4.10 ms | 926.7 µs | -77.4% | 🟢 improvement | | +| ORE/ore/range_lt_100 | 1000000 | 4.06 ms | 889.4 µs | -78.1% | 🟢 improvement | | +| ORE/ore/range_lt_100 | 10000000 | 4.15 ms | 880.5 µs | -78.8% | 🟢 improvement | | + +## v3-only scenarios (no v2 counterpart) + +| Scenario | Median | +|---|---| +| JSON/json/field_gt/functional/10000 | 233.8 µs | +| JSON/json/field_gt/functional/100000 | 844.7 µs | +| JSON/json/field_gt/functional/1000000 | 256.4 µs | +| JSON/json/field_gt/functional/10000000 | 387.5 µs | +| MATCH/match/eql_bloom_noindex/10000 | 56.79 ms | +| MATCH/match/eql_cast_firstname_noindex/10000 | 187.08 ms | +| MATCH/match/eql_cast_lastname_noindex/10000 | 55.16 ms | +| OPE/ope/range_gt_10/10000 | 122.5 µs | +| OPE/ope/range_gt_10/100000 | 123.5 µs | +| OPE/ope/range_gt_10/1000000 | 117.6 µs | +| OPE/ope/range_gt_10/10000000 | 126.4 µs | +| OPE/ope/range_gt_100/10000 | 353.4 µs | +| OPE/ope/range_gt_100/100000 | 652.1 µs | +| OPE/ope/range_gt_100/1000000 | 351.1 µs | +| OPE/ope/range_gt_100/10000000 | 352.5 µs | +| OPE/ope/range_lt_10/10000 | 120.5 µs | +| OPE/ope/range_lt_10/100000 | 126.5 µs | +| OPE/ope/range_lt_10/1000000 | 128.0 µs | +| OPE/ope/range_lt_10/10000000 | 123.2 µs | +| OPE/ope/range_lt_100/10000 | 358.8 µs | +| OPE/ope/range_lt_100/100000 | 3.31 ms | +| OPE/ope/range_lt_100/1000000 | 367.8 µs | +| OPE/ope/range_lt_100/10000000 | 360.7 µs | +| OPE/ope/range_lt_ordered_10/10000 | 116.9 µs | +| OPE/ope/range_lt_ordered_10/100000 | 120.3 µs | +| OPE/ope/range_lt_ordered_10/1000000 | 118.4 µs | +| OPE/ope/range_lt_ordered_10/10000000 | 115.2 µs | +| PLAINTEXT/plaintext/exact_eq/10000 | 94.1 µs | +| PLAINTEXT/plaintext/exact_eq/100000 | 93.6 µs | +| PLAINTEXT/plaintext/exact_eq/1000000 | 93.9 µs | +| PLAINTEXT/plaintext/exact_eq/10000000 | 92.9 µs | +| PLAINTEXT/plaintext/json_contains/10000 | 109.7 µs | +| PLAINTEXT/plaintext/json_contains/100000 | 227.7 µs | +| PLAINTEXT/plaintext/json_contains/1000000 | 289.8 µs | +| PLAINTEXT/plaintext/json_contains/10000000 | 147.6 µs | +| PLAINTEXT/plaintext/json_field_eq/10000 | 212.8 µs | +| PLAINTEXT/plaintext/json_field_eq/100000 | 219.4 µs | +| PLAINTEXT/plaintext/json_field_eq/1000000 | 275.0 µs | +| PLAINTEXT/plaintext/json_field_eq/10000000 | 147.7 µs | +| PLAINTEXT/plaintext/range_gt_10/10000 | 95.6 µs | +| PLAINTEXT/plaintext/range_gt_10/100000 | 86.7 µs | +| PLAINTEXT/plaintext/range_gt_10/1000000 | 91.7 µs | +| PLAINTEXT/plaintext/range_gt_10/10000000 | 89.0 µs | +| PLAINTEXT/plaintext/range_lt_ordered_10/10000 | 99.9 µs | +| PLAINTEXT/plaintext/range_lt_ordered_10/100000 | 100.8 µs | +| PLAINTEXT/plaintext/range_lt_ordered_10/1000000 | 99.9 µs | +| PLAINTEXT/plaintext/range_lt_ordered_10/10000000 | 95.9 µs | +| SMOKE_V3/smoke/bigint_ord/range_gt_10/10000 | 772.0 µs | +| SMOKE_V3/smoke/bigint_ord/range_gt_ordered_10/10000 | 571.9 µs | +| SMOKE_V3/smoke/boolean/select_back/10000 | 97.5 µs | +| SMOKE_V3/smoke/date_ord/range_gt_10/10000 | 1.45 ms | +| SMOKE_V3/smoke/date_ord/range_gt_ordered_10/10000 | 1.32 ms | +| SMOKE_V3/smoke/double_ord/range_gt_10/10000 | 1.06 ms | +| SMOKE_V3/smoke/double_ord/range_gt_ordered_10/10000 | 603.6 µs | +| SMOKE_V3/smoke/numeric_ord/range_gt_10/10000 | 1.01 ms | +| SMOKE_V3/smoke/numeric_ord/range_gt_ordered_10/10000 | 746.3 µs | +| SMOKE_V3/smoke/timestamp_ord/range_gt_10/10000 | 939.6 µs | +| SMOKE_V3/smoke/timestamp_ord/range_gt_ordered_10/10000 | 665.8 µs | + +## Index engagement audit (v3 plans) + +Scenarios matching an expected-index rule must show a non-empty `indexes_used` in their EXPLAIN capture. + +| Scenario | Indexes used | Rows | Status | +|---|---|---|---| +| COMBO/combo/bloom_ore_order_limit/10000 | combo_encrypted_v3_10000_name_match_gin_index | 4 | | +| COMBO/combo/bloom_ore_order_limit/100000 | combo_encrypted_v3_100000_name_match_gin_index | 10 | | +| COMBO/combo/bloom_ore_order_limit/1000000 | combo_encrypted_v3_1000000_name_match_gin_index | 10 | | +| COMBO/combo/filtered_group_by/10000 | combo_encrypted_v3_10000_name_match_gin_index | 4 | | +| COMBO/combo/filtered_group_by/100000 | combo_encrypted_v3_100000_name_match_gin_index | 51 | | +| COMBO/combo/filtered_group_by/1000000 | combo_encrypted_v3_1000000_name_match_gin_index | 237 | | +| COMBO/combo/top_n_filtered_group_by/10000 | combo_encrypted_v3_10000_name_match_gin_index | 4 | | +| COMBO/combo/top_n_filtered_group_by/100000 | combo_encrypted_v3_100000_name_match_gin_index | 10 | | +| COMBO/combo/top_n_filtered_group_by/1000000 | combo_encrypted_v3_1000000_name_match_gin_index | 10 | | +| EXACT/exact/eql_cast/10000 | string_encrypted_v3_10000_eq_btree_index | 1 | ✅ | +| EXACT/exact/eql_cast/100000 | string_encrypted_v3_100000_eq_btree_index | 1 | ✅ | +| EXACT/exact/eql_cast/1000000 | string_encrypted_v3_1000000_eq_btree_index | 1 | ✅ | +| EXACT/exact/eql_cast/10000000 | string_encrypted_v3_10000000_eq_btree_index | 1 | ✅ | +| EXACT/exact/eql_hash/10000 | string_encrypted_v3_10000_eq_btree_index | 1 | ✅ | +| EXACT/exact/eql_hash/100000 | string_encrypted_v3_100000_eq_btree_index | 1 | ✅ | +| EXACT/exact/eql_hash/1000000 | string_encrypted_v3_1000000_eq_btree_index | 1 | ✅ | +| EXACT/exact/eql_hash/10000000 | string_encrypted_v3_10000000_eq_btree_index | 1 | ✅ | +| GROUP_BY/group_by/low_cardinality_groups_encrypted/10000 | — | 1 | | +| GROUP_BY/group_by/low_cardinality_groups_encrypted/100000 | — | 1 | | +| GROUP_BY/group_by/low_cardinality_groups_encrypted/1000000 | — | 1 | | +| GROUP_BY/group_by/low_cardinality_groups_encrypted/10000000 | — | 1 | | +| GROUP_BY/group_by/low_cardinality_groups_plaintext/10000 | — | 1 | | +| GROUP_BY/group_by/low_cardinality_groups_plaintext/100000 | — | 1 | | +| GROUP_BY/group_by/low_cardinality_groups_plaintext/1000000 | — | 1 | | +| GROUP_BY/group_by/low_cardinality_groups_plaintext/10000000 | — | 1 | | +| GROUP_BY/group_by/top_n_groups_encrypted/10000 | — | 10 | | +| GROUP_BY/group_by/top_n_groups_encrypted/100000 | — | 10 | | +| GROUP_BY/group_by/top_n_groups_encrypted/1000000 | — | 10 | | +| GROUP_BY/group_by/top_n_groups_encrypted/10000000 | — | 10 | | +| GROUP_BY/group_by/top_n_groups_plaintext/10000 | — | 10 | | +| GROUP_BY/group_by/top_n_groups_plaintext/100000 | — | 10 | | +| GROUP_BY/group_by/top_n_groups_plaintext/1000000 | — | 10 | | +| GROUP_BY/group_by/top_n_groups_plaintext/10000000 | — | 10 | | +| JSON/json/contains/functional/10000 | json_ste_vec_small_encrypted_v3_10000_jsonb_array_index | 1 | ✅ | +| JSON/json/contains/functional/100000 | json_ste_vec_small_encrypted_v3_100000_jsonb_array_index | 1 | ✅ | +| JSON/json/contains/functional/1000000 | json_ste_vec_small_encrypted_v3_1000000_jsonb_array_index | 1 | ✅ | +| JSON/json/contains/functional/10000000 | json_ste_vec_small_encrypted_v3_10000000_jsonb_array_index | 1 | ✅ | +| JSON/json/field_eq/bare/10000 | json_ste_vec_small_encrypted_v3_10000_field_eq_idx | 10 | ✅ | +| JSON/json/field_eq/bare/100000 | json_ste_vec_small_encrypted_v3_100000_field_eq_idx | 10 | ✅ | +| JSON/json/field_eq/bare/1000000 | json_ste_vec_small_encrypted_v3_1000000_field_eq_idx | 10 | ✅ | +| JSON/json/field_eq/bare/10000000 | json_ste_vec_small_encrypted_v3_10000000_field_eq_idx | 10 | ✅ | +| JSON/json/field_eq/extractor/10000 | — | 10 | | +| JSON/json/field_eq/extractor/100000 | — | 10 | | +| JSON/json/field_eq/extractor/1000000 | — | 10 | | +| JSON/json/field_eq/extractor/10000000 | — | 10 | | +| JSON/json/field_eq/functional/10000 | json_ste_vec_small_encrypted_v3_10000_field_eq_idx | 10 | ✅ | +| JSON/json/field_eq/functional/100000 | json_ste_vec_small_encrypted_v3_100000_field_eq_idx | 10 | ✅ | +| JSON/json/field_eq/functional/1000000 | json_ste_vec_small_encrypted_v3_1000000_field_eq_idx | 10 | ✅ | +| JSON/json/field_eq/functional/10000000 | json_ste_vec_small_encrypted_v3_10000000_field_eq_idx | 10 | ✅ | +| JSON/json/field_gt/functional/10000 | json_ste_vec_small_encrypted_v3_10000_field_order_idx | 10 | | +| JSON/json/field_gt/functional/100000 | json_ste_vec_small_encrypted_v3_100000_field_order_idx | 10 | | +| JSON/json/field_gt/functional/1000000 | json_ste_vec_small_encrypted_v3_1000000_field_order_idx | 10 | | +| JSON/json/field_gt/functional/10000000 | json_ste_vec_small_encrypted_v3_10000000_field_order_idx | 10 | | +| JSON/json/field_order/functional/10000 | json_ste_vec_small_encrypted_v3_10000_field_order_idx | 10 | ✅ | +| JSON/json/field_order/functional/100000 | json_ste_vec_small_encrypted_v3_100000_field_order_idx | 10 | ✅ | +| JSON/json/field_order/functional/1000000 | json_ste_vec_small_encrypted_v3_1000000_field_order_idx | 10 | ✅ | +| JSON/json/field_order/functional/10000000 | json_ste_vec_small_encrypted_v3_10000000_field_order_idx | 10 | ✅ | +| MATCH/match/eql_bloom/10000 | string_encrypted_v3_10000_match_gin_index | 10 | ✅ | +| MATCH/match/eql_bloom/100000 | string_encrypted_v3_100000_match_gin_index | 10 | ✅ | +| MATCH/match/eql_bloom/1000000 | string_encrypted_v3_1000000_match_gin_index | 10 | ✅ | +| MATCH/match/eql_bloom_noindex/10000 | — | 10 | | +| MATCH/match/eql_cast_firstname/10000 | string_encrypted_v3_10000_match_gin_index | 4 | ✅ | +| MATCH/match/eql_cast_firstname/100000 | string_encrypted_v3_100000_match_gin_index | 10 | ✅ | +| MATCH/match/eql_cast_firstname/1000000 | string_encrypted_v3_1000000_match_gin_index | 10 | ✅ | +| MATCH/match/eql_cast_firstname_noindex/10000 | — | 4 | | +| MATCH/match/eql_cast_lastname/10000 | string_encrypted_v3_10000_match_gin_index | 10 | ✅ | +| MATCH/match/eql_cast_lastname/100000 | string_encrypted_v3_100000_match_gin_index | 10 | ✅ | +| MATCH/match/eql_cast_lastname/1000000 | string_encrypted_v3_1000000_match_gin_index | 10 | ✅ | +| MATCH/match/eql_cast_lastname_noindex/10000 | — | 10 | | +| OPE/ope/range_gt_10/10000 | — | 10 | | +| OPE/ope/range_gt_10/100000 | — | 10 | | +| OPE/ope/range_gt_10/1000000 | — | 10 | | +| OPE/ope/range_gt_10/10000000 | — | 10 | | +| OPE/ope/range_gt_100/10000 | — | 100 | | +| OPE/ope/range_gt_100/100000 | — | 100 | | +| OPE/ope/range_gt_100/1000000 | — | 100 | | +| OPE/ope/range_gt_100/10000000 | — | 100 | | +| OPE/ope/range_lt_10/10000 | — | 10 | | +| OPE/ope/range_lt_10/100000 | — | 10 | | +| OPE/ope/range_lt_10/1000000 | — | 10 | | +| OPE/ope/range_lt_10/10000000 | — | 10 | | +| OPE/ope/range_lt_100/10000 | — | 100 | | +| OPE/ope/range_lt_100/100000 | — | 100 | | +| OPE/ope/range_lt_100/1000000 | — | 100 | | +| OPE/ope/range_lt_100/10000000 | — | 100 | | +| OPE/ope/range_lt_ordered_10/10000 | integer_encrypted_ope_v3_10000_ope_index | 10 | ✅ | +| OPE/ope/range_lt_ordered_10/100000 | integer_encrypted_ope_v3_100000_ope_index | 10 | ✅ | +| OPE/ope/range_lt_ordered_10/1000000 | integer_encrypted_ope_v3_1000000_ope_index | 10 | ✅ | +| OPE/ope/range_lt_ordered_10/10000000 | integer_encrypted_ope_v3_10000000_ope_index | 10 | ✅ | +| ORE/ore/range_gt_10/10000 | integer_encrypted_v3_10000_ord_index | 10 | | +| ORE/ore/range_gt_10/100000 | integer_encrypted_v3_100000_ord_index | 10 | | +| ORE/ore/range_gt_10/1000000 | integer_encrypted_v3_1000000_ord_index | 10 | | +| ORE/ore/range_gt_10/10000000 | integer_encrypted_v3_10000000_ord_index | 10 | | +| ORE/ore/range_gt_100/10000 | integer_encrypted_v3_10000_ord_index | 100 | | +| ORE/ore/range_gt_100/100000 | integer_encrypted_v3_100000_ord_index | 100 | | +| ORE/ore/range_gt_100/1000000 | integer_encrypted_v3_1000000_ord_index | 100 | | +| ORE/ore/range_gt_100/10000000 | integer_encrypted_v3_10000000_ord_index | 100 | | +| ORE/ore/range_lt_10/10000 | integer_encrypted_v3_10000_ord_index | 10 | | +| ORE/ore/range_lt_10/100000 | integer_encrypted_v3_100000_ord_index | 10 | | +| ORE/ore/range_lt_10/1000000 | integer_encrypted_v3_1000000_ord_index | 10 | | +| ORE/ore/range_lt_10/10000000 | integer_encrypted_v3_10000000_ord_index | 10 | | +| ORE/ore/range_lt_100/10000 | integer_encrypted_v3_10000_ord_index | 100 | | +| ORE/ore/range_lt_100/100000 | integer_encrypted_v3_100000_ord_index | 100 | | +| ORE/ore/range_lt_100/1000000 | integer_encrypted_v3_1000000_ord_index | 100 | | +| ORE/ore/range_lt_100/10000000 | integer_encrypted_v3_10000000_ord_index | 100 | | +| ORE/ore/range_lt_ordered_10/10000 | integer_encrypted_v3_10000_ord_index | 10 | ✅ | +| ORE/ore/range_lt_ordered_10/100000 | integer_encrypted_v3_100000_ord_index | 10 | ✅ | +| ORE/ore/range_lt_ordered_10/1000000 | integer_encrypted_v3_1000000_ord_index | 10 | ✅ | +| ORE/ore/range_lt_ordered_10/10000000 | integer_encrypted_v3_10000000_ord_index | 10 | ✅ | +| PLAINTEXT/plaintext/exact_eq/10000 | string_plaintext_10000_value_idx | 1 | | +| PLAINTEXT/plaintext/exact_eq/100000 | string_plaintext_100000_value_idx | 1 | | +| PLAINTEXT/plaintext/exact_eq/1000000 | string_plaintext_1000000_value_idx | 1 | | +| PLAINTEXT/plaintext/exact_eq/10000000 | string_plaintext_10000000_value_idx | 1 | | +| PLAINTEXT/plaintext/json_contains/10000 | json_small_plaintext_10000_gin_idx | 10 | | +| PLAINTEXT/plaintext/json_contains/100000 | — | 10 | | +| PLAINTEXT/plaintext/json_contains/1000000 | — | 10 | | +| PLAINTEXT/plaintext/json_contains/10000000 | — | 10 | | +| PLAINTEXT/plaintext/json_field_eq/10000 | — | 10 | | +| PLAINTEXT/plaintext/json_field_eq/100000 | — | 10 | | +| PLAINTEXT/plaintext/json_field_eq/1000000 | — | 10 | | +| PLAINTEXT/plaintext/json_field_eq/10000000 | — | 10 | | +| PLAINTEXT/plaintext/range_gt_10/10000 | — | 10 | | +| PLAINTEXT/plaintext/range_gt_10/100000 | — | 10 | | +| PLAINTEXT/plaintext/range_gt_10/1000000 | — | 10 | | +| PLAINTEXT/plaintext/range_gt_10/10000000 | — | 10 | | +| PLAINTEXT/plaintext/range_lt_ordered_10/10000 | integer_plaintext_10000_value_idx | 10 | | +| PLAINTEXT/plaintext/range_lt_ordered_10/100000 | integer_plaintext_100000_value_idx | 10 | | +| PLAINTEXT/plaintext/range_lt_ordered_10/1000000 | integer_plaintext_1000000_value_idx | 10 | | +| PLAINTEXT/plaintext/range_lt_ordered_10/10000000 | integer_plaintext_10000000_value_idx | 10 | | +| SMOKE_V3/smoke/bigint_ord/range_gt_10/10000 | — | 10 | | +| SMOKE_V3/smoke/bigint_ord/range_gt_ordered_10/10000 | scalar_smoke_v3_bigint_val_ord_idx | 10 | ✅ | +| SMOKE_V3/smoke/date_ord/range_gt_10/10000 | — | 10 | | +| SMOKE_V3/smoke/date_ord/range_gt_ordered_10/10000 | scalar_smoke_v3_date_val_ord_idx | 10 | ✅ | +| SMOKE_V3/smoke/double_ord/range_gt_10/10000 | — | 10 | | +| SMOKE_V3/smoke/double_ord/range_gt_ordered_10/10000 | scalar_smoke_v3_double_val_ord_idx | 10 | ✅ | +| SMOKE_V3/smoke/numeric_ord/range_gt_10/10000 | — | 10 | | +| SMOKE_V3/smoke/numeric_ord/range_gt_ordered_10/10000 | scalar_smoke_v3_numeric_val_ord_idx | 10 | ✅ | +| SMOKE_V3/smoke/timestamp_ord/range_gt_10/10000 | — | 10 | | +| SMOKE_V3/smoke/timestamp_ord/range_gt_ordered_10/10000 | scalar_smoke_v3_timestamp_val_ord_idx | 10 | ✅ | + +## Ingest throughput: v3 vs v2 + +| Bench | Records | v2 rec/s | v3 rec/s | Δ | Note | +|---|---|---|---|---|---| +| encrypt_category_v3 | 500 | — | 912 | | | +| encrypt_category_v3 | 1,000 | — | 3,955 | | | +| encrypt_category_v3 | 10,000 | — | 11,723 | | | +| encrypt_int_ope_v3 | 500 | — | 734 | | real CLLW-OPE op terms (cipherstash-client 0.38.1, Index::new_ope) | +| encrypt_int_ope_v3 | 1,000 | — | 3,989 | | | +| encrypt_int_ope_v3 | 10,000 | — | 11,934 | | | +| encrypt_int_v3 | 500 | 699 | 604 | -13.5% | | +| encrypt_int_v3 | 1,000 | 1,587 | 1,552 | -2.2% | | +| encrypt_int_v3 | 10,000 | 2,127 | 2,154 | +1.3% | | +| encrypt_ste_vec_small_v3 | 500 | — | 822 | | | +| encrypt_ste_vec_small_v3 | 1,000 | — | 2,434 | | | +| encrypt_ste_vec_small_v3 | 10,000 | 4,032 | 4,461 | +10.6% | | +| encrypt_string_v3 | 500 | 966 | 566 | -41.5% | NOT a conversion regression: v3's only eq+match text domain (text_search) also REQUIRES the ORE term, so the config adds Index::new_ore() that v2's unique+match didn't carry — string ingest is capped at ORE-generation speed. A v3 hm+bf-only domain would restore v2 throughput. | +| encrypt_string_v3 | 1,000 | 3,989 | 1,037 | -74.0% | | +| encrypt_string_v3 | 10,000 | 9,649 | 1,323 | -86.3% | | + +## Index build times + +| Table | Build seconds | Recorded | +|---|---|---| +| string_encrypted_v3_10000 | 1 | 2026-07-03T13:10:14Z | +| integer_encrypted_v3_10000 | 1 | 2026-07-03T13:10:22Z | +| integer_encrypted_ope_v3_10000 | 0 | 2026-07-03T13:10:25Z | +| category_encrypted_v3_10000 | 0 | 2026-07-03T13:10:27Z | +| combo_encrypted_v3_10000 | 1 | 2026-07-03T13:10:42Z | +| json_ste_vec_small_encrypted_v3_10000 | 1 | 2026-07-03T13:10:47Z | +| string_encrypted_v3_100000 | 8 | 2026-07-03T13:36:20Z | +| integer_encrypted_v3_100000 | 4 | 2026-07-03T13:38:54Z | +| integer_encrypted_ope_v3_100000 | 0 | 2026-07-03T13:40:47Z | +| category_encrypted_v3_100000 | 1 | 2026-07-03T13:42:37Z | +| combo_encrypted_v3_100000 | 7 | 2026-07-03T13:45:31Z | +| json_ste_vec_small_encrypted_v3_100000 | 6 | 2026-07-03T13:46:31Z | +| string_encrypted_v3_1000000 | 78 | 2026-07-03T14:05:03Z | +| integer_encrypted_v3_1000000 | 44 | 2026-07-03T14:15:06Z | +| integer_encrypted_ope_v3_1000000 | 1 | 2026-07-03T14:16:48Z | +| category_encrypted_v3_1000000 | 1 | 2026-07-03T14:19:32Z | +| combo_encrypted_v3_1000000 | 67 | 2026-07-03T14:42:01Z | +| json_ste_vec_small_encrypted_v3_1000000 | 55 | 2026-07-03T14:46:55Z | +| integer_encrypted_1000000 | 42 | 2026-07-04T00:55:25Z | +| json_ste_vec_small_encrypted_100000 | 15 | 2026-07-04T01:21:47Z | +| integer_encrypted_ope_v3_10000 | 0 | 2026-07-04T01:49:59Z | +| integer_encrypted_ope_v3_100000 | 0 | 2026-07-04T01:51:54Z | +| integer_encrypted_ope_v3_1000000 | 1 | 2026-07-04T01:54:49Z | +| integer_encrypted_ope_v3_10000000 | 8 | 2026-07-04T05:52:51Z | +| json_ste_vec_small_encrypted_v3_10000000 | 270 | 2026-07-04T06:31:25Z | +| integer_encrypted_v3_10000000 | 474 | 2026-07-04T07:55:44Z | +| string_encrypted_v3_10000000 | 896 | 2026-07-04T10:17:38Z | +| category_encrypted_v3_10000000 | 9 | 2026-07-04T12:11:35Z | +| category_encrypted_10000000 | 148 | 2026-07-04T12:34:08Z | +| string_encrypted_10000000 | 342 | 2026-07-04T12:54:54Z | + +## Charts + +![v3_vs_v2_10000](v3/v3_vs_v2_10000.png) + +![overhead_vs_plaintext_10000](v3/overhead_vs_plaintext_10000.png) + +![ore_vs_ope_10000](v3/ore_vs_ope_10000.png) + +![v3_vs_v2_100000](v3/v3_vs_v2_100000.png) + +![overhead_vs_plaintext_100000](v3/overhead_vs_plaintext_100000.png) + +![ore_vs_ope_100000](v3/ore_vs_ope_100000.png) + +![v3_vs_v2_1000000](v3/v3_vs_v2_1000000.png) + +![overhead_vs_plaintext_1000000](v3/overhead_vs_plaintext_1000000.png) + +![ore_vs_ope_1000000](v3/ore_vs_ope_1000000.png) + +![v3_vs_v2_10000000](v3/v3_vs_v2_10000000.png) + +![overhead_vs_plaintext_10000000](v3/overhead_vs_plaintext_10000000.png) + +![ore_vs_ope_10000000](v3/ore_vs_ope_10000000.png) diff --git a/report/combo.md b/report/combo.md index d50a1d0..752fc12 100644 --- a/report/combo.md +++ b/report/combo.md @@ -40,19 +40,15 @@ ON combo_encrypted_10000 USING hash ( **Indexes used by the planner (per data set size):** -- 10,000: `combo_encrypted_10000_name_gin_index` -- 100,000: `combo_encrypted_100000_name_gin_index` -- 1,000,000: `combo_encrypted_1000000_name_gin_index` -- 10,000,000: `combo_encrypted_10000000_name_gin_index` - -*⚠️ = Query time exceeds 100ms* +- 10,000: `combo_encrypted_v3_10000_name_match_gin_index` +- 100,000: `combo_encrypted_v3_100000_name_match_gin_index` +- 1,000,000: `combo_encrypted_v3_1000000_name_match_gin_index` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 4 | 303.27μs | N/A | -| 100,000 | 10 | 2.11ms | N/A | -| 1,000,000 | 10 | 16.53ms | N/A | -| 10,000,000 | 10 | ⚠️ 159.30ms | N/A | +| 10,000 | 4 | 451.00μs | N/A | +| 100,000 | 10 | 2.13ms | N/A | +| 1,000,000 | 10 | 14.14ms | N/A | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -64,8 +60,8 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit Sort - Bitmap Heap Scan on combo_encrypted_10000 - Bitmap Index Scan using combo_encrypted_10000_name_gin_index + Bitmap Heap Scan on combo_encrypted_v3_10000 + Bitmap Index Scan using combo_encrypted_v3_10000_name_match_gin_index ``` Full `EXPLAIN (FORMAT JSON)`: @@ -89,7 +85,7 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 36, "Plans": [ { - "Alias": "combo_encrypted_10000", + "Alias": "combo_encrypted_v3_10000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, @@ -99,32 +95,32 @@ Full `EXPLAIN (FORMAT JSON)`: "Plans": [ { "Async Capable": false, - "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1554,461,1033,91,1393,453}'::smallint[])", - "Index Name": "combo_encrypted_10000_name_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbL>skz&>@ZwHR>sj! '{1554,461,1033,91,1393,453}'::smallint[])", - "Relation Name": "combo_encrypted_10000", - "Startup Cost": 56.22, - "Total Cost": 60.73 + "Recheck Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbL>skz&>@ZwHR>sj! '{1033,1554,453,1393,91,461}'::smallint[])", - "Index Name": "combo_encrypted_100000_name_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJtpEKZ-1_Rlb9xuzbSS7Z^6}IlL&FPAi!hQM-qlov%c*O9uu5-j7QD)aGa`MU~ga '{1033,1554,453,1393,91,461}'::smallint[])", - "Relation Name": "combo_encrypted_100000", - "Startup Cost": 93.35, - "Total Cost": 97.86 + "Recheck Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJtpEKZ-1_Rlb9xuzbSS7Z^6}IlL&FPAi!hQM-qlov%c*O9uu5-j7QD)aGa`MU~ga '{1033,91,461,1393,453,1554}'::smallint[])", - "Index Name": "combo_encrypted_1000000_name_gin_index", - "Node Type": "Bitmap Index Scan", - "Parallel Aware": false, - "Parent Relationship": "Outer", - "Plan Rows": 1, - "Plan Width": 0, - "Startup Cost": 0.0, - "Total Cost": 282.35 - } - ], - "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,91,461,1393,453,1554}'::smallint[])", - "Relation Name": "combo_encrypted_1000000", - "Startup Cost": 282.35, - "Total Cost": 286.86 - } - ], - "Sort Key": [ - "(eql_v2.ore_block_u64_8_256(age))" - ], - "Startup Cost": 286.87, - "Total Cost": 286.87 - } - ], - "Startup Cost": 286.87, - "Total Cost": 286.87 - } - } -] -``` - -**10,000,000 rows** - -``` -Limit - Sort - Bitmap Heap Scan on combo_encrypted_10000000 - Bitmap Index Scan using combo_encrypted_10000000_name_gin_index + Bitmap Heap Scan on combo_encrypted_v3_1000000 + Bitmap Index Scan using combo_encrypted_v3_1000000_name_match_gin_index ``` Full `EXPLAIN (FORMAT JSON)`: @@ -302,7 +227,7 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 36, "Plans": [ { - "Alias": "combo_encrypted_10000000", + "Alias": "combo_encrypted_v3_1000000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, @@ -312,32 +237,32 @@ Full `EXPLAIN (FORMAT JSON)`: "Plans": [ { "Async Capable": false, - "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1393,461,1033,1554,453,91}'::smallint[])", - "Index Name": "combo_encrypted_10000000_name_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK!3*9Wj3Ebjn%k4>m4}Mm}6`(v@xTT!hH9xjbl!rG=xu{D9cc=Q '{1393,461,1033,1554,453,91}'::smallint[])", - "Relation Name": "combo_encrypted_10000000", - "Startup Cost": 2258.22, - "Total Cost": 2262.73 + "Recheck Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK!3*9Wj3Ebjn%k4>m4}Mm}6`(v@xTT!hH9xjbl!rG=xu{D9cc=Q> 'hm'::text))::eql_v2.hmac_256)" + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -434,7 +357,7 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 32, "Plans": [ { - "Alias": "combo_encrypted_10000", + "Alias": "combo_encrypted_v3_10000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, @@ -444,33 +367,33 @@ Full `EXPLAIN (FORMAT JSON)`: "Plans": [ { "Async Capable": false, - "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,91,453,1554,461,1393}'::smallint[])", - "Index Name": "combo_encrypted_10000_name_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJUhfrb`JEtIr&txLSDer*96|pI`;UA|QJV{i$g$y '{1033,91,453,1554,461,1393}'::smallint[])", - "Relation Name": "combo_encrypted_10000", - "Startup Cost": 56.22, - "Total Cost": 60.49 + "Recheck Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJUhfrb`JEtIr&txLSDer*96|pI`;UA|QJV{i$g$y> 'hm'::text))::eql_v2.hmac_256)" + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], - "Startup Cost": 60.5, - "Total Cost": 60.5 + "Startup Cost": 61.0, + "Total Cost": 61.01 } ], - "Startup Cost": 60.5, + "Startup Cost": 61.0, "Strategy": "Sorted", - "Total Cost": 60.52 + "Total Cost": 61.02 } } ] @@ -481,8 +404,8 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Aggregate (Sorted) Sort - Bitmap Heap Scan on combo_encrypted_100000 - Bitmap Index Scan using combo_encrypted_100000_name_gin_index + Bitmap Heap Scan on combo_encrypted_v3_100000 + Bitmap Index Scan using combo_encrypted_v3_100000_name_match_gin_index ``` Full `EXPLAIN (FORMAT JSON)`: @@ -493,7 +416,7 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan": { "Async Capable": false, "Group Key": [ - "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -510,7 +433,7 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 32, "Plans": [ { - "Alias": "combo_encrypted_100000", + "Alias": "combo_encrypted_v3_100000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, @@ -520,33 +443,33 @@ Full `EXPLAIN (FORMAT JSON)`: "Plans": [ { "Async Capable": false, - "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1554,91,1033,453,461,1393}'::smallint[])", - "Index Name": "combo_encrypted_100000_name_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLH8|5ql4M2Q_Pp`vyaAZWp6+X-lgSi|Z5MHiX>KE^)(=s*NOLxQ|R!;$YnKh-wL)>^x9Zn|24Dt^$rm)!b)|?E^*5Z;+q;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_100000\"}, \"v\": 3, \"bf\": [1471, 943, 1346, 1076, 567, 1673], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c35bc10e47437489ceccd697f83c193e402f589e059b223b6367059997df64e15305798f235df5f24135f52eceeed140c773b69166ff84df05ef43cd4979584f524f55026fa0e987397b59cfec41626e7fcd430dd7d4d72a501f0d3e20c3f57e7e6846351d12010108c409522fd5076798228081070549dd640d1a0092d002d9f9b62805158abae3850b48b25f7ba2424196b1224ecf056dd4afce29f352a480118f4c9f2c0fe7331f862cbddff09432f8d19dc48cfcb784e01ba365e32137e3eaea6c4c2acd4d218973067a199c1a9bd37e4047c766fb9a357e39931fa21c24725455138a6d75799b92be48db6550ef6d18539fafae82d416eccded84d87789f48d9353709ec734ac6b535f73c7c86e43\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Index Name": "combo_encrypted_v3_100000_name_match_gin_index", "Node Type": "Bitmap Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 1, "Plan Width": 0, "Startup Cost": 0.0, - "Total Cost": 93.35 + "Total Cost": 93.6 } ], - "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1554,91,1033,453,461,1393}'::smallint[])", - "Relation Name": "combo_encrypted_100000", - "Startup Cost": 93.35, - "Total Cost": 97.61 + "Recheck Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLH8|5ql4M2Q_Pp`vyaAZWp6+X-lgSi|Z5MHiX>KE^)(=s*NOLxQ|R!;$YnKh-wL)>^x9Zn|24Dt^$rm)!b)|?E^*5Z;+q;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_100000\"}, \"v\": 3, \"bf\": [1471, 943, 1346, 1076, 567, 1673], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c35bc10e47437489ceccd697f83c193e402f589e059b223b6367059997df64e15305798f235df5f24135f52eceeed140c773b69166ff84df05ef43cd4979584f524f55026fa0e987397b59cfec41626e7fcd430dd7d4d72a501f0d3e20c3f57e7e6846351d12010108c409522fd5076798228081070549dd640d1a0092d002d9f9b62805158abae3850b48b25f7ba2424196b1224ecf056dd4afce29f352a480118f4c9f2c0fe7331f862cbddff09432f8d19dc48cfcb784e01ba365e32137e3eaea6c4c2acd4d218973067a199c1a9bd37e4047c766fb9a357e39931fa21c24725455138a6d75799b92be48db6550ef6d18539fafae82d416eccded84d87789f48d9353709ec734ac6b535f73c7c86e43\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Relation Name": "combo_encrypted_v3_100000", + "Startup Cost": 93.6, + "Total Cost": 98.12 } ], "Sort Key": [ - "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], - "Startup Cost": 97.62, - "Total Cost": 97.63 + "Startup Cost": 98.13, + "Total Cost": 98.13 } ], - "Startup Cost": 97.62, + "Startup Cost": 98.13, "Strategy": "Sorted", - "Total Cost": 97.64 + "Total Cost": 98.15 } } ] @@ -557,8 +480,8 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Aggregate (Sorted) Sort - Bitmap Heap Scan on combo_encrypted_1000000 - Bitmap Index Scan using combo_encrypted_1000000_name_gin_index + Bitmap Heap Scan on combo_encrypted_v3_1000000 + Bitmap Index Scan using combo_encrypted_v3_1000000_name_match_gin_index ``` Full `EXPLAIN (FORMAT JSON)`: @@ -569,7 +492,7 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan": { "Async Capable": false, "Group Key": [ - "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -586,7 +509,7 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 32, "Plans": [ { - "Alias": "combo_encrypted_1000000", + "Alias": "combo_encrypted_v3_1000000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, @@ -596,109 +519,33 @@ Full `EXPLAIN (FORMAT JSON)`: "Plans": [ { "Async Capable": false, - "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,1033,91,461,1393,1554}'::smallint[])", - "Index Name": "combo_encrypted_1000000_name_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbKd&X$zB8z`*yRf!732|Aj@6>qjSB^1sS$Vw%h{e>9i#x~6z*1*IdoEQeVkw1nOVCi8ZO{!0oK#}5CWZZ8~N4Rlnr$L7wq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_1000000\"}, \"v\": 3, \"bf\": [567, 1076, 1471, 1346, 1673, 943], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c37ac803e7e33616e24d657cb0c13195c32451b0380519d765dbe59a22428dd5e37ad4c87ec1aa1e6dcf9b85af628b3b57d34aa882d23a7d616f346ee8f14d649151d95ccfa6f3aed289823153566a3c0440a315174426e0d07a15733bab9c973e5b7078ae0534ae9bcac756810b2785517f28dcb03722cc94af137415fa1c041bb1821a44875c8bbb0c7f8a1da06c77042bcd5bfd799ca1cd8333d31ed01bfddcfe0a9fadca1ba048a46f9a02ce82f68e78e1c9829fa4552dd71a205a30bca22be8b23ca2c83290983ac3ba5a9f73c0f502b267e1f462149417e3e28b29fd96fafc934c1ca29a9b78d9fbec0deaa25fd5d4b7186e680c64d2136efb47ff8f27364acb539da1a849148f74aed73200c62e\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Index Name": "combo_encrypted_v3_1000000_name_match_gin_index", "Node Type": "Bitmap Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 1, "Plan Width": 0, "Startup Cost": 0.0, - "Total Cost": 282.35 + "Total Cost": 290.85 } ], - "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,1033,91,461,1393,1554}'::smallint[])", - "Relation Name": "combo_encrypted_1000000", - "Startup Cost": 282.35, - "Total Cost": 286.61 + "Recheck Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbKd&X$zB8z`*yRf!732|Aj@6>qjSB^1sS$Vw%h{e>9i#x~6z*1*IdoEQeVkw1nOVCi8ZO{!0oK#}5CWZZ8~N4Rlnr$L7wq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_1000000\"}, \"v\": 3, \"bf\": [567, 1076, 1471, 1346, 1673, 943], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c37ac803e7e33616e24d657cb0c13195c32451b0380519d765dbe59a22428dd5e37ad4c87ec1aa1e6dcf9b85af628b3b57d34aa882d23a7d616f346ee8f14d649151d95ccfa6f3aed289823153566a3c0440a315174426e0d07a15733bab9c973e5b7078ae0534ae9bcac756810b2785517f28dcb03722cc94af137415fa1c041bb1821a44875c8bbb0c7f8a1da06c77042bcd5bfd799ca1cd8333d31ed01bfddcfe0a9fadca1ba048a46f9a02ce82f68e78e1c9829fa4552dd71a205a30bca22be8b23ca2c83290983ac3ba5a9f73c0f502b267e1f462149417e3e28b29fd96fafc934c1ca29a9b78d9fbec0deaa25fd5d4b7186e680c64d2136efb47ff8f27364acb539da1a849148f74aed73200c62e\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Relation Name": "combo_encrypted_v3_1000000", + "Startup Cost": 290.85, + "Total Cost": 295.37 } ], "Sort Key": [ - "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], - "Startup Cost": 286.62, - "Total Cost": 286.63 + "Startup Cost": 295.38, + "Total Cost": 295.38 } ], - "Startup Cost": 286.62, + "Startup Cost": 295.38, "Strategy": "Sorted", - "Total Cost": 286.64 - } - } -] -``` - -**10,000,000 rows** - -``` -Aggregate (Sorted) - Sort - Bitmap Heap Scan on combo_encrypted_10000000 - Bitmap Index Scan using combo_encrypted_10000000_name_gin_index -``` - -Full `EXPLAIN (FORMAT JSON)`: - -```json -[ - { - "Plan": { - "Async Capable": false, - "Group Key": [ - "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" - ], - "Node Type": "Aggregate", - "Parallel Aware": false, - "Partial Mode": "Simple", - "Plan Rows": 1, - "Plan Width": 40, - "Plans": [ - { - "Async Capable": false, - "Node Type": "Sort", - "Parallel Aware": false, - "Parent Relationship": "Outer", - "Plan Rows": 1, - "Plan Width": 32, - "Plans": [ - { - "Alias": "combo_encrypted_10000000", - "Async Capable": false, - "Node Type": "Bitmap Heap Scan", - "Parallel Aware": false, - "Parent Relationship": "Outer", - "Plan Rows": 1, - "Plan Width": 32, - "Plans": [ - { - "Async Capable": false, - "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,453,461,1554,91,1393}'::smallint[])", - "Index Name": "combo_encrypted_10000000_name_gin_index", - "Node Type": "Bitmap Index Scan", - "Parallel Aware": false, - "Parent Relationship": "Outer", - "Plan Rows": 1, - "Plan Width": 0, - "Startup Cost": 0.0, - "Total Cost": 2258.22 - } - ], - "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,453,461,1554,91,1393}'::smallint[])", - "Relation Name": "combo_encrypted_10000000", - "Startup Cost": 2258.22, - "Total Cost": 2262.49 - } - ], - "Sort Key": [ - "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" - ], - "Startup Cost": 2262.5, - "Total Cost": 2262.5 - } - ], - "Startup Cost": 2262.5, - "Strategy": "Sorted", - "Total Cost": 2262.52 + "Total Cost": 295.4 } } ] @@ -744,17 +591,15 @@ ON combo_encrypted_10000 USING hash ( **Indexes used by the planner (per data set size):** -- 10,000: `combo_encrypted_10000_name_gin_index` -- 100,000: `combo_encrypted_100000_name_gin_index` -- 1,000,000: `combo_encrypted_1000000_name_gin_index` -- 10,000,000: `combo_encrypted_10000000_name_gin_index` +- 10,000: `combo_encrypted_v3_10000_name_match_gin_index` +- 100,000: `combo_encrypted_v3_100000_name_match_gin_index` +- 1,000,000: `combo_encrypted_v3_1000000_name_match_gin_index` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 4 | 177.00μs | N/A | -| 100,000 | 10 | 1.01ms | N/A | -| 1,000,000 | 10 | 5.32ms | N/A | -| 10,000,000 | 10 | 52.33ms | N/A | +| 10,000 | 4 | 245.09μs | N/A | +| 100,000 | 10 | 786.23μs | N/A | +| 1,000,000 | 10 | 5.25ms | N/A | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -768,8 +613,8 @@ Limit Sort Aggregate (Sorted) Sort - Bitmap Heap Scan on combo_encrypted_10000 - Bitmap Index Scan using combo_encrypted_10000_name_gin_index + Bitmap Heap Scan on combo_encrypted_v3_10000 + Bitmap Index Scan using combo_encrypted_v3_10000_name_match_gin_index ``` Full `EXPLAIN (FORMAT JSON)`: @@ -795,7 +640,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -813,7 +658,7 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 32, "Plans": [ { - "Alias": "combo_encrypted_10000", + "Alias": "combo_encrypted_v3_10000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, @@ -823,44 +668,44 @@ Full `EXPLAIN (FORMAT JSON)`: "Plans": [ { "Async Capable": false, - "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,1554,91,1393,461,453}'::smallint[])", - "Index Name": "combo_encrypted_10000_name_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLJ@{d+gEr3m|9$?(a<5Y^o6;FpZkwW+twq$9c1+3#Hbqm5C`c1?j6pob<4Idq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_10000\"}, \"v\": 3, \"bf\": [1471, 1346, 567, 1076, 943, 1673], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c357a2e1e684606d053a7d2ea49601d879065c9cfcdcca0cdbfaa451191dabbd50cd556c39b6153a2254d357110460b9b07e97eb7704c3bd2e41190846ea00770cd425c4de22b019e2ef89a44d4a82e106f6a6698cb3d099040376ead796b31d400d66583dc98d18d8c6c5ad0ae5c3b73e572f13127872afbd811fc4f37a0ffd8d15db4add60cf7d6c9f8fee87e7b40214764f859f3177b8a9a80be27d1fe4b04eed3392a810b4f3da263205f3ce3563350be0e9783e3b33fb5a357c727fce4fb325f3074064e90b18dc875a200d888b6028afbf2cbf08e35e171e15b32fa6bd35b57a9e32347ea5cd91aaa200fa1059e614ee03e093ce7e49b2ca66bed0db7265e13f46ba7a55d4acdefa9d4f9cd88145\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Index Name": "combo_encrypted_v3_10000_name_match_gin_index", "Node Type": "Bitmap Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 1, "Plan Width": 0, "Startup Cost": 0.0, - "Total Cost": 56.22 + "Total Cost": 56.47 } ], - "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,1554,91,1393,461,453}'::smallint[])", - "Relation Name": "combo_encrypted_10000", - "Startup Cost": 56.22, - "Total Cost": 60.49 + "Recheck Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLJ@{d+gEr3m|9$?(a<5Y^o6;FpZkwW+twq$9c1+3#Hbqm5C`c1?j6pob<4Idq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_10000\"}, \"v\": 3, \"bf\": [1471, 1346, 567, 1076, 943, 1673], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c357a2e1e684606d053a7d2ea49601d879065c9cfcdcca0cdbfaa451191dabbd50cd556c39b6153a2254d357110460b9b07e97eb7704c3bd2e41190846ea00770cd425c4de22b019e2ef89a44d4a82e106f6a6698cb3d099040376ead796b31d400d66583dc98d18d8c6c5ad0ae5c3b73e572f13127872afbd811fc4f37a0ffd8d15db4add60cf7d6c9f8fee87e7b40214764f859f3177b8a9a80be27d1fe4b04eed3392a810b4f3da263205f3ce3563350be0e9783e3b33fb5a357c727fce4fb325f3074064e90b18dc875a200d888b6028afbf2cbf08e35e171e15b32fa6bd35b57a9e32347ea5cd91aaa200fa1059e614ee03e093ce7e49b2ca66bed0db7265e13f46ba7a55d4acdefa9d4f9cd88145\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Relation Name": "combo_encrypted_v3_10000", + "Startup Cost": 56.47, + "Total Cost": 60.99 } ], "Sort Key": [ - "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], - "Startup Cost": 60.5, - "Total Cost": 60.5 + "Startup Cost": 61.0, + "Total Cost": 61.01 } ], - "Startup Cost": 60.5, + "Startup Cost": 61.0, "Strategy": "Sorted", - "Total Cost": 60.52 + "Total Cost": 61.02 } ], "Sort Key": [ "(count(*)) DESC" ], - "Startup Cost": 60.53, - "Total Cost": 60.53 + "Startup Cost": 61.03, + "Total Cost": 61.04 } ], - "Startup Cost": 60.53, - "Total Cost": 60.53 + "Startup Cost": 61.03, + "Total Cost": 61.04 } } ] @@ -873,8 +718,8 @@ Limit Sort Aggregate (Sorted) Sort - Bitmap Heap Scan on combo_encrypted_100000 - Bitmap Index Scan using combo_encrypted_100000_name_gin_index + Bitmap Heap Scan on combo_encrypted_v3_100000 + Bitmap Index Scan using combo_encrypted_v3_100000_name_match_gin_index ``` Full `EXPLAIN (FORMAT JSON)`: @@ -900,7 +745,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -918,7 +763,7 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 32, "Plans": [ { - "Alias": "combo_encrypted_100000", + "Alias": "combo_encrypted_v3_100000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, @@ -928,44 +773,44 @@ Full `EXPLAIN (FORMAT JSON)`: "Plans": [ { "Async Capable": false, - "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,461,1033,1554,1393,91}'::smallint[])", - "Index Name": "combo_encrypted_100000_name_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbM6EwWN2VRz*I3DdDB#Fmo86+?kTUDQ)3C~$YCfpIWtH3*?`N1MbTs_dsnSw}Szu~U`$sq7vNWOvE$ptPi!+(lKfM!NLJq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_100000\"}, \"v\": 3, \"bf\": [567, 943, 1673, 1346, 1076, 1471], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c34318ae765150f77b3a53a263bc7d2993112769788be44c691b6bb7dd0d108287ccf62da1c7b66cce8a289f4b0952dda6525ef989cd7dc0234274f4210812bc6c6cf77842215f4ee0069d5d53a44978ba9afa08fc508dfb429c9ae59fe09b1273671429c50943643b8d06a953cefefaff93a57437960fae6da97d06605a455e9d42ea642245ab451b32f59c3377a7d22e6cdaf03ea0db72f487cc24ec8cffa2f93bee652ef90dd93ef1a753a3c6b9ec87c1685b79444cdeeff126163034a7b0250223b500e6739e976a0feac92b54cde7c0249b106c1ceb8617407131b893b688bdfaba895f2345ae848dac6078c107cdce8aa0b27658eb23c31483eaa2189f56b7cda0d2d5b068905f006440337a0ae6\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Index Name": "combo_encrypted_v3_100000_name_match_gin_index", "Node Type": "Bitmap Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 1, "Plan Width": 0, "Startup Cost": 0.0, - "Total Cost": 93.35 + "Total Cost": 93.6 } ], - "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,461,1033,1554,1393,91}'::smallint[])", - "Relation Name": "combo_encrypted_100000", - "Startup Cost": 93.35, - "Total Cost": 97.61 + "Recheck Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbM6EwWN2VRz*I3DdDB#Fmo86+?kTUDQ)3C~$YCfpIWtH3*?`N1MbTs_dsnSw}Szu~U`$sq7vNWOvE$ptPi!+(lKfM!NLJq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_100000\"}, \"v\": 3, \"bf\": [567, 943, 1673, 1346, 1076, 1471], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c34318ae765150f77b3a53a263bc7d2993112769788be44c691b6bb7dd0d108287ccf62da1c7b66cce8a289f4b0952dda6525ef989cd7dc0234274f4210812bc6c6cf77842215f4ee0069d5d53a44978ba9afa08fc508dfb429c9ae59fe09b1273671429c50943643b8d06a953cefefaff93a57437960fae6da97d06605a455e9d42ea642245ab451b32f59c3377a7d22e6cdaf03ea0db72f487cc24ec8cffa2f93bee652ef90dd93ef1a753a3c6b9ec87c1685b79444cdeeff126163034a7b0250223b500e6739e976a0feac92b54cde7c0249b106c1ceb8617407131b893b688bdfaba895f2345ae848dac6078c107cdce8aa0b27658eb23c31483eaa2189f56b7cda0d2d5b068905f006440337a0ae6\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Relation Name": "combo_encrypted_v3_100000", + "Startup Cost": 93.6, + "Total Cost": 98.12 } ], "Sort Key": [ - "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], - "Startup Cost": 97.62, - "Total Cost": 97.63 + "Startup Cost": 98.13, + "Total Cost": 98.13 } ], - "Startup Cost": 97.62, + "Startup Cost": 98.13, "Strategy": "Sorted", - "Total Cost": 97.64 + "Total Cost": 98.15 } ], "Sort Key": [ "(count(*)) DESC" ], - "Startup Cost": 97.65, - "Total Cost": 97.66 + "Startup Cost": 98.16, + "Total Cost": 98.16 } ], - "Startup Cost": 97.65, - "Total Cost": 97.66 + "Startup Cost": 98.16, + "Total Cost": 98.16 } } ] @@ -978,113 +823,8 @@ Limit Sort Aggregate (Sorted) Sort - Bitmap Heap Scan on combo_encrypted_1000000 - Bitmap Index Scan using combo_encrypted_1000000_name_gin_index -``` - -Full `EXPLAIN (FORMAT JSON)`: - -```json -[ - { - "Plan": { - "Async Capable": false, - "Node Type": "Limit", - "Parallel Aware": false, - "Plan Rows": 1, - "Plan Width": 40, - "Plans": [ - { - "Async Capable": false, - "Node Type": "Sort", - "Parallel Aware": false, - "Parent Relationship": "Outer", - "Plan Rows": 1, - "Plan Width": 40, - "Plans": [ - { - "Async Capable": false, - "Group Key": [ - "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" - ], - "Node Type": "Aggregate", - "Parallel Aware": false, - "Parent Relationship": "Outer", - "Partial Mode": "Simple", - "Plan Rows": 1, - "Plan Width": 40, - "Plans": [ - { - "Async Capable": false, - "Node Type": "Sort", - "Parallel Aware": false, - "Parent Relationship": "Outer", - "Plan Rows": 1, - "Plan Width": 32, - "Plans": [ - { - "Alias": "combo_encrypted_1000000", - "Async Capable": false, - "Node Type": "Bitmap Heap Scan", - "Parallel Aware": false, - "Parent Relationship": "Outer", - "Plan Rows": 1, - "Plan Width": 32, - "Plans": [ - { - "Async Capable": false, - "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,91,1554,461,1033,1393}'::smallint[])", - "Index Name": "combo_encrypted_1000000_name_gin_index", - "Node Type": "Bitmap Index Scan", - "Parallel Aware": false, - "Parent Relationship": "Outer", - "Plan Rows": 1, - "Plan Width": 0, - "Startup Cost": 0.0, - "Total Cost": 282.35 - } - ], - "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,91,1554,461,1033,1393}'::smallint[])", - "Relation Name": "combo_encrypted_1000000", - "Startup Cost": 282.35, - "Total Cost": 286.61 - } - ], - "Sort Key": [ - "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" - ], - "Startup Cost": 286.62, - "Total Cost": 286.63 - } - ], - "Startup Cost": 286.62, - "Strategy": "Sorted", - "Total Cost": 286.64 - } - ], - "Sort Key": [ - "(count(*)) DESC" - ], - "Startup Cost": 286.65, - "Total Cost": 286.66 - } - ], - "Startup Cost": 286.65, - "Total Cost": 286.66 - } - } -] -``` - -**10,000,000 rows** - -``` -Limit - Sort - Aggregate (Sorted) - Sort - Bitmap Heap Scan on combo_encrypted_10000000 - Bitmap Index Scan using combo_encrypted_10000000_name_gin_index + Bitmap Heap Scan on combo_encrypted_v3_1000000 + Bitmap Index Scan using combo_encrypted_v3_1000000_name_match_gin_index ``` Full `EXPLAIN (FORMAT JSON)`: @@ -1110,7 +850,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -1128,7 +868,7 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 32, "Plans": [ { - "Alias": "combo_encrypted_10000000", + "Alias": "combo_encrypted_v3_1000000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, @@ -1138,44 +878,44 @@ Full `EXPLAIN (FORMAT JSON)`: "Plans": [ { "Async Capable": false, - "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,1554,461,91,1033,1393}'::smallint[])", - "Index Name": "combo_encrypted_10000000_name_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK?n#yHO8S<9OhZ5wwj!b#P6_t|pj)n8K?Zo~dhrsIBju0m)@$tkUG0hZ}l)P{ufwd!^FOb85Lx~{q0-yfvT$p$FPm6Rsq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_1000000\"}, \"v\": 3, \"bf\": [1471, 567, 943, 1076, 1673, 1346], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c3f5daee23452cdc6846ef2bd879e525ea569d3c31dbe369d74c759d578f4c5a5a97a9c8f407a7058b6995f1df3f07cbdf9f7fc96dfc1dfd8ac223d5e8d50a008f3b9d6cded770d4fa28534887f6e9af5130cf7ca08321dc3572af25a063d72618ecdaef2ab55bbb159abea62804432d8d289f0f9aa78adcfda13aa8ca7269e4e34e74bf5ca2045f5b174bdfb58337b8e0ddd6824dc6d6cb1ec3553fd88a2b1d259c33ab069a5d564e2a981077324f60431a8294d8cae96f5b8f120b164c5a2341a34e3242bd4102eedefc38665e5990703d9ed7bbd22c2b7bdb905ed14ed67e6b1a87b6a1544d58e1a69d45d11ddd19630d374848465eefee3327cfedc631f70230eadbbf80547c17dac2524a297e6720\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Index Name": "combo_encrypted_v3_1000000_name_match_gin_index", "Node Type": "Bitmap Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 1, "Plan Width": 0, "Startup Cost": 0.0, - "Total Cost": 2258.22 + "Total Cost": 290.85 } ], - "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,1554,461,91,1033,1393}'::smallint[])", - "Relation Name": "combo_encrypted_10000000", - "Startup Cost": 2258.22, - "Total Cost": 2262.49 + "Recheck Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK?n#yHO8S<9OhZ5wwj!b#P6_t|pj)n8K?Zo~dhrsIBju0m)@$tkUG0hZ}l)P{ufwd!^FOb85Lx~{q0-yfvT$p$FPm6Rsq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_1000000\"}, \"v\": 3, \"bf\": [1471, 567, 943, 1076, 1673, 1346], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c3f5daee23452cdc6846ef2bd879e525ea569d3c31dbe369d74c759d578f4c5a5a97a9c8f407a7058b6995f1df3f07cbdf9f7fc96dfc1dfd8ac223d5e8d50a008f3b9d6cded770d4fa28534887f6e9af5130cf7ca08321dc3572af25a063d72618ecdaef2ab55bbb159abea62804432d8d289f0f9aa78adcfda13aa8ca7269e4e34e74bf5ca2045f5b174bdfb58337b8e0ddd6824dc6d6cb1ec3553fd88a2b1d259c33ab069a5d564e2a981077324f60431a8294d8cae96f5b8f120b164c5a2341a34e3242bd4102eedefc38665e5990703d9ed7bbd22c2b7bdb905ed14ed67e6b1a87b6a1544d58e1a69d45d11ddd19630d374848465eefee3327cfedc631f70230eadbbf80547c17dac2524a297e6720\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Relation Name": "combo_encrypted_v3_1000000", + "Startup Cost": 290.85, + "Total Cost": 295.37 } ], "Sort Key": [ - "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], - "Startup Cost": 2262.5, - "Total Cost": 2262.5 + "Startup Cost": 295.38, + "Total Cost": 295.38 } ], - "Startup Cost": 2262.5, + "Startup Cost": 295.38, "Strategy": "Sorted", - "Total Cost": 2262.52 + "Total Cost": 295.4 } ], "Sort Key": [ "(count(*)) DESC" ], - "Startup Cost": 2262.53, - "Total Cost": 2262.53 + "Startup Cost": 295.41, + "Total Cost": 295.41 } ], - "Startup Cost": 2262.53, - "Total Cost": 2262.53 + "Startup Cost": 295.41, + "Total Cost": 295.41 } } ] diff --git a/report/exact.md b/report/exact.md index d2ce848..0aa1637 100644 --- a/report/exact.md +++ b/report/exact.md @@ -34,17 +34,17 @@ ON string_encrypted_10000 USING GIN ( **Indexes used by the planner (per data set size):** -- 10,000: `string_encrypted_10000_hash_index` -- 100,000: `string_encrypted_100000_hash_index` -- 1,000,000: `string_encrypted_1000000_hash_index` -- 10,000,000: `string_encrypted_10000000_hash_index` +- 10,000: `string_encrypted_v3_10000_eq_btree_index` +- 100,000: `string_encrypted_v3_100000_eq_btree_index` +- 1,000,000: `string_encrypted_v3_1000000_eq_btree_index` +- 10,000,000: `string_encrypted_v3_10000000_eq_btree_index` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 1 | 119.29μs | 24.05ms | -| 100,000 | 1 | 112.11μs | 23.86ms | -| 1,000,000 | 1 | 114.68μs | 23.74ms | -| 10,000,000 | 1 | 102.98μs | 24.26ms | +| 10,000 | 1 | 125.98μs | 24.58ms | +| 100,000 | 1 | 120.73μs | 24.54ms | +| 1,000,000 | 1 | 123.30μs | 24.26ms | +| 10,000,000 | 1 | 140.68μs | 24.79ms | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -55,7 +55,7 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Index Scan using string_encrypted_10000_hash_index on string_encrypted_10000 + Index Scan using string_encrypted_v3_10000_eq_btree_index on string_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -68,26 +68,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 649, "Plans": [ { - "Alias": "string_encrypted_10000", + "Alias": "string_encrypted_v3_10000", "Async Capable": false, - "Index Cond": "(((value).data ->> 'hm'::text) = '0379ecd88462a47250b720767ba169469b55dc5cdda2763c6f29a3e2e3011af4'::text)", - "Index Name": "string_encrypted_10000_hash_index", + "Index Cond": "(((value)::jsonb ->> 'hm'::text) = ((('{\"c\": \"mBbJ@pO<31RWq<2Vo1gF#%gQCBETb!kn=gu2|2J}0jLelmc+1B&xl*WJMGZJ&??7QhzJM7AR)R^oa~Ft;Gcf*^=SZ8Ap{Y9ZJUzWuXn&w#ikBUE~R#1Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"string_encrypted_v3_10000\"}, \"v\": 3, \"bf\": [6, 870, 1786, 1726, 2009, 927, 1853, 551, 1662, 1592, 529, 300, 1710, 488, 167, 621, 485, 19, 88, 1112, 528, 558, 1154, 687, 966, 1603, 1454, 1455, 1268, 393, 569, 309, 463, 1197, 238, 1970, 193, 843, 1824, 1766, 964, 1756, 981, 1325, 1414, 578, 1108, 2012, 296, 1953, 373, 1221, 1675, 1161, 1563, 857, 1854, 1470, 1582, 1911, 884, 1545, 697, 1637, 1066, 38, 1912, 164, 1412, 365, 1651, 207, 17, 277, 62, 699, 761, 923, 1772, 712, 385, 1370, 1925], \"hm\": \"b0b055247cded917baabf9b0200b89d76d32981c1ed299fd2210b3217f5baf57\", \"ob\": [\"c5c5aa2ca88a380754bc68f51c80961f466ccfbf630a65e114447e0fc086de94d65e963662935ec00983ec4e8ac643ce31599f418d5df32d71b4d66e9892c679f909bd89cfe0a01152cbe053126d527a31615775bd8c15940a1850271dacff08bcfb2463b6e4e0e2c1f5d65e2778db270453134bad4d46314f0ce95e8a271753b7b6efa372c122690b9a0f0f3031fbfda479b57c8e5ac902b7711944809b948182f305eaa132dfc25cdb32b699c5fb1dcc607b6bdcec05e65f0f114fe2c26f470609e79c78606ae0edf49443476643a98bb90dc97b833748fd6fc3b5b8317afaeac1ce8bcaca9a2d5dec9df1e25ae856b367a21d056325e85534d89a8a832ae885801e152af64b7f7f73eaaf1f49a2f8be3a7fe210ba811d97ab5e00374f1e567f7c078b37d4e443731e3f8d84a8fe4caeca9267d2e812da5ef3ffe41a7a30ae505d228ea7dcc54e10eceee3a88bf852737c588dbccd9d372054da2caa8038a1e311db50b4f7eeb03b7d3aef8fd3c89f4e21caf21a22fe67e2f42122b0a0b847d30dedf0d65fe828d2744c046ce04505a5c7084226e42f73\", \"951757575757575733f0468c7d82d838dbe077939798e6a3ad43556be5c5ed05ea70a2e354ee8b6f3d0566d065838731e54792d7fc5828ccde3e800c818bc246243c799bbe9f15d5b0b8ef862c5b8e740435aabc91b2babea3dc1f93e9828651582e0b25dd28a2f7e8522b56556151b6ce7ef45ab2fb89af4e88ba5c55eff0f1d8137b92e7b94f88cdf7b76e477a88d906c2c1567ec0c8d7dfa51aec655a24daf78a819637261a1ee677f8cf19140db4143dd4584466db2ce3a856e4341dd24302f7783e9e727d3aede3adddf4df01d81ec4a7393ad26f6fbbbcf5b285058c0692e45cac1f292875afac0da65b33d5e9350561da510541f31ed2da8ecdc429ba91db0deb1f8bf6b519e8433a033e07d0d6c268f57f99f1810357fda0bc8e7dbccf2169e87e15bb2386cf1186f712871413faa946ae6e790e6844dafe73cddb50787d0044db7c7a935004e9c6459640c8642036773e57ae198a70211077dbd3541f8638a7daac3082c479c917ea23a7aabf069a821d04ed213e28fe3f0268b08bfbd525974ca8b403a6d7aa2667a5bd409e2a710d7f9f64a8\"]}'::jsonb)::eql_v3.text_search)::jsonb ->> 'hm'::text))", + "Index Name": "string_encrypted_v3_10000_eq_btree_index", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 1, - "Plan Width": 36, - "Relation Name": "string_encrypted_10000", + "Plan Width": 649, + "Relation Name": "string_encrypted_v3_10000", "Scan Direction": "Forward", - "Startup Cost": 0.0, - "Total Cost": 8.27 + "Startup Cost": 0.41, + "Total Cost": 8.43 } ], - "Startup Cost": 0.0, - "Total Cost": 8.27 + "Startup Cost": 0.41, + "Total Cost": 8.43 } } ] @@ -97,7 +97,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using string_encrypted_100000_hash_index on string_encrypted_100000 + Index Scan using string_encrypted_v3_100000_eq_btree_index on string_encrypted_v3_100000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -110,26 +110,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 635, "Plans": [ { - "Alias": "string_encrypted_100000", + "Alias": "string_encrypted_v3_100000", "Async Capable": false, - "Index Cond": "(((value).data ->> 'hm'::text) = '1cc588acb3d87df5f7b66ccec01912ddba6f9f66fb96939cd2055d45af937af4'::text)", - "Index Name": "string_encrypted_100000_hash_index", + "Index Cond": "(((value)::jsonb ->> 'hm'::text) = ((('{\"c\": \"mBbLN+r8g4YgcBdu+5a_Lnqe6A#q049S2ijJ3B5-T>G%kqL=V?kAf;R~XSl>5Z(?Nrmp-cHXD2slwK}s02`W`yy5>p<#pW>YmsLmarFLO#b!Eg5> 'hm'::text))", + "Index Name": "string_encrypted_v3_100000_eq_btree_index", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 1, - "Plan Width": 36, - "Relation Name": "string_encrypted_100000", + "Plan Width": 635, + "Relation Name": "string_encrypted_v3_100000", "Scan Direction": "Forward", - "Startup Cost": 0.0, - "Total Cost": 8.27 + "Startup Cost": 0.42, + "Total Cost": 8.44 } ], - "Startup Cost": 0.0, - "Total Cost": 8.27 + "Startup Cost": 0.42, + "Total Cost": 8.44 } } ] @@ -139,7 +139,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using string_encrypted_1000000_hash_index on string_encrypted_1000000 + Index Scan using string_encrypted_v3_1000000_eq_btree_index on string_encrypted_v3_1000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -152,26 +152,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 640, "Plans": [ { - "Alias": "string_encrypted_1000000", + "Alias": "string_encrypted_v3_1000000", "Async Capable": false, - "Index Cond": "(((value).data ->> 'hm'::text) = '30906de41a8760c9f4c3a500a5e111c24f8fdde7f8a3bcdbc95cbe76d3697bb3'::text)", - "Index Name": "string_encrypted_1000000_hash_index", + "Index Cond": "(((value)::jsonb ->> 'hm'::text) = ((('{\"c\": \"mBbJdt#m#xF-e-eiNK9exV6i~9!7y^kZw24Q{Ux3r)d74=laAYW?=YKsT+08{odOj1_;s(tmi-sG_stf(ev$Oo>sBBgd=Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"string_encrypted_v3_1000000\"}, \"v\": 3, \"bf\": [220, 422, 1613, 1366, 1893, 677, 748, 621, 167, 884, 1770, 973, 986, 1392, 578, 1098, 1114, 1968, 141, 1529, 290, 1897, 1772, 1106, 964, 981, 1603, 93, 1662, 830, 1066, 1470, 802, 1663, 38, 1325, 1412, 1592, 1487, 788, 1699, 1360, 1370, 1563, 602, 173, 1369, 584, 887, 551, 769, 331, 1710, 365, 296, 1766, 761, 2036, 2018, 1637], \"hm\": \"848bc7b916bdb4038118ecad4ec5cca948ff41d628e9c1c7f79c4b595dda3b4f\", \"ob\": [\"26157d3ada2a0dacf1e9f3d8959225b29bf4516b76043b053b4322e06c45b0bf7094c9b385464299cef6045327c7d2dbb09ac938175caf732efa2fd5fc9d5a04b6e61bc7df41237b3bcc3ea0fae2d492766d799e3c3beeeb24d82f43039473ba8faa768120b72af48d7e60373a1adb47c0fc48bb40bc8f01f4d9fa25c414db43799b04523bd26ef40c2ee80dbea777b741bed5c88384bab3405b928a948a9b35e886d7f3f585f7886e6621c7b18e6da2ef5c16ce142f23eebaf840370767702ad4ca227fba25fe07156c64d0e4786256f1b9fcde333d52ae825a0fe91a3e43945acbbdf38e9f2f65479f59d59c0985275875204b88b056f05f1abccdf10d7428dcfe0cf55f002fce27ff62e6e2b07c90e450311f5898391bc6062e035dd1346c7dce1dea519a88037c45a603adb1b3bd9295d3e633865c4ff98a51b1669c5c04dbcf76739f00b28481107b4166a7582f65387f31df13424b4c491d4c056261aae6888e821a3f86a06e8f24c3136e7ed801d15b3095db408a1a63e2ce7cef8462612c2948cbe34948daede275b3ee8588533668af10763068\"]}'::jsonb)::eql_v3.text_search)::jsonb ->> 'hm'::text))", + "Index Name": "string_encrypted_v3_1000000_eq_btree_index", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 2, - "Plan Width": 36, - "Relation Name": "string_encrypted_1000000", + "Plan Width": 640, + "Relation Name": "string_encrypted_v3_1000000", "Scan Direction": "Forward", - "Startup Cost": 0.0, - "Total Cost": 12.54 + "Startup Cost": 0.56, + "Total Cost": 12.59 } ], - "Startup Cost": 0.0, - "Total Cost": 6.27 + "Startup Cost": 0.56, + "Total Cost": 6.57 } } ] @@ -181,7 +181,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using string_encrypted_10000000_hash_index on string_encrypted_10000000 + Index Scan using string_encrypted_v3_10000000_eq_btree_index on string_encrypted_v3_10000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -194,26 +194,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 636, "Plans": [ { - "Alias": "string_encrypted_10000000", + "Alias": "string_encrypted_v3_10000000", "Async Capable": false, - "Index Cond": "(((value).data ->> 'hm'::text) = 'e361bf6d2ee8c36944302cb9963da12b0e6bbdc563f5e088f8b970b7779cc2fb'::text)", - "Index Name": "string_encrypted_10000000_hash_index", + "Index Cond": "(((value)::jsonb ->> 'hm'::text) = ((('{\"c\": \"mBbLA^%@(97XVTaaM9LYMt-ftBR5CY5R#2|34Hi1MR-oCrXvA%LspSYovTTH9Ey}M> 'hm'::text))", + "Index Name": "string_encrypted_v3_10000000_eq_btree_index", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 8, - "Plan Width": 36, - "Relation Name": "string_encrypted_10000000", + "Plan Width": 636, + "Relation Name": "string_encrypted_v3_10000000", "Scan Direction": "Forward", - "Startup Cost": 0.0, - "Total Cost": 38.14 + "Startup Cost": 0.56, + "Total Cost": 36.7 } ], - "Startup Cost": 0.0, - "Total Cost": 4.77 + "Startup Cost": 0.56, + "Total Cost": 5.08 } } ] @@ -253,17 +253,17 @@ ON string_encrypted_10000 USING GIN ( **Indexes used by the planner (per data set size):** -- 10,000: `string_encrypted_10000_hash_index` -- 100,000: `string_encrypted_100000_hash_index` -- 1,000,000: `string_encrypted_1000000_hash_index` -- 10,000,000: `string_encrypted_10000000_hash_index` +- 10,000: `string_encrypted_v3_10000_eq_btree_index` +- 100,000: `string_encrypted_v3_100000_eq_btree_index` +- 1,000,000: `string_encrypted_v3_1000000_eq_btree_index` +- 10,000,000: `string_encrypted_v3_10000000_eq_btree_index` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 1 | 110.71μs | 24.82ms | -| 100,000 | 1 | 109.71μs | 23.94ms | -| 1,000,000 | 1 | 104.06μs | 24.05ms | -| 10,000,000 | 1 | 107.06μs | 23.66ms | +| 10,000 | 1 | 124.09μs | 23.69ms | +| 100,000 | 1 | 125.41μs | 24.57ms | +| 1,000,000 | 1 | 122.42μs | 24.12ms | +| 10,000,000 | 1 | 121.98μs | 24.98ms | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -274,7 +274,7 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Index Scan using string_encrypted_10000_hash_index on string_encrypted_10000 + Index Scan using string_encrypted_v3_10000_eq_btree_index on string_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -287,26 +287,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 649, "Plans": [ { - "Alias": "string_encrypted_10000", + "Alias": "string_encrypted_v3_10000", "Async Capable": false, - "Index Cond": "(((value).data ->> 'hm'::text) = '0379ecd88462a47250b720767ba169469b55dc5cdda2763c6f29a3e2e3011af4'::text)", - "Index Name": "string_encrypted_10000_hash_index", + "Index Cond": "(((value)::jsonb ->> 'hm'::text) = ((('{\"c\": \"mBbL*j*tj3m5o(Z#9rYvPK@!yBA^dMUbV6lODN0kzh%wSOZvH;SP?cwVd|3(Tlb(y5K95XAh4LoF4BlBpTdz~k>&{o(!)ZtPrXNt`~%ERYb%=RW~FvvY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"string_encrypted_v3_10000\"}, \"v\": 3, \"bf\": [300, 843, 1592, 385, 981, 88, 1197, 1414, 1970, 1824, 569, 1112, 558, 697, 463, 1221, 1925, 1603, 485, 19, 309, 238, 1786, 1637, 488, 2012, 1726, 207, 193, 373, 687, 699, 1710, 528, 927, 164, 277, 62, 529, 1545, 1154, 761, 1470, 966, 1766, 1582, 1066, 296, 1772, 578, 1325, 923, 1370, 1455, 1108, 1953, 1675, 1161, 1454, 167, 2009, 6, 1268, 1651, 1912, 870, 1412, 884, 1563, 38, 1854, 1911, 1756, 712, 551, 964, 393, 365, 857, 621, 1853, 17, 1662], \"hm\": \"b0b055247cded917baabf9b0200b89d76d32981c1ed299fd2210b3217f5baf57\", \"ob\": [\"c5c5aa2ca88a380754bc68f51c80961f466ccfbf630a65e114447e0fc086de94d65e963662935ec00983ec4e8ac643ce31599f418d5df32d71b4d66e9892c679f909bd89cfe0a01152cbe053126d527a31615775bd8c15940a1850271dacff08bcfb2463b6e4e0e2c1f5d65e2778db270453134bad4d46314f0ce95e8a271753b7b6efa372c1226905db028b6741814138b847c3ef7ff694294e05d9bc3eb206b825c928d0798cedad94dba2dec18774787269a2e8a98158e71af371c8280edb61059015d16dd3f6e43644dfccbcad9942e49342a7c5915b9fe7f4d4a912c02e0d61c30725008867b4c6996122a637bc9367ae24cd4e721bfcbdb56830f048d2819a83062346cc2e5409eed776f39ae54261f9f5ce184fdc0a5764e7c9a3f71580984112f1f5cf47835f60b6bcc56ca0bee345fc7047c7e8e7675a2e6097d6a48b7d3cfe9ac52937407bd570bc268ab82e060ddc569f4b08c6f48f8bf77e594ca47198b686529a0086c8ba116595f5e04714be721a235208f6d7ab4f6575d2f3ada740668d4fb7606481bd9265bf2b8c5e1c3cfd7e70449e\", \"951757575757575733f0468c7d82d838dbe077939798e6a3ad43556be5c5ed05ea70a2e354ee8b6f3d0566d065838731e54792d7fc5828ccde3e800c818bc246243c799bbe9f15d5b0b8ef862c5b8e740435aabc91b2babea3dc1f93e9828651582e0b25dd28a2f7e8522b56556151b6ce7ef45ab2fb89af4e88ba5c55eff0f1d8137b92e7b94f88416b4cb4144a3a960ac995d76fcd1dd1821eb2c081aead71ff9a373e62d740c80119a344c6d14a96f2bc78b21849458b507d1b2a2c9ca2b64260122b1834111d7f4582b76cfd0d8ec516a7dc72bdc0d3248ccf39e8182f855b164190e86279d4a7b46b053286fb13aed52abdd9952a168c8cd567b435512ee76f952a17a403d80c254539c7c7018eb2902716688c98008594eb0e77e9ba7e7c41f13080c4088428182db3565a5ec76ec611949cf1a1e2624942eceff2c8e6fa81fe91118c7bd718cd3c476ab3f08d9643c9f2a0ccd8c3d1304f5c3917f1ff31e55743a438dc2a104b61a92440036a90998a8aba29777d63713af08326dfc7340ca68e58c71cec1053a14d0c016ae1aca548d84e1c39ee\"]}'::jsonb)::eql_v3.text_search)::jsonb ->> 'hm'::text))", + "Index Name": "string_encrypted_v3_10000_eq_btree_index", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 1, - "Plan Width": 36, - "Relation Name": "string_encrypted_10000", + "Plan Width": 649, + "Relation Name": "string_encrypted_v3_10000", "Scan Direction": "Forward", - "Startup Cost": 0.0, - "Total Cost": 8.27 + "Startup Cost": 0.41, + "Total Cost": 8.43 } ], - "Startup Cost": 0.0, - "Total Cost": 8.27 + "Startup Cost": 0.41, + "Total Cost": 8.43 } } ] @@ -316,7 +316,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using string_encrypted_100000_hash_index on string_encrypted_100000 + Index Scan using string_encrypted_v3_100000_eq_btree_index on string_encrypted_v3_100000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -329,26 +329,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 635, "Plans": [ { - "Alias": "string_encrypted_100000", + "Alias": "string_encrypted_v3_100000", "Async Capable": false, - "Index Cond": "(((value).data ->> 'hm'::text) = '1cc588acb3d87df5f7b66ccec01912ddba6f9f66fb96939cd2055d45af937af4'::text)", - "Index Name": "string_encrypted_100000_hash_index", + "Index Cond": "(((value)::jsonb ->> 'hm'::text) = ((('{\"c\": \"mBbJSl}Ec!H_TSK+j{`dYu2U2A+WSn+k~c)jauZ$1dPl4hr;4M{-+}t2P>1$}+?t)i&A-hFy)yv#8w{K!4|Jn!!_<<+Oe!$FC%WjGyu3rFLO#b!Eg5> 'hm'::text))", + "Index Name": "string_encrypted_v3_100000_eq_btree_index", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 1, - "Plan Width": 36, - "Relation Name": "string_encrypted_100000", + "Plan Width": 635, + "Relation Name": "string_encrypted_v3_100000", "Scan Direction": "Forward", - "Startup Cost": 0.0, - "Total Cost": 8.27 + "Startup Cost": 0.42, + "Total Cost": 8.44 } ], - "Startup Cost": 0.0, - "Total Cost": 8.27 + "Startup Cost": 0.42, + "Total Cost": 8.44 } } ] @@ -358,7 +358,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using string_encrypted_1000000_hash_index on string_encrypted_1000000 + Index Scan using string_encrypted_v3_1000000_eq_btree_index on string_encrypted_v3_1000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -371,26 +371,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 640, "Plans": [ { - "Alias": "string_encrypted_1000000", + "Alias": "string_encrypted_v3_1000000", "Async Capable": false, - "Index Cond": "(((value).data ->> 'hm'::text) = '30906de41a8760c9f4c3a500a5e111c24f8fdde7f8a3bcdbc95cbe76d3697bb3'::text)", - "Index Name": "string_encrypted_1000000_hash_index", + "Index Cond": "(((value)::jsonb ->> 'hm'::text) = ((('{\"c\": \"mBbLpfeKUBfl{rFVU-@|sB|z?Ay}8nH44)4k_@#DXY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"string_encrypted_v3_1000000\"}, \"v\": 3, \"bf\": [964, 1360, 1369, 830, 1663, 748, 1968, 1710, 1098, 365, 2018, 1766, 331, 884, 38, 1770, 1370, 1529, 1487, 220, 1772, 296, 981, 621, 1114, 141, 2036, 1412, 1366, 1897, 788, 1603, 1066, 986, 1637, 173, 887, 167, 1699, 677, 602, 1563, 761, 769, 973, 584, 93, 1592, 1106, 1470, 290, 1392, 1893, 578, 1662, 802, 1613, 422, 1325, 551], \"hm\": \"848bc7b916bdb4038118ecad4ec5cca948ff41d628e9c1c7f79c4b595dda3b4f\", \"ob\": [\"26157d3ada2a0dacf1e9f3d8959225b29bf4516b76043b053b4322e06c45b0bf7094c9b385464299cef6045327c7d2dbb09ac938175caf732efa2fd5fc9d5a04b6e61bc7df41237b3bcc3ea0fae2d492766d799e3c3beeeb24d82f43039473ba8faa768120b72af48d7e60373a1adb47c0fc48bb40bc8f01f4d9fa25c414db43799b04523bd26ef441d4aa82be97710bebf2a5ab7b20d4f9d5ed764b7f1c85713311594bbc7d4ed56ce568ae730c28fc8bb37ffb6f72486f02f910903a78727abe013d2e3ab2025aecc80da2ecec6fffa65775c9448f76a34940235cdc8b3526de544e0c6eb2803de8016a3e8f59be3f0e8d06aa30aa58543eba5cabad8c17aff95452483600d1a9a901a2b112b66cfc46c33dc710426a84436c3d33bfd8c006a118e0898d3a15c09d1bf97f9b6864c807a8920fa5705c0bba2c274b817a3cf89a1c21e796b47dff20c4da5150996cb965dce5de13e13fce060b001cbce747dfca51cd8dc74da9892a2c1df3a2da233eb30d5a597ad2c76bfd4a9d2b220815681e9163966d85fe30eec8b9ce1dcf3ce84a146a9ddb72d6f6\"]}'::jsonb)::eql_v3.text_search)::jsonb ->> 'hm'::text))", + "Index Name": "string_encrypted_v3_1000000_eq_btree_index", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 2, - "Plan Width": 36, - "Relation Name": "string_encrypted_1000000", + "Plan Width": 640, + "Relation Name": "string_encrypted_v3_1000000", "Scan Direction": "Forward", - "Startup Cost": 0.0, - "Total Cost": 12.54 + "Startup Cost": 0.56, + "Total Cost": 12.59 } ], - "Startup Cost": 0.0, - "Total Cost": 6.27 + "Startup Cost": 0.56, + "Total Cost": 6.57 } } ] @@ -400,7 +400,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using string_encrypted_10000000_hash_index on string_encrypted_10000000 + Index Scan using string_encrypted_v3_10000000_eq_btree_index on string_encrypted_v3_10000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -413,26 +413,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 636, "Plans": [ { - "Alias": "string_encrypted_10000000", + "Alias": "string_encrypted_v3_10000000", "Async Capable": false, - "Index Cond": "(((value).data ->> 'hm'::text) = 'e361bf6d2ee8c36944302cb9963da12b0e6bbdc563f5e088f8b970b7779cc2fb'::text)", - "Index Name": "string_encrypted_10000000_hash_index", + "Index Cond": "(((value)::jsonb ->> 'hm'::text) = ((('{\"c\": \"mBbLqC5@G1suIviQg^nWXnOg?BbiPoYlp6+G9t?!&!?K%ASRq!)qQ37AlfBV@ejYDkVIUE#2}J{*(X&vygtFk*+>$~{febuEPC^=d=Ht)hn?;Yg=(dCVQh6}#1Q2)NxIzjOYXJFCv9j}(_#\", \"i\": {\"c\": \"value\", \"t\": \"string_encrypted_v3_10000000\"}, \"v\": 3, \"bf\": [2021, 286, 410, 802, 1065, 386, 780, 1341, 1467, 632, 289, 1670, 516, 402, 1254, 808, 1451, 36, 1699, 1664, 1676, 1315, 38, 1081, 1075, 1405, 607, 1875, 341, 951, 408, 556, 1453, 426, 295, 1767, 166, 564, 151, 1885, 1589, 586, 804, 315, 1877, 792, 474, 902, 1007, 1821, 83, 1762, 1751, 634, 925, 417, 677, 1350, 434, 1097, 1693, 1952, 1348, 870, 1590, 1241, 1309, 1058, 637, 20, 1355, 763, 383, 1805, 1064, 1765, 159, 1774, 1593, 464, 661, 723, 1645, 1671, 588, 1561, 620, 750, 1641], \"hm\": \"d2724b9d2d45e0f740a3e916f1c6dbd21ba93c51b1e298a24d6018ba6044696d\", \"ob\": [\"e23a02c59ee11eab8020a79df213755783bcaf970aaf69061eac8ea97b8b912015cb1436737b200f5b9a3094a55f8766eab33944b6845c16adecc15df7879a9d6ac329cc890a2ed026395d422c1de4f0221f10655a3fa5dd3617fd9587add7ca996d485751069db560add03feed5fd5616682fb53c2680db98d951dcf77d2b35ac8b002486588470df6572451311826120cb16cb80f64253c8b50c85154266fd70ff15fd2858b9e6770ba811816ccf00a648fe382f730637bbe32ca7200e7c3949d50c3c7b36a27e4a1f0c53998479afb8d3fce537b7e01102ad77477f182da29923fc84a285ecc7b9b003acbdaf56783f7e773f88a6cd47e0e157d533e8a169ab6d3fdef0a292a620f89d04a2f1926ba4d7826c49a04ba122e3e30bf1e068327e2cb438a859b6801a52a38da654bf9c0f647c1e4c35e1b23e42a74621ae027c23322becbc337879fb230f3b019516fbc6b38e1bda57bac2286b9e471f9042b2cb578cde41f66bcd23c03e6b2d04d97f63fc70cddd8ad73f82a6ee293431b451bcfa17f5e5bd7f1a26f73d8eae9312ac507e925e77f9a8c7\", \"6e8a31fdfdfdfdfdd2a053164937bd39150b308f9210a6e0cdc08b07417c519d6ad5de4cd889057cbc2a7f8adf8c7b3ddcc2473e84b00b73a4d10f0e589325765d79859d47ade23cc46291670457cb1ba250da2b8b65b6c81fb158654d6d129a6e6e3a4955e7f9915b203582b0e8cd55897c95fecb19f69bf075819846b0efbe80f131fd8b586e2c66cb75d1cdebeb53ed1fac08762e77a03c76bd6b3c30ed6506f8979827234f39bb0c7a2854e0f559f330b220509ad0b637e0e591d2ad107dfc546bba015d25704e9884a83a918ac136dfdfd858aa5dd3b4154e84a54859faced3ab538d993caf8be511d26ed0dcf8991adfa956bda96ed4d1bcef8f4819a99acd9560c825ead72134b715b07156deb9538641936a96d10f8ab163af40d54011ca03e2caaef477ac36c9b56ca5ec2a930d75b8b4c35e45e40d3be8419f71dc16c45031f9f5a5d6c0a2719f84acf367c754318d7d6a0d65af7bd1f00e4b1df511b3af76e98fc701655bcdc5c9765b7539e6918b316a6b045ee5a463e5bf2bed05ce9e6a6947ee524391cd85db4397c688006e171da346bd\"]}'::jsonb)::eql_v3.text_search)::jsonb ->> 'hm'::text))", + "Index Name": "string_encrypted_v3_10000000_eq_btree_index", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 8, - "Plan Width": 36, - "Relation Name": "string_encrypted_10000000", + "Plan Width": 636, + "Relation Name": "string_encrypted_v3_10000000", "Scan Direction": "Forward", - "Startup Cost": 0.0, - "Total Cost": 38.14 + "Startup Cost": 0.56, + "Total Cost": 36.7 } ], - "Startup Cost": 0.0, - "Total Cost": 4.77 + "Startup Cost": 0.56, + "Total Cost": 5.08 } } ] diff --git a/report/group_by.md b/report/group_by.md index 399e136..4146dfc 100644 --- a/report/group_by.md +++ b/report/group_by.md @@ -35,10 +35,10 @@ ON category_encrypted_10000 using hash ( | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 1 | 2.21ms | N/A | -| 100,000 | 1 | 20.10ms | N/A | -| 1,000,000 | 1 | 95.95ms | N/A | -| 10,000,000 | 1 | ⚠️ 789.77ms | N/A | +| 10,000 | 1 | 2.17ms | N/A | +| 100,000 | 1 | 19.31ms | N/A | +| 1,000,000 | 1 | 83.25ms | N/A | +| 10,000,000 | 1 | ⚠️ 899.99ms | N/A | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -50,7 +50,7 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Aggregate Aggregate (Hashed) - Seq Scan on category_encrypted_10000 + Seq Scan on category_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -69,7 +69,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "(((category_encrypted_10000.value).data ->> 'hm'::text))::eql_v2.hmac_256" + "(((category_encrypted_v3_10000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -80,26 +80,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Planned Partitions": 0, "Plans": [ { - "Alias": "category_encrypted_10000", + "Alias": "category_encrypted_v3_10000", "Async Capable": false, "Node Type": "Seq Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 10000, "Plan Width": 32, - "Relation Name": "category_encrypted_10000", + "Relation Name": "category_encrypted_v3_10000", "Startup Cost": 0.0, - "Total Cost": 602.0 + "Total Cost": 542.0 } ], - "Startup Cost": 627.0, + "Startup Cost": 567.0, "Strategy": "Hashed", - "Total Cost": 630.12 + "Total Cost": 570.12 } ], - "Startup Cost": 633.25, + "Startup Cost": 573.25, "Strategy": "Plain", - "Total Cost": 633.26 + "Total Cost": 573.26 } } ] @@ -110,7 +110,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Aggregate Aggregate (Hashed) - Seq Scan on category_encrypted_100000 + Seq Scan on category_encrypted_v3_100000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -129,7 +129,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "(((category_encrypted_100000.value).data ->> 'hm'::text))::eql_v2.hmac_256" + "(((category_encrypted_v3_100000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -140,26 +140,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Planned Partitions": 0, "Plans": [ { - "Alias": "category_encrypted_100000", + "Alias": "category_encrypted_v3_100000", "Async Capable": false, "Node Type": "Seq Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 100000, "Plan Width": 32, - "Relation Name": "category_encrypted_100000", + "Relation Name": "category_encrypted_v3_100000", "Startup Cost": 0.0, - "Total Cost": 6066.0 + "Total Cost": 5417.0 } ], - "Startup Cost": 6316.0, + "Startup Cost": 5667.0, "Strategy": "Hashed", - "Total Cost": 6319.12 + "Total Cost": 5670.12 } ], - "Startup Cost": 6322.25, + "Startup Cost": 5673.25, "Strategy": "Plain", - "Total Cost": 6322.26 + "Total Cost": 5673.26 } } ] @@ -173,7 +173,7 @@ Aggregate Gather Merge Sort Aggregate (Hashed) - Seq Scan on category_encrypted_1000000 + Seq Scan on category_encrypted_v3_1000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -192,7 +192,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "((((category_encrypted_1000000.value).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((category_encrypted_v3_1000000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], "Node Type": "Group", "Parallel Aware": false, @@ -219,7 +219,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "(((category_encrypted_1000000.value).data ->> 'hm'::text))::eql_v2.hmac_256" + "(((category_encrypted_v3_1000000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -230,42 +230,42 @@ Full `EXPLAIN (FORMAT JSON)`: "Planned Partitions": 0, "Plans": [ { - "Alias": "category_encrypted_1000000", + "Alias": "category_encrypted_v3_1000000", "Async Capable": false, "Node Type": "Seq Scan", "Parallel Aware": true, "Parent Relationship": "Outer", - "Plan Rows": 416656, + "Plan Rows": 416665, "Plan Width": 32, - "Relation Name": "category_encrypted_1000000", + "Relation Name": "category_encrypted_v3_1000000", "Startup Cost": 0.0, - "Total Cost": 52840.2 + "Total Cost": 46875.32 } ], - "Startup Cost": 53881.84, + "Startup Cost": 47916.98, "Strategy": "Hashed", - "Total Cost": 53884.96 + "Total Cost": 47920.1 } ], "Sort Key": [ - "((((category_encrypted_1000000.value).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((category_encrypted_v3_1000000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], - "Startup Cost": 53894.92, - "Total Cost": 53895.55 + "Startup Cost": 47930.06, + "Total Cost": 47930.69 } ], - "Startup Cost": 54894.94, - "Total Cost": 54953.28, + "Startup Cost": 48930.09, + "Total Cost": 48988.42, "Workers Planned": 2 } ], - "Startup Cost": 54894.94, - "Total Cost": 54955.16 + "Startup Cost": 48930.09, + "Total Cost": 48990.3 } ], - "Startup Cost": 54958.28, + "Startup Cost": 48993.42, "Strategy": "Plain", - "Total Cost": 54958.29 + "Total Cost": 48993.43 } } ] @@ -279,7 +279,7 @@ Aggregate Gather Merge Sort Aggregate (Hashed) - Seq Scan on category_encrypted_10000000 + Seq Scan on category_encrypted_v3_10000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -298,7 +298,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "((((category_encrypted_10000000.value).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((category_encrypted_v3_10000000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], "Node Type": "Group", "Parallel Aware": false, @@ -325,7 +325,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "(((category_encrypted_10000000.value).data ->> 'hm'::text))::eql_v2.hmac_256" + "(((category_encrypted_v3_10000000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -336,42 +336,42 @@ Full `EXPLAIN (FORMAT JSON)`: "Planned Partitions": 0, "Plans": [ { - "Alias": "category_encrypted_10000000", + "Alias": "category_encrypted_v3_10000000", "Async Capable": false, "Node Type": "Seq Scan", "Parallel Aware": true, "Parent Relationship": "Outer", - "Plan Rows": 4166822, + "Plan Rows": 4166670, "Plan Width": 32, - "Relation Name": "category_encrypted_10000000", + "Relation Name": "category_encrypted_v3_10000000", "Startup Cost": 0.0, - "Total Cost": 528325.28 + "Total Cost": 468750.38 } ], - "Startup Cost": 538742.33, + "Startup Cost": 479167.05, "Strategy": "Hashed", - "Total Cost": 538745.46 + "Total Cost": 479170.17 } ], "Sort Key": [ - "((((category_encrypted_10000000.value).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((category_encrypted_v3_10000000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], - "Startup Cost": 538755.41, - "Total Cost": 538756.04 + "Startup Cost": 479180.13, + "Total Cost": 479180.76 } ], - "Startup Cost": 539755.44, - "Total Cost": 539813.77, + "Startup Cost": 480180.16, + "Total Cost": 480238.49, "Workers Planned": 2 } ], - "Startup Cost": 539755.44, - "Total Cost": 539815.65 + "Startup Cost": 480180.16, + "Total Cost": 480240.37 } ], - "Startup Cost": 539818.77, + "Startup Cost": 480243.49, "Strategy": "Plain", - "Total Cost": 539818.78 + "Total Cost": 480243.5 } } ] @@ -403,10 +403,10 @@ SELECT count(*) FROM (SELECT 1 FROM {TABLE} GROUP BY value) g | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 1 | 1.17ms | N/A | -| 100,000 | 1 | 9.14ms | N/A | -| 1,000,000 | 1 | 40.41ms | N/A | -| 10,000,000 | 1 | ⚠️ 341.69ms | N/A | +| 10,000 | 1 | 1.21ms | N/A | +| 100,000 | 1 | 9.60ms | N/A | +| 1,000,000 | 1 | 37.13ms | N/A | +| 10,000,000 | 1 | ⚠️ 343.93ms | N/A | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -517,17 +517,17 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 8, "Relation Name": "category_plaintext_100000", "Startup Cost": 0.0, - "Total Cost": 1544.0 + "Total Cost": 1541.0 } ], - "Startup Cost": 1794.0, + "Startup Cost": 1791.0, "Strategy": "Hashed", - "Total Cost": 1796.5 + "Total Cost": 1793.5 } ], - "Startup Cost": 1799.62, + "Startup Cost": 1796.62, "Strategy": "Plain", - "Total Cost": 1799.63 + "Total Cost": 1796.63 } } ] @@ -607,33 +607,33 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 8, "Relation Name": "category_plaintext_1000000", "Startup Cost": 0.0, - "Total Cost": 9574.67 + "Total Cost": 9572.67 } ], - "Startup Cost": 10616.33, + "Startup Cost": 10614.33, "Strategy": "Hashed", - "Total Cost": 10618.83 + "Total Cost": 10616.83 } ], "Sort Key": [ "category_plaintext_1000000.value" ], - "Startup Cost": 10628.79, - "Total Cost": 10629.42 + "Startup Cost": 10626.79, + "Total Cost": 10627.42 } ], - "Startup Cost": 11628.82, - "Total Cost": 11687.15, + "Startup Cost": 11626.82, + "Total Cost": 11685.15, "Workers Planned": 2 } ], - "Startup Cost": 11628.82, - "Total Cost": 11688.4 + "Startup Cost": 11626.82, + "Total Cost": 11686.4 } ], - "Startup Cost": 11691.53, + "Startup Cost": 11689.53, "Strategy": "Plain", - "Total Cost": 11691.54 + "Total Cost": 11689.54 } } ] @@ -709,37 +709,37 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Seq Scan", "Parallel Aware": true, "Parent Relationship": "Outer", - "Plan Rows": 4166275, + "Plan Rows": 4166608, "Plan Width": 8, "Relation Name": "category_plaintext_10000000", "Startup Cost": 0.0, - "Total Cost": 95774.75 + "Total Cost": 95721.08 } ], - "Startup Cost": 106190.43, + "Startup Cost": 106137.6, "Strategy": "Hashed", - "Total Cost": 106192.93 + "Total Cost": 106140.1 } ], "Sort Key": [ "category_plaintext_10000000.value" ], - "Startup Cost": 106202.89, - "Total Cost": 106203.52 + "Startup Cost": 106150.06, + "Total Cost": 106150.69 } ], - "Startup Cost": 107202.91, - "Total Cost": 107261.25, + "Startup Cost": 107150.08, + "Total Cost": 107208.42, "Workers Planned": 2 } ], - "Startup Cost": 107202.91, - "Total Cost": 107262.5 + "Startup Cost": 107150.08, + "Total Cost": 107209.67 } ], - "Startup Cost": 107265.63, + "Startup Cost": 107212.8, "Strategy": "Plain", - "Total Cost": 107265.64 + "Total Cost": 107212.81 } } ] @@ -780,10 +780,10 @@ ON category_encrypted_10000 using hash ( | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 10 | 2.53ms | N/A | -| 100,000 | 10 | 20.28ms | N/A | -| 1,000,000 | 10 | 92.97ms | N/A | -| 10,000,000 | 10 | ⚠️ 815.42ms | N/A | +| 10,000 | 10 | 2.11ms | N/A | +| 100,000 | 10 | 19.99ms | N/A | +| 1,000,000 | 10 | 88.02ms | N/A | +| 10,000,000 | 10 | ⚠️ 912.90ms | N/A | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -796,7 +796,7 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI Limit Sort Aggregate (Hashed) - Seq Scan on category_encrypted_10000 + Seq Scan on category_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -822,7 +822,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "(((value).data ->> 'hm'::text))::eql_v2.hmac_256" + "(((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -833,32 +833,32 @@ Full `EXPLAIN (FORMAT JSON)`: "Planned Partitions": 0, "Plans": [ { - "Alias": "category_encrypted_10000", + "Alias": "category_encrypted_v3_10000", "Async Capable": false, "Node Type": "Seq Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 10000, "Plan Width": 32, - "Relation Name": "category_encrypted_10000", + "Relation Name": "category_encrypted_v3_10000", "Startup Cost": 0.0, - "Total Cost": 602.0 + "Total Cost": 542.0 } ], - "Startup Cost": 652.0, + "Startup Cost": 592.0, "Strategy": "Hashed", - "Total Cost": 655.12 + "Total Cost": 595.12 } ], "Sort Key": [ "(count(*)) DESC" ], - "Startup Cost": 660.53, - "Total Cost": 661.15 + "Startup Cost": 600.53, + "Total Cost": 601.15 } ], - "Startup Cost": 660.53, - "Total Cost": 660.55 + "Startup Cost": 600.53, + "Total Cost": 600.55 } } ] @@ -870,7 +870,7 @@ Full `EXPLAIN (FORMAT JSON)`: Limit Sort Aggregate (Hashed) - Seq Scan on category_encrypted_100000 + Seq Scan on category_encrypted_v3_100000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -896,7 +896,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "(((value).data ->> 'hm'::text))::eql_v2.hmac_256" + "(((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -907,32 +907,32 @@ Full `EXPLAIN (FORMAT JSON)`: "Planned Partitions": 0, "Plans": [ { - "Alias": "category_encrypted_100000", + "Alias": "category_encrypted_v3_100000", "Async Capable": false, "Node Type": "Seq Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 100000, "Plan Width": 32, - "Relation Name": "category_encrypted_100000", + "Relation Name": "category_encrypted_v3_100000", "Startup Cost": 0.0, - "Total Cost": 6066.0 + "Total Cost": 5417.0 } ], - "Startup Cost": 6566.0, + "Startup Cost": 5917.0, "Strategy": "Hashed", - "Total Cost": 6569.12 + "Total Cost": 5920.12 } ], "Sort Key": [ "(count(*)) DESC" ], - "Startup Cost": 6574.53, - "Total Cost": 6575.15 + "Startup Cost": 5925.53, + "Total Cost": 5926.15 } ], - "Startup Cost": 6574.53, - "Total Cost": 6574.55 + "Startup Cost": 5925.53, + "Total Cost": 5925.55 } } ] @@ -947,7 +947,7 @@ Limit Gather Merge Sort Aggregate (Hashed) - Seq Scan on category_encrypted_1000000 + Seq Scan on category_encrypted_v3_1000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -973,7 +973,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "((((value).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -1001,7 +1001,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "(((value).data ->> 'hm'::text))::eql_v2.hmac_256" + "(((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -1012,49 +1012,49 @@ Full `EXPLAIN (FORMAT JSON)`: "Planned Partitions": 0, "Plans": [ { - "Alias": "category_encrypted_1000000", + "Alias": "category_encrypted_v3_1000000", "Async Capable": false, "Node Type": "Seq Scan", "Parallel Aware": true, "Parent Relationship": "Outer", - "Plan Rows": 416656, + "Plan Rows": 416665, "Plan Width": 32, - "Relation Name": "category_encrypted_1000000", + "Relation Name": "category_encrypted_v3_1000000", "Startup Cost": 0.0, - "Total Cost": 52840.2 + "Total Cost": 46875.32 } ], - "Startup Cost": 54923.48, + "Startup Cost": 48958.64, "Strategy": "Hashed", - "Total Cost": 54926.6 + "Total Cost": 48961.77 } ], "Sort Key": [ - "((((value).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], - "Startup Cost": 54936.56, - "Total Cost": 54937.19 + "Startup Cost": 48971.72, + "Total Cost": 48972.35 } ], - "Startup Cost": 55936.58, - "Total Cost": 55994.92, + "Startup Cost": 49971.75, + "Total Cost": 50030.09, "Workers Planned": 2 } ], - "Startup Cost": 55936.58, + "Startup Cost": 49971.75, "Strategy": "Sorted", - "Total Cost": 56000.55 + "Total Cost": 50035.71 } ], "Sort Key": [ "(count(*)) DESC" ], - "Startup Cost": 56005.95, - "Total Cost": 56006.57 + "Startup Cost": 50041.11, + "Total Cost": 50041.74 } ], - "Startup Cost": 56005.95, - "Total Cost": 56005.97 + "Startup Cost": 50041.11, + "Total Cost": 50041.14 } } ] @@ -1069,7 +1069,7 @@ Limit Gather Merge Sort Aggregate (Hashed) - Seq Scan on category_encrypted_10000000 + Seq Scan on category_encrypted_v3_10000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -1095,7 +1095,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "((((value).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -1123,7 +1123,7 @@ Full `EXPLAIN (FORMAT JSON)`: { "Async Capable": false, "Group Key": [ - "(((value).data ->> 'hm'::text))::eql_v2.hmac_256" + "(((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" ], "Node Type": "Aggregate", "Parallel Aware": false, @@ -1134,49 +1134,49 @@ Full `EXPLAIN (FORMAT JSON)`: "Planned Partitions": 0, "Plans": [ { - "Alias": "category_encrypted_10000000", + "Alias": "category_encrypted_v3_10000000", "Async Capable": false, "Node Type": "Seq Scan", "Parallel Aware": true, "Parent Relationship": "Outer", - "Plan Rows": 4166822, + "Plan Rows": 4166670, "Plan Width": 32, - "Relation Name": "category_encrypted_10000000", + "Relation Name": "category_encrypted_v3_10000000", "Startup Cost": 0.0, - "Total Cost": 528325.28 + "Total Cost": 468750.38 } ], - "Startup Cost": 549159.39, + "Startup Cost": 489583.72, "Strategy": "Hashed", - "Total Cost": 549162.51 + "Total Cost": 489586.85 } ], "Sort Key": [ - "((((value).data ->> 'hm'::text))::eql_v2.hmac_256)" + "((((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" ], - "Startup Cost": 549172.47, - "Total Cost": 549173.09 + "Startup Cost": 489596.81, + "Total Cost": 489597.43 } ], - "Startup Cost": 550172.49, - "Total Cost": 550230.83, + "Startup Cost": 490596.83, + "Total Cost": 490655.17, "Workers Planned": 2 } ], - "Startup Cost": 550172.49, + "Startup Cost": 490596.83, "Strategy": "Sorted", - "Total Cost": 550236.45 + "Total Cost": 490660.79 } ], "Sort Key": [ "(count(*)) DESC" ], - "Startup Cost": 550241.86, - "Total Cost": 550242.48 + "Startup Cost": 490666.2, + "Total Cost": 490666.82 } ], - "Startup Cost": 550241.86, - "Total Cost": 550241.88 + "Startup Cost": 490666.2, + "Total Cost": 490666.22 } } ] @@ -1208,10 +1208,10 @@ SELECT value, count(*) FROM {TABLE} GROUP BY 1 ORDER BY count(*) DESC LIMIT 10 | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 10 | 1.20ms | N/A | -| 100,000 | 10 | 9.52ms | N/A | -| 1,000,000 | 10 | 40.21ms | N/A | -| 10,000,000 | 10 | ⚠️ 350.21ms | N/A | +| 10,000 | 10 | 1.24ms | N/A | +| 100,000 | 10 | 10.07ms | N/A | +| 1,000,000 | 10 | 38.70ms | N/A | +| 10,000,000 | 10 | ⚠️ 363.08ms | N/A | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -1344,23 +1344,23 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 8, "Relation Name": "category_plaintext_100000", "Startup Cost": 0.0, - "Total Cost": 1544.0 + "Total Cost": 1541.0 } ], - "Startup Cost": 2044.0, + "Startup Cost": 2041.0, "Strategy": "Hashed", - "Total Cost": 2046.5 + "Total Cost": 2043.5 } ], "Sort Key": [ "(count(*)) DESC" ], - "Startup Cost": 2051.9, - "Total Cost": 2052.53 + "Startup Cost": 2048.9, + "Total Cost": 2049.53 } ], - "Startup Cost": 2051.9, - "Total Cost": 2051.93 + "Startup Cost": 2048.9, + "Total Cost": 2048.93 } } ] @@ -1449,40 +1449,40 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 8, "Relation Name": "category_plaintext_1000000", "Startup Cost": 0.0, - "Total Cost": 9574.67 + "Total Cost": 9572.67 } ], - "Startup Cost": 11658.0, + "Startup Cost": 11656.0, "Strategy": "Hashed", - "Total Cost": 11660.5 + "Total Cost": 11658.5 } ], "Sort Key": [ "value" ], - "Startup Cost": 11670.46, - "Total Cost": 11671.08 + "Startup Cost": 11668.46, + "Total Cost": 11669.08 } ], - "Startup Cost": 12670.48, - "Total Cost": 12728.82, + "Startup Cost": 12668.48, + "Total Cost": 12726.82, "Workers Planned": 2 } ], - "Startup Cost": 12670.48, + "Startup Cost": 12668.48, "Strategy": "Sorted", - "Total Cost": 12733.82 + "Total Cost": 12731.82 } ], "Sort Key": [ "(count(*)) DESC" ], - "Startup Cost": 12739.22, - "Total Cost": 12739.85 + "Startup Cost": 12737.22, + "Total Cost": 12737.85 } ], - "Startup Cost": 12739.22, - "Total Cost": 12739.25 + "Startup Cost": 12737.22, + "Total Cost": 12737.25 } } ] @@ -1567,44 +1567,44 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Seq Scan", "Parallel Aware": true, "Parent Relationship": "Outer", - "Plan Rows": 4166275, + "Plan Rows": 4166608, "Plan Width": 8, "Relation Name": "category_plaintext_10000000", "Startup Cost": 0.0, - "Total Cost": 95774.75 + "Total Cost": 95721.08 } ], - "Startup Cost": 116606.12, + "Startup Cost": 116554.12, "Strategy": "Hashed", - "Total Cost": 116608.62 + "Total Cost": 116556.62 } ], "Sort Key": [ "value" ], - "Startup Cost": 116618.58, - "Total Cost": 116619.2 + "Startup Cost": 116566.58, + "Total Cost": 116567.21 } ], - "Startup Cost": 117618.6, - "Total Cost": 117676.94, + "Startup Cost": 117566.6, + "Total Cost": 117624.94, "Workers Planned": 2 } ], - "Startup Cost": 117618.6, + "Startup Cost": 117566.6, "Strategy": "Sorted", - "Total Cost": 117681.94 + "Total Cost": 117629.94 } ], "Sort Key": [ "(count(*)) DESC" ], - "Startup Cost": 117687.34, - "Total Cost": 117687.97 + "Startup Cost": 117635.34, + "Total Cost": 117635.97 } ], - "Startup Cost": 117687.34, - "Total Cost": 117687.37 + "Startup Cost": 117635.34, + "Total Cost": 117635.37 } } ] diff --git a/report/ingest_category_throughput_chart.png b/report/ingest_category_throughput_chart.png new file mode 100644 index 0000000..339fc92 Binary files /dev/null and b/report/ingest_category_throughput_chart.png differ diff --git a/report/ingest_category_time_chart.png b/report/ingest_category_time_chart.png new file mode 100644 index 0000000..96811b1 Binary files /dev/null and b/report/ingest_category_time_chart.png differ diff --git a/report/ingest_comparison_throughput_10000.png b/report/ingest_comparison_throughput_10000.png index dc4ce53..a7ff145 100644 Binary files a/report/ingest_comparison_throughput_10000.png and b/report/ingest_comparison_throughput_10000.png differ diff --git a/report/ingest_comparison_time_10000.png b/report/ingest_comparison_time_10000.png index ea0b2a0..4928a2d 100644 Binary files a/report/ingest_comparison_time_10000.png and b/report/ingest_comparison_time_10000.png differ diff --git a/report/ingest_comparison_time_10000_filtered.png b/report/ingest_comparison_time_10000_filtered.png index d9387fc..52f09ff 100644 Binary files a/report/ingest_comparison_time_10000_filtered.png and b/report/ingest_comparison_time_10000_filtered.png differ diff --git a/report/ingest_int_ope_throughput_chart.png b/report/ingest_int_ope_throughput_chart.png new file mode 100644 index 0000000..84db8ac Binary files /dev/null and b/report/ingest_int_ope_throughput_chart.png differ diff --git a/report/ingest_int_ope_time_chart.png b/report/ingest_int_ope_time_chart.png new file mode 100644 index 0000000..11c38a5 Binary files /dev/null and b/report/ingest_int_ope_time_chart.png differ diff --git a/report/ingest_int_throughput_chart.png b/report/ingest_int_throughput_chart.png index c80d1c6..6e8c5eb 100644 Binary files a/report/ingest_int_throughput_chart.png and b/report/ingest_int_throughput_chart.png differ diff --git a/report/ingest_int_time_chart.png b/report/ingest_int_time_chart.png index ef9a807..bd113fe 100644 Binary files a/report/ingest_int_time_chart.png and b/report/ingest_int_time_chart.png differ diff --git a/report/ingest_ste_vec_small_throughput_chart.png b/report/ingest_ste_vec_small_throughput_chart.png index b7db65a..c9c50a9 100644 Binary files a/report/ingest_ste_vec_small_throughput_chart.png and b/report/ingest_ste_vec_small_throughput_chart.png differ diff --git a/report/ingest_ste_vec_small_time_chart.png b/report/ingest_ste_vec_small_time_chart.png index 5b755ec..69ec704 100644 Binary files a/report/ingest_ste_vec_small_time_chart.png and b/report/ingest_ste_vec_small_time_chart.png differ diff --git a/report/ingest_string_throughput_chart.png b/report/ingest_string_throughput_chart.png index fc25858..7651f27 100644 Binary files a/report/ingest_string_throughput_chart.png and b/report/ingest_string_throughput_chart.png differ diff --git a/report/ingest_string_time_chart.png b/report/ingest_string_time_chart.png index 94193ff..e0987fd 100644 Binary files a/report/ingest_string_time_chart.png and b/report/ingest_string_time_chart.png differ diff --git a/report/json.md b/report/json.md index 9f30674..39c3859 100644 --- a/report/json.md +++ b/report/json.md @@ -48,17 +48,17 @@ ON json_ste_vec_small_encrypted_10000 USING GIN ( **Indexes used by the planner (per data set size):** -- 10,000: `json_ste_vec_small_encrypted_10000_jsonb_array_index` -- 100,000: `json_ste_vec_small_encrypted_100000_jsonb_array_index` -- 1,000,000: `json_ste_vec_small_encrypted_1000000_jsonb_array_index` -- 10,000,000: `json_ste_vec_small_encrypted_10000000_jsonb_array_index` +- 10,000: `json_ste_vec_small_encrypted_v3_10000_jsonb_array_index` +- 100,000: `json_ste_vec_small_encrypted_v3_100000_jsonb_array_index` +- 1,000,000: `json_ste_vec_small_encrypted_v3_1000000_jsonb_array_index` +- 10,000,000: `json_ste_vec_small_encrypted_v3_10000000_jsonb_array_index` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 1 | 238.33μs | N/A | -| 100,000 | 1 | 287.01μs | N/A | -| 1,000,000 | 1 | 433.92μs | N/A | -| 10,000,000 | 1 | 853.79μs | N/A | +| 10,000 | 1 | 233.88μs | N/A | +| 100,000 | 1 | 256.09μs | N/A | +| 1,000,000 | 1 | 419.36μs | N/A | +| 10,000,000 | 1 | 1.06ms | N/A | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -69,8 +69,8 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Bitmap Heap Scan on json_ste_vec_small_encrypted_10000 - Bitmap Index Scan using json_ste_vec_small_encrypted_10000_jsonb_array_index + Bitmap Heap Scan on json_ste_vec_small_encrypted_v3_10000 + Bitmap Index Scan using json_ste_vec_small_encrypted_v3_10000_jsonb_array_index ``` Full `EXPLAIN (FORMAT JSON)`: @@ -86,7 +86,7 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_10000", + "Alias": "json_ste_vec_small_encrypted_v3_10000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, @@ -96,8 +96,8 @@ Full `EXPLAIN (FORMAT JSON)`: "Plans": [ { "Async Capable": false, - "Index Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db49711c282c9945019a0d5d828669b07666c22835fea10dec1a7c1b6a6f19643526e9fc2f711acceb0290e4deab64aa2b340c662c9\\\"}\",\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db5d403405be41b6282af7f22db8d658eb80dd800b412c08aa4b2cc3a75b9f4ce55d3df3c2335e40f7e45297ada\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e403ea3be1fea72fbc01ec952a09371fc9612b428b7ded13cecfef3b2cd8fcf7cb40c4b548f4c91d187ad027907127860abcc58b92b1670f85e5178cfeda25766f3f6de0327c7813de3e52dbd36b43d96e847acf1153f5e023bdff8fdff1a784fd2a8f33ddb78b3849e8e5372a2519a2e3ac83c226bbd0643ee330d80e925bfe30c189b749ee761281403e3e9332f03f5c731be4a94c42f14eedd5afde4f40601554d424a5a\\\"}\",\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0984d4957290b0eb89f172928170998bc114ac343a673440e682d03234d35c039ae0ba9a5bba6f3901e018ba8c10f88db4cfa3e37e6357\\\"}\"}'::jsonb[])", - "Index Name": "json_ste_vec_small_encrypted_10000_jsonb_array_index", + "Index Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445b99a8145a992feffd27dbccc23403644ed2feffa7aa72ca2e78d163b006e9765c25c979709adfac3eb53f92dcfcff868232545184a5122622c6d2e57\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ae112c2089404a378b7e03856b6281edd02159fedc2e7e61244c43b14ce9d67921f590c328d1587160f9af113ae95aaf453a37514c268eb4317678bfe4365cfa8f689edce9796f5ec194f8e6a48882b07607ae6e03c16a6a3d985d5edbe516bbca6094d9b73343a57de5f0311c4e25df6eaf7c094fe5d1b97ea3696a3043f38c68c7560242188228687fbb7880bbe891b3aaa83029995d9553b71bc27d8de087dfd65eb12f1a976887c322c729\\\"}\",\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed445b99a8145a992fefe400f7a9a1f0253ffa837b76c1602d4a28ae81114\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d8b88e748150ce18ba0d1fa98dda6bf96cb47d12150661d4710365e26993420af2ccd1d836df55ccbc9bb7a6fb4f5589c09032c4bf\\\"}\"}'::jsonb[])", + "Index Name": "json_ste_vec_small_encrypted_v3_10000_jsonb_array_index", "Node Type": "Bitmap Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", @@ -107,8 +107,8 @@ Full `EXPLAIN (FORMAT JSON)`: "Total Cost": 68.86 } ], - "Recheck Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db49711c282c9945019a0d5d828669b07666c22835fea10dec1a7c1b6a6f19643526e9fc2f711acceb0290e4deab64aa2b340c662c9\\\"}\",\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db5d403405be41b6282af7f22db8d658eb80dd800b412c08aa4b2cc3a75b9f4ce55d3df3c2335e40f7e45297ada\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e403ea3be1fea72fbc01ec952a09371fc9612b428b7ded13cecfef3b2cd8fcf7cb40c4b548f4c91d187ad027907127860abcc58b92b1670f85e5178cfeda25766f3f6de0327c7813de3e52dbd36b43d96e847acf1153f5e023bdff8fdff1a784fd2a8f33ddb78b3849e8e5372a2519a2e3ac83c226bbd0643ee330d80e925bfe30c189b749ee761281403e3e9332f03f5c731be4a94c42f14eedd5afde4f40601554d424a5a\\\"}\",\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0984d4957290b0eb89f172928170998bc114ac343a673440e682d03234d35c039ae0ba9a5bba6f3901e018ba8c10f88db4cfa3e37e6357\\\"}\"}'::jsonb[])", - "Relation Name": "json_ste_vec_small_encrypted_10000", + "Recheck Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445b99a8145a992feffd27dbccc23403644ed2feffa7aa72ca2e78d163b006e9765c25c979709adfac3eb53f92dcfcff868232545184a5122622c6d2e57\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ae112c2089404a378b7e03856b6281edd02159fedc2e7e61244c43b14ce9d67921f590c328d1587160f9af113ae95aaf453a37514c268eb4317678bfe4365cfa8f689edce9796f5ec194f8e6a48882b07607ae6e03c16a6a3d985d5edbe516bbca6094d9b73343a57de5f0311c4e25df6eaf7c094fe5d1b97ea3696a3043f38c68c7560242188228687fbb7880bbe891b3aaa83029995d9553b71bc27d8de087dfd65eb12f1a976887c322c729\\\"}\",\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed445b99a8145a992fefe400f7a9a1f0253ffa837b76c1602d4a28ae81114\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d8b88e748150ce18ba0d1fa98dda6bf96cb47d12150661d4710365e26993420af2ccd1d836df55ccbc9bb7a6fb4f5589c09032c4bf\\\"}\"}'::jsonb[])", + "Relation Name": "json_ste_vec_small_encrypted_v3_10000", "Startup Cost": 68.86, "Total Cost": 73.13 } @@ -124,8 +124,8 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Bitmap Heap Scan on json_ste_vec_small_encrypted_100000 - Bitmap Index Scan using json_ste_vec_small_encrypted_100000_jsonb_array_index + Bitmap Heap Scan on json_ste_vec_small_encrypted_v3_100000 + Bitmap Index Scan using json_ste_vec_small_encrypted_v3_100000_jsonb_array_index ``` Full `EXPLAIN (FORMAT JSON)`: @@ -141,7 +141,7 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_100000", + "Alias": "json_ste_vec_small_encrypted_v3_100000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, @@ -151,8 +151,8 @@ Full `EXPLAIN (FORMAT JSON)`: "Plans": [ { "Async Capable": false, - "Index Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db4971212d5f2ebe58b72e7b8fa9d528196612fc962cd5f14cc85a882d495c5b8ceb74335081e41aebe9001cefa\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e403ea40004cb28aaac8579a40c9c68653f7a1c8d9218ad7259f4c37e28164a5a9f1db7ecb4dea34907606105b4452af42e910a89810c847757038d7ebf79c9a6872a60a39e10541852a9e017fe49d2cf3ec12edbb2421f0d9b4f528de812be40d57dd4943c3a26424f3fec93108c779a185f6fa2ffe1f2d0e2140cb54042b17262a629b52ceca7af4d8f8c9aed1d963e206c1665b0e991d8a6e0fa9ce055393f253aae9a3d4deb0c90f023b5010edb624f036e23c373a974fdd10f0664040cdbf9692db261\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0a3129231c38a147def14a10589ac6578debca348aa74b3bc9d81b55e6679aafb3f791a0549e371ad4d1a962a1c24fcd3c33beaf6012e9\\\"}\",\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db49711c141b2cd54aca1d3dc8a37a02a141772209033e93fe56b3ef7bce24c1636c1edc48440f71a57f084f0498568a3af3e15f7fe\\\"}\"}'::jsonb[])", - "Index Name": "json_ste_vec_small_encrypted_100000_jsonb_array_index", + "Index Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed445baee82925a7a5a663fa0a488c796509325fbe46fee6db4348e604e9fca13c9c6dab8f19e6380c88111eca6e1024946c57cd2189644e055f6e3da741d\\\"}\",\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445baeddd580ed0f4e600b1a1b0a795e861d0738c0807142caf160adc5367814641383016a79c782539e7c3c74094a26998670debf9\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d759d250a567842a7c3f5af2a6b3f2a58a8160fc3e4079dc9e54b19e671a8834488db7592a060356887c3e718a86beaefae5648294\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ad759eaaa77577c5c0fa51b44f31e10c15d77798a69fe38252a01a79d62483c88ca828f2f55b01f2ce53421931e02a7425637d9aab24caf3f8184fa93b84fb2a933202bd7b27a38fa1d6eaeddeee178e882b82275ca68f35401ef1ced3167a7e0df4852a35c4042b081517fc9e45eb66b68285f26d619787ae9a2873ec2f0bee0f17ff420f38d30c9366a12709cb076e0da9aae5109dcb3d2f23105c3fba4c802a8d948bac8f609f84f2f73702fa5a4eeb1362738de9e4bd2b2e91b1a83867e0bba8c1b56b6d5b1f0b274539a841071fc02399a4d7\\\"}\"}'::jsonb[])", + "Index Name": "json_ste_vec_small_encrypted_v3_100000_jsonb_array_index", "Node Type": "Bitmap Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", @@ -162,8 +162,8 @@ Full `EXPLAIN (FORMAT JSON)`: "Total Cost": 90.19 } ], - "Recheck Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db4971212d5f2ebe58b72e7b8fa9d528196612fc962cd5f14cc85a882d495c5b8ceb74335081e41aebe9001cefa\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e403ea40004cb28aaac8579a40c9c68653f7a1c8d9218ad7259f4c37e28164a5a9f1db7ecb4dea34907606105b4452af42e910a89810c847757038d7ebf79c9a6872a60a39e10541852a9e017fe49d2cf3ec12edbb2421f0d9b4f528de812be40d57dd4943c3a26424f3fec93108c779a185f6fa2ffe1f2d0e2140cb54042b17262a629b52ceca7af4d8f8c9aed1d963e206c1665b0e991d8a6e0fa9ce055393f253aae9a3d4deb0c90f023b5010edb624f036e23c373a974fdd10f0664040cdbf9692db261\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0a3129231c38a147def14a10589ac6578debca348aa74b3bc9d81b55e6679aafb3f791a0549e371ad4d1a962a1c24fcd3c33beaf6012e9\\\"}\",\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db49711c141b2cd54aca1d3dc8a37a02a141772209033e93fe56b3ef7bce24c1636c1edc48440f71a57f084f0498568a3af3e15f7fe\\\"}\"}'::jsonb[])", - "Relation Name": "json_ste_vec_small_encrypted_100000", + "Recheck Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed445baee82925a7a5a663fa0a488c796509325fbe46fee6db4348e604e9fca13c9c6dab8f19e6380c88111eca6e1024946c57cd2189644e055f6e3da741d\\\"}\",\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445baeddd580ed0f4e600b1a1b0a795e861d0738c0807142caf160adc5367814641383016a79c782539e7c3c74094a26998670debf9\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d759d250a567842a7c3f5af2a6b3f2a58a8160fc3e4079dc9e54b19e671a8834488db7592a060356887c3e718a86beaefae5648294\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ad759eaaa77577c5c0fa51b44f31e10c15d77798a69fe38252a01a79d62483c88ca828f2f55b01f2ce53421931e02a7425637d9aab24caf3f8184fa93b84fb2a933202bd7b27a38fa1d6eaeddeee178e882b82275ca68f35401ef1ced3167a7e0df4852a35c4042b081517fc9e45eb66b68285f26d619787ae9a2873ec2f0bee0f17ff420f38d30c9366a12709cb076e0da9aae5109dcb3d2f23105c3fba4c802a8d948bac8f609f84f2f73702fa5a4eeb1362738de9e4bd2b2e91b1a83867e0bba8c1b56b6d5b1f0b274539a841071fc02399a4d7\\\"}\"}'::jsonb[])", + "Relation Name": "json_ste_vec_small_encrypted_v3_100000", "Startup Cost": 90.19, "Total Cost": 94.45 } @@ -179,8 +179,8 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Bitmap Heap Scan on json_ste_vec_small_encrypted_1000000 - Bitmap Index Scan using json_ste_vec_small_encrypted_1000000_jsonb_array_index + Bitmap Heap Scan on json_ste_vec_small_encrypted_v3_1000000 + Bitmap Index Scan using json_ste_vec_small_encrypted_v3_1000000_jsonb_array_index ``` Full `EXPLAIN (FORMAT JSON)`: @@ -196,7 +196,7 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_1000000", + "Alias": "json_ste_vec_small_encrypted_v3_1000000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, @@ -206,8 +206,8 @@ Full `EXPLAIN (FORMAT JSON)`: "Plans": [ { "Async Capable": false, - "Index Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db5d4045f7eae249da635745e1a5e6691a7feb66fed367ce633d7792fef78397cb5ba02b5c0da766c5ace2e9b3c\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e403ea40004cb28aaac8579a40c9c68653f7a1c8d93be87493ade620ca595abd48e66e220c9e30c77842a002a700b059d4d59250090b87f4a38fa321bf852c5d7458ab0d670443ebf9a445e27bfe098819e341e0c431b2b50e889d713e682b1937939d1370f0dd64421ea3610fae0a279833dc61c14ef788dffca9f26246050d98430966dac692632292260560226b1ea6cec1e2f57a80fe979f14c65bf9dd364449f136ba3\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0984d495716bf9ae2c0a31447b038fd5bd56472d846a1a2cb71a3b9f5436ef8fc2c6c25c58e2e9e6fc05934730282d950e9b98d221f899\\\"}\",\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db4984a02b345757574904a5f1c307b11290aaa1b1b4542856950ff97176a23e23b1ca676713a1a2384ea826486\\\"}\"}'::jsonb[])", - "Index Name": "json_ste_vec_small_encrypted_1000000_jsonb_array_index", + "Index Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed446d572477e0e74ae828304897b9f568962af078cdd5e9f431c2c05d49d78229e2d75115eee93156538ce6055ce65b627f446147bd3\\\"}\",\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445b99b00a005cc452ce307db927ed0c8b81d13e19cbb4c97c25a98a345ce77a106ed1accffff18f5c5a8d521f49164c2570fe0e15944dabc246a97232eed758beac7af182c7c455eb7763c5421a9eec34836c60124\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ae112c208a42fb629a590c3da6f55830676a44954cfacabcf6e315666343ea53c93db241fd37c6ba98ac8f703af8286961605cb53c8ca249738e035ca41ac9c92fe8ca38c498b62165de133166c7f9de09cdce5c1c54456b27e990e2d61075c67d683c61e87bcead8a94af1bf1d9c91f88e6dd8f38e76312d2e77c622afc00c6bfbd5bdebe01a36c6e63b205f42dd9798d6befe357093808609fed789160e166fefd9c137a72b2db8795d532d964e2a9ff3df18176\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d8b97d5813f5decb57cd129b4a3cfe86ba1339f27bee6833a277032ea11fd3cdaea0249e4dfd806fd691c652212db9a671e096a540\\\"}\"}'::jsonb[])", + "Index Name": "json_ste_vec_small_encrypted_v3_1000000_jsonb_array_index", "Node Type": "Bitmap Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", @@ -217,8 +217,8 @@ Full `EXPLAIN (FORMAT JSON)`: "Total Cost": 111.51 } ], - "Recheck Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db5d4045f7eae249da635745e1a5e6691a7feb66fed367ce633d7792fef78397cb5ba02b5c0da766c5ace2e9b3c\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e403ea40004cb28aaac8579a40c9c68653f7a1c8d93be87493ade620ca595abd48e66e220c9e30c77842a002a700b059d4d59250090b87f4a38fa321bf852c5d7458ab0d670443ebf9a445e27bfe098819e341e0c431b2b50e889d713e682b1937939d1370f0dd64421ea3610fae0a279833dc61c14ef788dffca9f26246050d98430966dac692632292260560226b1ea6cec1e2f57a80fe979f14c65bf9dd364449f136ba3\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0984d495716bf9ae2c0a31447b038fd5bd56472d846a1a2cb71a3b9f5436ef8fc2c6c25c58e2e9e6fc05934730282d950e9b98d221f899\\\"}\",\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db4984a02b345757574904a5f1c307b11290aaa1b1b4542856950ff97176a23e23b1ca676713a1a2384ea826486\\\"}\"}'::jsonb[])", - "Relation Name": "json_ste_vec_small_encrypted_1000000", + "Recheck Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed446d572477e0e74ae828304897b9f568962af078cdd5e9f431c2c05d49d78229e2d75115eee93156538ce6055ce65b627f446147bd3\\\"}\",\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445b99b00a005cc452ce307db927ed0c8b81d13e19cbb4c97c25a98a345ce77a106ed1accffff18f5c5a8d521f49164c2570fe0e15944dabc246a97232eed758beac7af182c7c455eb7763c5421a9eec34836c60124\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ae112c208a42fb629a590c3da6f55830676a44954cfacabcf6e315666343ea53c93db241fd37c6ba98ac8f703af8286961605cb53c8ca249738e035ca41ac9c92fe8ca38c498b62165de133166c7f9de09cdce5c1c54456b27e990e2d61075c67d683c61e87bcead8a94af1bf1d9c91f88e6dd8f38e76312d2e77c622afc00c6bfbd5bdebe01a36c6e63b205f42dd9798d6befe357093808609fed789160e166fefd9c137a72b2db8795d532d964e2a9ff3df18176\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d8b97d5813f5decb57cd129b4a3cfe86ba1339f27bee6833a277032ea11fd3cdaea0249e4dfd806fd691c652212db9a671e096a540\\\"}\"}'::jsonb[])", + "Relation Name": "json_ste_vec_small_encrypted_v3_1000000", "Startup Cost": 111.51, "Total Cost": 115.78 } @@ -234,8 +234,8 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Bitmap Heap Scan on json_ste_vec_small_encrypted_10000000 - Bitmap Index Scan using json_ste_vec_small_encrypted_10000000_jsonb_array_index + Bitmap Heap Scan on json_ste_vec_small_encrypted_v3_10000000 + Bitmap Index Scan using json_ste_vec_small_encrypted_v3_10000000_jsonb_array_index ``` Full `EXPLAIN (FORMAT JSON)`: @@ -251,7 +251,7 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_10000000", + "Alias": "json_ste_vec_small_encrypted_v3_10000000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, @@ -261,8 +261,8 @@ Full `EXPLAIN (FORMAT JSON)`: "Plans": [ { "Async Capable": false, - "Index Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e4113e9f962fbe6fe249a5de0f12ba7ed560c524ef29c96018408b83c94c4c76ef043485fdb4c0d3dbe1c73986f14fea459d4976516c1b96cdd3820f5b5f9a3517a94cf901aea6edf910824dc75cb38166bc34693f784dde67958dbda26a643bbca03014b39e7d2aef06e009af176dccb11c27947e4ff7f9394632439395b3c101d8e8c721c6c5600da3d64a9aeea4520829440901344c2377277039617\\\"}\",\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db4971212d687dc77e2922544be2e3a767b9e6e92cae4e7f344ae9bf59a6986cfacd75f6cd0867c19ad4280b0919b6a3e929b02cd6ddf62d400008e47943e3d6fcb89d5046e32912438f622e77d\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0984d494d6304819280964b36414fc29e4ea7f18c10a0b42d088191c96642d1a2434e91c0d4dcb0fa2fd386a20f67a128a29dc864feec2\\\"}\",\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db49711c282c9945019a194351fb299f75ed665afb97d57ea0658a61a53b755e69da35ab919\\\"}\"}'::jsonb[])", - "Index Name": "json_ste_vec_small_encrypted_10000000_jsonb_array_index", + "Index Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed445b99b00a005cc452b2f322ff38b63e1fd75ec0c254ef4eab3454d73767587fdd4e961c3d6719c8851f75df976\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d8b88f3dc8ef1dbc11bad17ae69d7bd0c112796ba6416baf0e3b0dc577886a15389fc364d1b3ceb56488adecb738298ff9b47cd306\\\"}\",\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ae112b8eee58a8745ea7dfee54ece27100c9bdd278919b961e699db652bba421a06e89490da16222946fbfb0930425811f6a467a6c47a0fb2a5c1137f336085f4b277c939e2e775adc108ba19fdec36e352996de6a29fe5dd44c35750a4ba83fefcab64f8d5b71ee2d5918284de3e48a14c237e38ba457ae00a5cf594ae52bb6d35fffb84c9b0937a5d35a60a7b4dfeae483a9d4abdbbdc797201cca110864ac480c384077184935682e302ee65f3283118bcf4707\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445baeddc1bf42210e9f10a92d31e6e326398d47cb4f593328e1832b2656e3b102da2deda13\\\"}\"}'::jsonb[])", + "Index Name": "json_ste_vec_small_encrypted_v3_10000000_jsonb_array_index", "Node Type": "Bitmap Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", @@ -272,8 +272,8 @@ Full `EXPLAIN (FORMAT JSON)`: "Total Cost": 132.79 } ], - "Recheck Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e4113e9f962fbe6fe249a5de0f12ba7ed560c524ef29c96018408b83c94c4c76ef043485fdb4c0d3dbe1c73986f14fea459d4976516c1b96cdd3820f5b5f9a3517a94cf901aea6edf910824dc75cb38166bc34693f784dde67958dbda26a643bbca03014b39e7d2aef06e009af176dccb11c27947e4ff7f9394632439395b3c101d8e8c721c6c5600da3d64a9aeea4520829440901344c2377277039617\\\"}\",\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db4971212d687dc77e2922544be2e3a767b9e6e92cae4e7f344ae9bf59a6986cfacd75f6cd0867c19ad4280b0919b6a3e929b02cd6ddf62d400008e47943e3d6fcb89d5046e32912438f622e77d\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0984d494d6304819280964b36414fc29e4ea7f18c10a0b42d088191c96642d1a2434e91c0d4dcb0fa2fd386a20f67a128a29dc864feec2\\\"}\",\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db49711c282c9945019a194351fb299f75ed665afb97d57ea0658a61a53b755e69da35ab919\\\"}\"}'::jsonb[])", - "Relation Name": "json_ste_vec_small_encrypted_10000000", + "Recheck Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed445b99b00a005cc452b2f322ff38b63e1fd75ec0c254ef4eab3454d73767587fdd4e961c3d6719c8851f75df976\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d8b88f3dc8ef1dbc11bad17ae69d7bd0c112796ba6416baf0e3b0dc577886a15389fc364d1b3ceb56488adecb738298ff9b47cd306\\\"}\",\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ae112b8eee58a8745ea7dfee54ece27100c9bdd278919b961e699db652bba421a06e89490da16222946fbfb0930425811f6a467a6c47a0fb2a5c1137f336085f4b277c939e2e775adc108ba19fdec36e352996de6a29fe5dd44c35750a4ba83fefcab64f8d5b71ee2d5918284de3e48a14c237e38ba457ae00a5cf594ae52bb6d35fffb84c9b0937a5d35a60a7b4dfeae483a9d4abdbbdc797201cca110864ac480c384077184935682e302ee65f3283118bcf4707\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445baeddc1bf42210e9f10a92d31e6e326398d47cb4f593328e1832b2656e3b102da2deda13\\\"}\"}'::jsonb[])", + "Relation Name": "json_ste_vec_small_encrypted_v3_10000000", "Startup Cost": 132.79, "Total Cost": 137.05 } @@ -331,17 +331,17 @@ ON json_ste_vec_small_encrypted_10000 USING GIN ( **Indexes used by the planner (per data set size):** -- 10,000: `json_ste_vec_small_encrypted_10000_field_eq_idx` -- 100,000: `json_ste_vec_small_encrypted_100000_field_eq_idx` -- 1,000,000: `json_ste_vec_small_encrypted_1000000_field_eq_idx` -- 10,000,000: `json_ste_vec_small_encrypted_10000000_field_eq_idx` +- 10,000: `json_ste_vec_small_encrypted_v3_10000_field_eq_idx` +- 100,000: `json_ste_vec_small_encrypted_v3_100000_field_eq_idx` +- 1,000,000: `json_ste_vec_small_encrypted_v3_1000000_field_eq_idx` +- 10,000,000: `json_ste_vec_small_encrypted_v3_10000000_field_eq_idx` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 10 | 109.04μs | N/A | -| 100,000 | 10 | 106.46μs | N/A | -| 1,000,000 | 10 | 99.38μs | N/A | -| 10,000,000 | 10 | 109.18μs | N/A | +| 10,000 | 10 | 113.66μs | N/A | +| 100,000 | 10 | 115.15μs | N/A | +| 1,000,000 | 10 | 111.50μs | N/A | +| 10,000,000 | 10 | 96.58μs | N/A | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -352,7 +352,7 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Index Scan using json_ste_vec_small_encrypted_10000_field_eq_idx on json_ste_vec_small_encrypted_10000 + Index Scan using json_ste_vec_small_encrypted_v3_10000_field_eq_idx on json_ste_vec_small_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -368,23 +368,23 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_10000", + "Alias": "json_ste_vec_small_encrypted_v3_10000", "Async Capable": false, - "Index Cond": "(eql_v2.eq_term((value -> 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbLP(i?F+N4}@Yd7+CEvBh%4WvWGA-Clm>I7>+FpI2@T`6kjE%$~vnW*H{GSQRxTsN%B(Hto#H*A)ql=&pvnJm04OwTPpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_10000\"}, \"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"v\": 2, \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}'::jsonb)::eql_v2.ste_vec_entry))", - "Index Name": "json_ste_vec_small_encrypted_10000_field_eq_idx", + "Index Cond": "(eql_v3.eq_term(eql_v3.jsonb_path_query_first((value)::jsonb, '75146c96a91ff82146e29e87b5accb95'::text)) = eql_v3.eq_term(('{\"a\": false, \"c\": \"mBbKl&U3G&rdmu!jlvOTNtai|WzTf%GxRRf|8D&*yFcQeZw~`a2wXjcee|dUu?(RM*o=Mf^e@IT*g|>~0V||-vzKbT*s~X`M^rdAlgWgZ#Jz9V6vZ`F(4Uv%?$9NLh8{gxllTC75JJ6cXpEbP!uwg-8nnb9kNg%aApC#s*+tb_lY_4JjIjc(PWht(iJW)gKqCBRpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_10000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_10000_field_eq_idx", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 10000, "Plan Width": 4, - "Relation Name": "json_ste_vec_small_encrypted_10000", + "Relation Name": "json_ste_vec_small_encrypted_v3_10000", "Scan Direction": "Forward", "Startup Cost": 0.54, - "Total Cost": 2046.54 + "Total Cost": 2242.54 } ], "Startup Cost": 0.54, - "Total Cost": 2.58 + "Total Cost": 2.78 } } ] @@ -394,7 +394,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using json_ste_vec_small_encrypted_100000_field_eq_idx on json_ste_vec_small_encrypted_100000 + Index Scan using json_ste_vec_small_encrypted_v3_100000_field_eq_idx on json_ste_vec_small_encrypted_v3_100000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -410,23 +410,23 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_100000", + "Alias": "json_ste_vec_small_encrypted_v3_100000", "Async Capable": false, - "Index Cond": "(eql_v2.eq_term((value -> 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbJ#Az`rN2!?|a+B*-Bmmq?~X$Xb;T3=`{)vYGWIVl1O4v-;wGe0L(${xlw#6&~c2+OgUrj#oFGkUC;JCyf+BZwxob;Y*Mape$W+(md@rfSN5Ye@09b#rnIlsO#puh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_100000\"}, \"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"v\": 2, \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}'::jsonb)::eql_v2.ste_vec_entry))", - "Index Name": "json_ste_vec_small_encrypted_100000_field_eq_idx", + "Index Cond": "(eql_v3.eq_term(eql_v3.jsonb_path_query_first((value)::jsonb, '75146c96a91ff82146e29e87b5accb95'::text)) = eql_v3.eq_term(('{\"a\": false, \"c\": \"mBbL>G+POZxYGacl>M3T^U9ILZDpH%1hfdNmea4A8^XTV*dGo;>8yO5r?BT&aSI_ZsSuV&t8=ymMaG~D6e7#MN-qMs)Y%I_YVN-rsOB%cplB^itOiGKiEl{QCd4G!M9XzS&)=SJlG6IPjHQ5xoo1+$vm3D)DE!$9mVU$_o~@jtT%uE4Q&7M?5}sa{E9tIM-1n8!Nah=}AiNxXpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_100000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_100000_field_eq_idx", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 100000, "Plan Width": 4, - "Relation Name": "json_ste_vec_small_encrypted_100000", + "Relation Name": "json_ste_vec_small_encrypted_v3_100000", "Scan Direction": "Forward", "Startup Cost": 0.54, - "Total Cost": 19741.54 + "Total Cost": 22303.54 } ], "Startup Cost": 0.54, - "Total Cost": 2.52 + "Total Cost": 2.78 } } ] @@ -436,7 +436,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using json_ste_vec_small_encrypted_1000000_field_eq_idx on json_ste_vec_small_encrypted_1000000 + Index Scan using json_ste_vec_small_encrypted_v3_1000000_field_eq_idx on json_ste_vec_small_encrypted_v3_1000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -452,23 +452,23 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_1000000", + "Alias": "json_ste_vec_small_encrypted_v3_1000000", "Async Capable": false, - "Index Cond": "(eql_v2.eq_term((value -> 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbJeS~GW(rh_Ip#L(=Tk4TQhWW<9ljWmSq7yFQK{3){*^3mrvZVb*R$1K>{#a~UP>9qrQVA&6A(*plc?p!)G6K6VxXRF-Ao<%8ZuHeK?nJ3--0Nm!1=ln2Xui4i>S)gYG;I(F^bd2`!ND6isp!LMOUBn>CRQ!LHS7`%z%ZEdL=*l4D?dx-|!N3+f4h3PAmRMTaIoe$WB`ON`M4Kyne+%ye{{cPA*_4ri{z#dizy\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_1000000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_1000000_field_eq_idx", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 1002404, + "Plan Rows": 1001642, "Plan Width": 4, - "Relation Name": "json_ste_vec_small_encrypted_1000000", + "Relation Name": "json_ste_vec_small_encrypted_v3_1000000", "Scan Direction": "Forward", "Startup Cost": 0.68, - "Total Cost": 187629.75 + "Total Cost": 222842.41 } ], "Startup Cost": 0.68, - "Total Cost": 2.55 + "Total Cost": 2.9 } } ] @@ -478,7 +478,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using json_ste_vec_small_encrypted_10000000_field_eq_idx on json_ste_vec_small_encrypted_10000000 + Index Scan using json_ste_vec_small_encrypted_v3_10000000_field_eq_idx on json_ste_vec_small_encrypted_v3_10000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -494,23 +494,23 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_10000000", + "Alias": "json_ste_vec_small_encrypted_v3_10000000", "Async Capable": false, - "Index Cond": "(eql_v2.eq_term((value -> 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbJLhWn-J_XuAF@lJV1yj2RsWY00Q2F%S?!W`})*vltb>7kZ*|BK4On8t^sSE)U-JiRV)L0?jR{}{TcEhaWm?it8o3@A!B9O_Ve_vbf!P^7`HpOMhg7r=0>?cU1z3gGN?;ss-t|Pc*N4jA6b4XX?4ja(m^ns%IO=0v;tCgV#q5`TSV2hKIfV#*07WP+Ji7W{F$7iY3M9G5^FM;|!vaI5(ygH_cN#w3lA&0TG8q6@l&@FR^NUj6QUOpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_10000000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_10000000_field_eq_idx", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 9986163, + "Plan Rows": 9998476, "Plan Width": 4, - "Relation Name": "json_ste_vec_small_encrypted_10000000", + "Relation Name": "json_ste_vec_small_encrypted_v3_10000000", "Scan Direction": "Forward", "Startup Cost": 0.69, - "Total Cost": 1876261.54 + "Total Cost": 2112453.02 } ], "Startup Cost": 0.69, - "Total Cost": 2.57 + "Total Cost": 2.8 } } ] @@ -569,10 +569,10 @@ ON json_ste_vec_small_encrypted_10000 USING GIN ( | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 10 | 506.68μs | N/A | -| 100,000 | 10 | 477.53μs | N/A | -| 1,000,000 | 10 | 465.99μs | N/A | -| 10,000,000 | 10 | 432.23μs | N/A | +| 10,000 | 10 | 807.07μs | N/A | +| 100,000 | 10 | 6.13ms | N/A | +| 1,000,000 | 10 | 72.04ms | N/A | +| 10,000,000 | 10 | 636.13μs | N/A | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -583,7 +583,7 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Seq Scan on json_ste_vec_small_encrypted_10000 + Seq Scan on json_ste_vec_small_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -599,21 +599,21 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_10000", + "Alias": "json_ste_vec_small_encrypted_v3_10000", "Async Capable": false, - "Filter": "((eql_v2.to_stevec_query(value))::jsonb @> (('{\"sv\": [{\"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}]}'::jsonb)::eql_v2.stevec_query)::jsonb)", + "Filter": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\"}'::jsonb[])", "Node Type": "Seq Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 9999, + "Plan Rows": 10000, "Plan Width": 4, - "Relation Name": "json_ste_vec_small_encrypted_10000", + "Relation Name": "json_ste_vec_small_encrypted_v3_10000", "Startup Cost": 0.0, - "Total Cost": 4474.0 + "Total Cost": 4645.0 } ], "Startup Cost": 0.0, - "Total Cost": 4.47 + "Total Cost": 4.64 } } ] @@ -623,7 +623,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on json_ste_vec_small_encrypted_100000 + Seq Scan on json_ste_vec_small_encrypted_v3_100000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -639,21 +639,21 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_100000", + "Alias": "json_ste_vec_small_encrypted_v3_100000", "Async Capable": false, - "Filter": "((eql_v2.to_stevec_query(value))::jsonb @> (('{\"sv\": [{\"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}]}'::jsonb)::eql_v2.stevec_query)::jsonb)", + "Filter": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\"}'::jsonb[])", "Node Type": "Seq Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 99990, + "Plan Rows": 100000, "Plan Width": 4, - "Relation Name": "json_ste_vec_small_encrypted_100000", + "Relation Name": "json_ste_vec_small_encrypted_v3_100000", "Startup Cost": 0.0, - "Total Cost": 44132.0 + "Total Cost": 46444.0 } ], "Startup Cost": 0.0, - "Total Cost": 4.41 + "Total Cost": 4.64 } } ] @@ -663,7 +663,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on json_ste_vec_small_encrypted_1000000 + Seq Scan on json_ste_vec_small_encrypted_v3_1000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -679,21 +679,21 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_1000000", + "Alias": "json_ste_vec_small_encrypted_v3_1000000", "Async Capable": false, - "Filter": "((eql_v2.to_stevec_query(value))::jsonb @> (('{\"sv\": [{\"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}]}'::jsonb)::eql_v2.stevec_query)::jsonb)", + "Filter": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\"}'::jsonb[])", "Node Type": "Seq Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 1002304, + "Plan Rows": 1001642, "Plan Width": 4, - "Relation Name": "json_ste_vec_small_encrypted_1000000", + "Relation Name": "json_ste_vec_small_encrypted_v3_1000000", "Startup Cost": 0.0, - "Total Cost": 432237.06 + "Total Cost": 464757.03 } ], "Startup Cost": 0.0, - "Total Cost": 4.31 + "Total Cost": 4.64 } } ] @@ -703,7 +703,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on json_ste_vec_small_encrypted_10000000 + Seq Scan on json_ste_vec_small_encrypted_v3_10000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -719,21 +719,21 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_10000000", + "Alias": "json_ste_vec_small_encrypted_v3_10000000", "Async Capable": false, - "Filter": "((eql_v2.to_stevec_query(value))::jsonb @> (('{\"sv\": [{\"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}]}'::jsonb)::eql_v2.stevec_query)::jsonb)", + "Filter": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\"}'::jsonb[])", "Node Type": "Seq Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 9985164, + "Plan Rows": 9998476, "Plan Width": 4, - "Relation Name": "json_ste_vec_small_encrypted_10000000", + "Relation Name": "json_ste_vec_small_encrypted_v3_10000000", "Startup Cost": 0.0, - "Total Cost": 4313101.2 + "Total Cost": 4527343.95 } ], "Startup Cost": 0.0, - "Total Cost": 4.32 + "Total Cost": 4.53 } } ] @@ -785,17 +785,17 @@ ON json_ste_vec_small_encrypted_10000 USING GIN ( **Indexes used by the planner (per data set size):** -- 10,000: `json_ste_vec_small_encrypted_10000_field_eq_idx` -- 100,000: `json_ste_vec_small_encrypted_100000_field_eq_idx` -- 1,000,000: `json_ste_vec_small_encrypted_1000000_field_eq_idx` -- 10,000,000: `json_ste_vec_small_encrypted_10000000_field_eq_idx` +- 10,000: `json_ste_vec_small_encrypted_v3_10000_field_eq_idx` +- 100,000: `json_ste_vec_small_encrypted_v3_100000_field_eq_idx` +- 1,000,000: `json_ste_vec_small_encrypted_v3_1000000_field_eq_idx` +- 10,000,000: `json_ste_vec_small_encrypted_v3_10000000_field_eq_idx` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 10 | 105.03μs | N/A | -| 100,000 | 10 | 102.71μs | N/A | -| 1,000,000 | 10 | 103.47μs | N/A | -| 10,000,000 | 10 | 106.50μs | N/A | +| 10,000 | 10 | 111.68μs | N/A | +| 100,000 | 10 | 115.59μs | N/A | +| 1,000,000 | 10 | 119.66μs | N/A | +| 10,000,000 | 10 | 97.53μs | N/A | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -806,7 +806,7 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Index Scan using json_ste_vec_small_encrypted_10000_field_eq_idx on json_ste_vec_small_encrypted_10000 + Index Scan using json_ste_vec_small_encrypted_v3_10000_field_eq_idx on json_ste_vec_small_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -822,23 +822,23 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_10000", + "Alias": "json_ste_vec_small_encrypted_v3_10000", "Async Capable": false, - "Index Cond": "(eql_v2.eq_term((value -> 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbLP(i?F+N4}@Yd7+CEvBh%4WvWGA-Clm>I7>+FpI2@T`6kjE%$~vnW*H{GSQRxTsN%B(Hto#H*A)ql=&pvnJm04OwTPpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_10000\"}, \"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"v\": 2, \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}'::jsonb)::eql_v2.ste_vec_entry))", - "Index Name": "json_ste_vec_small_encrypted_10000_field_eq_idx", + "Index Cond": "(eql_v3.eq_term(eql_v3.jsonb_path_query_first((value)::jsonb, '75146c96a91ff82146e29e87b5accb95'::text)) = eql_v3.eq_term(('{\"a\": false, \"c\": \"mBbKl&U3G&rdmu!jlvOTNtai|WzTf%GxRRf|8D&*yFcQeZw~`a2wXjcee|dUu?(RM*o=Mf^e@IT*g|>~0V||-vzKbT*s~X`M^rdAlgWgZ#Jz9V6vZ`F(4Uv%?$9NLh8{gxllTC75JJ6cXpEbP!uwg-8nnb9kNg%aApC#s*+tb_lY_4JjIjc(PWht(iJW)gKqCBRpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_10000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_10000_field_eq_idx", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 10000, "Plan Width": 4, - "Relation Name": "json_ste_vec_small_encrypted_10000", + "Relation Name": "json_ste_vec_small_encrypted_v3_10000", "Scan Direction": "Forward", "Startup Cost": 0.54, - "Total Cost": 2046.54 + "Total Cost": 2242.54 } ], "Startup Cost": 0.54, - "Total Cost": 2.58 + "Total Cost": 2.78 } } ] @@ -848,7 +848,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using json_ste_vec_small_encrypted_100000_field_eq_idx on json_ste_vec_small_encrypted_100000 + Index Scan using json_ste_vec_small_encrypted_v3_100000_field_eq_idx on json_ste_vec_small_encrypted_v3_100000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -864,23 +864,23 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_100000", + "Alias": "json_ste_vec_small_encrypted_v3_100000", "Async Capable": false, - "Index Cond": "(eql_v2.eq_term((value -> 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbJ#Az`rN2!?|a+B*-Bmmq?~X$Xb;T3=`{)vYGWIVl1O4v-;wGe0L(${xlw#6&~c2+OgUrj#oFGkUC;JCyf+BZwxob;Y*Mape$W+(md@rfSN5Ye@09b#rnIlsO#puh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_100000\"}, \"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"v\": 2, \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}'::jsonb)::eql_v2.ste_vec_entry))", - "Index Name": "json_ste_vec_small_encrypted_100000_field_eq_idx", + "Index Cond": "(eql_v3.eq_term(eql_v3.jsonb_path_query_first((value)::jsonb, '75146c96a91ff82146e29e87b5accb95'::text)) = eql_v3.eq_term(('{\"a\": false, \"c\": \"mBbL>G+POZxYGacl>M3T^U9ILZDpH%1hfdNmea4A8^XTV*dGo;>8yO5r?BT&aSI_ZsSuV&t8=ymMaG~D6e7#MN-qMs)Y%I_YVN-rsOB%cplB^itOiGKiEl{QCd4G!M9XzS&)=SJlG6IPjHQ5xoo1+$vm3D)DE!$9mVU$_o~@jtT%uE4Q&7M?5}sa{E9tIM-1n8!Nah=}AiNxXpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_100000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_100000_field_eq_idx", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 100000, "Plan Width": 4, - "Relation Name": "json_ste_vec_small_encrypted_100000", + "Relation Name": "json_ste_vec_small_encrypted_v3_100000", "Scan Direction": "Forward", "Startup Cost": 0.54, - "Total Cost": 19741.54 + "Total Cost": 22303.54 } ], "Startup Cost": 0.54, - "Total Cost": 2.52 + "Total Cost": 2.78 } } ] @@ -890,7 +890,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using json_ste_vec_small_encrypted_1000000_field_eq_idx on json_ste_vec_small_encrypted_1000000 + Index Scan using json_ste_vec_small_encrypted_v3_1000000_field_eq_idx on json_ste_vec_small_encrypted_v3_1000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -906,23 +906,23 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_1000000", + "Alias": "json_ste_vec_small_encrypted_v3_1000000", "Async Capable": false, - "Index Cond": "(eql_v2.eq_term((value -> 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbJeS~GW(rh_Ip#L(=Tk4TQhWW<9ljWmSq7yFQK{3){*^3mrvZVb*R$1K>{#a~UP>9qrQVA&6A(*plc?p!)G6K6VxXRF-Ao<%8ZuHeK?nJ3--0Nm!1=ln2Xui4i>S)gYG;I(F^bd2`!ND6isp!LMOUBn>CRQ!LHS7`%z%ZEdL=*l4D?dx-|!N3+f4h3PAmRMTaIoe$WB`ON`M4Kyne+%ye{{cPA*_4ri{z#dizy\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_1000000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_1000000_field_eq_idx", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 1002404, + "Plan Rows": 1001642, "Plan Width": 4, - "Relation Name": "json_ste_vec_small_encrypted_1000000", + "Relation Name": "json_ste_vec_small_encrypted_v3_1000000", "Scan Direction": "Forward", "Startup Cost": 0.68, - "Total Cost": 187629.75 + "Total Cost": 222842.41 } ], "Startup Cost": 0.68, - "Total Cost": 2.55 + "Total Cost": 2.9 } } ] @@ -932,7 +932,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using json_ste_vec_small_encrypted_10000000_field_eq_idx on json_ste_vec_small_encrypted_10000000 + Index Scan using json_ste_vec_small_encrypted_v3_10000000_field_eq_idx on json_ste_vec_small_encrypted_v3_10000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -948,23 +948,23 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 4, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_10000000", + "Alias": "json_ste_vec_small_encrypted_v3_10000000", "Async Capable": false, - "Index Cond": "(eql_v2.eq_term((value -> 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbJLhWn-J_XuAF@lJV1yj2RsWY00Q2F%S?!W`})*vltb>7kZ*|BK4On8t^sSE)U-JiRV)L0?jR{}{TcEhaWm?it8o3@A!B9O_Ve_vbf!P^7`HpOMhg7r=0>?cU1z3gGN?;ss-t|Pc*N4jA6b4XX?4ja(m^ns%IO=0v;tCgV#q5`TSV2hKIfV#*07WP+Ji7W{F$7iY3M9G5^FM;|!vaI5(ygH_cN#w3lA&0TG8q6@l&@FR^NUj6QUOpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_10000000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_10000000_field_eq_idx", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 9986163, + "Plan Rows": 9998476, "Plan Width": 4, - "Relation Name": "json_ste_vec_small_encrypted_10000000", + "Relation Name": "json_ste_vec_small_encrypted_v3_10000000", "Scan Direction": "Forward", "Startup Cost": 0.69, - "Total Cost": 1876261.54 + "Total Cost": 2112453.02 } ], "Startup Cost": 0.69, - "Total Cost": 2.57 + "Total Cost": 2.8 } } ] @@ -974,6 +974,230 @@ Full `EXPLAIN (FORMAT JSON)`: ![Query Performance - JSON/field_eq/functional](query_json_field_eq_functional_chart.png) +## field_gt/functional + +**Description:** Unknown query + +**** + +**Indexes available on the table:** +```sql +-- EQL 2.3 functional GIN indexes for the json ste_vec bench. +-- +-- jsonb_array — whole-document containment (contains/functional): +-- eql_v2.jsonb_array(value) @> eql_v2.jsonb_array($1). +-- stevec_query — typed field-level containment (field_eq/extractor): +-- value @> $1::eql_v2.stevec_query inlines to a native +-- jsonb @> over eql_v2.to_stevec_query(value)::jsonb. +-- XOR-aware: one index covers hm- and oc-bearing selectors. +-- +-- Replaces the pre-2.3 eql_v2.ste_vec / eql_v2.hmac_256_terms GIN indexes +-- (hmac_256_terms was removed in EQL 2.3 — see cipherstash/eql#223). + +CREATE INDEX +json_ste_vec_small_encrypted_10000_jsonb_array_index +ON json_ste_vec_small_encrypted_10000 USING GIN ( + eql_v2.jsonb_array(value) +); + +CREATE INDEX +json_ste_vec_small_encrypted_10000_stevec_query_index +ON json_ste_vec_small_encrypted_10000 USING GIN ( + (eql_v2.to_stevec_query(value)::jsonb) jsonb_path_ops +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: `json_ste_vec_small_encrypted_v3_10000_field_order_idx` +- 100,000: `json_ste_vec_small_encrypted_v3_100000_field_order_idx` +- 1,000,000: `json_ste_vec_small_encrypted_v3_1000000_field_order_idx` +- 10,000,000: `json_ste_vec_small_encrypted_v3_10000000_field_order_idx` + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 234.47μs | N/A | +| 100,000 | 10 | 848.51μs | N/A | +| 1,000,000 | 10 | 258.98μs | N/A | +| 10,000,000 | 10 | 392.79μs | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Index Scan using json_ste_vec_small_encrypted_v3_10000_field_order_idx on json_ste_vec_small_encrypted_v3_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_10000", + "Async Capable": false, + "Index Cond": "(eql_v3.ore_cllw(eql_v3.jsonb_path_query_first((value)::jsonb, '1c16090f62b45fc9a1404b2135beab94'::text)) > eql_v3.ore_cllw(('{\"a\": false, \"c\": \"mBbKl&U3G&rdmu!jlvOTNtai|6gK>*kN_ZyJpH9*c*$KTw9`)`)x;o={1z-A{D1D*Mb%o9gRb|Cu>!45`J)1foOj_sBK&5czy\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_10000\"}, \"s\": \"1c16090f62b45fc9a1404b2135beab94\", \"v\": 3, \"oc\": \"e108bb37379dfda0f0143886d8b88e748150ce18ba0d1fa98dda6bf96cb47d12150661d4710365e26993420af2ccd1d836df55ccbc9bb7a6fb4f5589c09032c4bf\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_10000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 2646, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.66, + "Total Cost": 6593.76 + } + ], + "Startup Cost": 0.66, + "Total Cost": 25.58 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Index Scan using json_ste_vec_small_encrypted_v3_100000_field_order_idx on json_ste_vec_small_encrypted_v3_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_100000", + "Async Capable": false, + "Index Cond": "(eql_v3.ore_cllw(eql_v3.jsonb_path_query_first((value)::jsonb, '1c16090f62b45fc9a1404b2135beab94'::text)) > eql_v3.ore_cllw(('{\"a\": false, \"c\": \"mBbL>G+POZxYGacl>M3T^U9IL6fdmJ|9;<-fD;-|!-w$DNLmafTf`uqt(>D=qElQ`P{2JBo?e$L>8?`T_m$H~<{Pshyc~U?zy\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_100000\"}, \"s\": \"1c16090f62b45fc9a1404b2135beab94\", \"v\": 3, \"oc\": \"e108bb37379dfda0f0143886d759d250a567842a7c3f5af2a6b3f2a58a8160fc3e4079dc9e54b19e671a8834488db7592a060356887c3e718a86beaefae5648294\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_100000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 62310, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.67, + "Total Cost": 85355.09 + } + ], + "Startup Cost": 0.67, + "Total Cost": 14.37 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Index Scan using json_ste_vec_small_encrypted_v3_1000000_field_order_idx on json_ste_vec_small_encrypted_v3_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_1000000", + "Async Capable": false, + "Index Cond": "(eql_v3.ore_cllw(eql_v3.jsonb_path_query_first((value)::jsonb, '1c16090f62b45fc9a1404b2135beab94'::text)) > eql_v3.ore_cllw(('{\"a\": false, \"c\": \"mBbJ%T#O?hLqA`E(Oz(edIR9Z6r5ZRt;(F4${{cPA*_4ri{z#dizy\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_1000000\"}, \"s\": \"1c16090f62b45fc9a1404b2135beab94\", \"v\": 3, \"oc\": \"e108bb37379dfda0f0143886d8b97d5813f5decb57cd129b4a3cfe86ba1339f27bee6833a277032ea11fd3cdaea0249e4dfd806fd691c652212db9a671e096a540\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_1000000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 23672, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.8, + "Total Cost": 91165.11 + } + ], + "Startup Cost": 0.8, + "Total Cost": 39.31 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Index Scan using json_ste_vec_small_encrypted_v3_10000000_field_order_idx on json_ste_vec_small_encrypted_v3_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_10000000", + "Async Capable": false, + "Index Cond": "(eql_v3.ore_cllw(eql_v3.jsonb_path_query_first((value)::jsonb, '1c16090f62b45fc9a1404b2135beab94'::text)) > eql_v3.ore_cllw(('{\"a\": false, \"c\": \"mBbKdL{%RNuK>0?jR{}{TcEha6s0(h*T(hF&eWwwx?&mD6;1%QQN$qQ45E=ZH>MOf%~L$ImtO1v5r;(;f$kkIv1)ycK6Hbizy\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_10000000\"}, \"s\": \"1c16090f62b45fc9a1404b2135beab94\", \"v\": 3, \"oc\": \"e108bb37379dfda0f0143886d8b88f3dc8ef1dbc11bad17ae69d7bd0c112796ba6416baf0e3b0dc577886a15389fc364d1b3ceb56488adecb738298ff9b47cd306\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_10000000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1190152, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.81, + "Total Cost": 3713359.52 + } + ], + "Startup Cost": 0.81, + "Total Cost": 32.01 + } + } +] +``` + +
+ +![Query Performance - JSON/field_gt/functional](query_json_field_gt_functional_chart.png) + ## field_order/functional **Description:** Field-level ORDER BY via ORE extractor on `value -> 'sel'` @@ -1018,17 +1242,17 @@ ON json_ste_vec_small_encrypted_10000 USING GIN ( **Indexes used by the planner (per data set size):** -- 10,000: `json_ste_vec_small_encrypted_10000_field_order_idx` -- 100,000: `json_ste_vec_small_encrypted_100000_field_order_idx` -- 1,000,000: `json_ste_vec_small_encrypted_1000000_field_order_idx` -- 10,000,000: `json_ste_vec_small_encrypted_10000000_field_order_idx` +- 10,000: `json_ste_vec_small_encrypted_v3_10000_field_order_idx` +- 100,000: `json_ste_vec_small_encrypted_v3_100000_field_order_idx` +- 1,000,000: `json_ste_vec_small_encrypted_v3_1000000_field_order_idx` +- 10,000,000: `json_ste_vec_small_encrypted_v3_10000000_field_order_idx` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 10 | 324.65μs | N/A | -| 100,000 | 10 | 315.29μs | N/A | -| 1,000,000 | 10 | 367.56μs | N/A | -| 10,000,000 | 10 | 367.54μs | N/A | +| 10,000 | 10 | 257.22μs | N/A | +| 100,000 | 10 | 279.27μs | N/A | +| 1,000,000 | 10 | 286.05μs | N/A | +| 10,000,000 | 10 | 343.30μs | N/A | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -1039,7 +1263,7 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Index Scan using json_ste_vec_small_encrypted_10000_field_order_idx on json_ste_vec_small_encrypted_10000 + Index Scan using json_ste_vec_small_encrypted_v3_10000_field_order_idx on json_ste_vec_small_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -1055,22 +1279,22 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 36, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_10000", + "Alias": "json_ste_vec_small_encrypted_v3_10000", "Async Capable": false, - "Index Name": "json_ste_vec_small_encrypted_10000_field_order_idx", + "Index Name": "json_ste_vec_small_encrypted_v3_10000_field_order_idx", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 10000, "Plan Width": 36, - "Relation Name": "json_ste_vec_small_encrypted_10000", + "Relation Name": "json_ste_vec_small_encrypted_v3_10000", "Scan Direction": "Forward", "Startup Cost": 0.41, - "Total Cost": 13014.19 + "Total Cost": 13797.16 } ], "Startup Cost": 0.41, - "Total Cost": 13.42 + "Total Cost": 14.21 } } ] @@ -1080,7 +1304,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using json_ste_vec_small_encrypted_100000_field_order_idx on json_ste_vec_small_encrypted_100000 + Index Scan using json_ste_vec_small_encrypted_v3_100000_field_order_idx on json_ste_vec_small_encrypted_v3_100000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -1096,22 +1320,22 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 36, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_100000", + "Alias": "json_ste_vec_small_encrypted_v3_100000", "Async Capable": false, - "Index Name": "json_ste_vec_small_encrypted_100000_field_order_idx", + "Index Name": "json_ste_vec_small_encrypted_v3_100000_field_order_idx", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 100000, "Plan Width": 36, - "Relation Name": "json_ste_vec_small_encrypted_100000", + "Relation Name": "json_ste_vec_small_encrypted_v3_100000", "Scan Direction": "Forward", "Startup Cost": 0.42, - "Total Cost": 127618.52 + "Total Cost": 137868.42 } ], "Startup Cost": 0.42, - "Total Cost": 13.18 + "Total Cost": 14.2 } } ] @@ -1121,7 +1345,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using json_ste_vec_small_encrypted_1000000_field_order_idx on json_ste_vec_small_encrypted_1000000 + Index Scan using json_ste_vec_small_encrypted_v3_1000000_field_order_idx on json_ste_vec_small_encrypted_v3_1000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -1137,22 +1361,22 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 36, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_1000000", + "Alias": "json_ste_vec_small_encrypted_v3_1000000", "Async Capable": false, - "Index Name": "json_ste_vec_small_encrypted_1000000_field_order_idx", + "Index Name": "json_ste_vec_small_encrypted_v3_1000000_field_order_idx", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 1002404, + "Plan Rows": 1001642, "Plan Width": 36, - "Relation Name": "json_ste_vec_small_encrypted_1000000", + "Relation Name": "json_ste_vec_small_encrypted_v3_1000000", "Scan Direction": "Forward", "Startup Cost": 0.55, - "Total Cost": 1238292.08 + "Total Cost": 1378881.81 } ], "Startup Cost": 0.55, - "Total Cost": 12.9 + "Total Cost": 14.32 } } ] @@ -1162,7 +1386,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using json_ste_vec_small_encrypted_10000000_field_order_idx on json_ste_vec_small_encrypted_10000000 + Index Scan using json_ste_vec_small_encrypted_v3_10000000_field_order_idx on json_ste_vec_small_encrypted_v3_10000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -1178,22 +1402,22 @@ Full `EXPLAIN (FORMAT JSON)`: "Plan Width": 36, "Plans": [ { - "Alias": "json_ste_vec_small_encrypted_10000000", + "Alias": "json_ste_vec_small_encrypted_v3_10000000", "Async Capable": false, - "Index Name": "json_ste_vec_small_encrypted_10000000_field_order_idx", + "Index Name": "json_ste_vec_small_encrypted_v3_10000000_field_order_idx", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 9986163, + "Plan Rows": 9998476, "Plan Width": 36, - "Relation Name": "json_ste_vec_small_encrypted_10000000", + "Relation Name": "json_ste_vec_small_encrypted_v3_10000000", "Scan Direction": "Forward", "Startup Cost": 0.56, - "Total Cost": 12366683.86 + "Total Cost": 13318010.53 } ], "Startup Cost": 0.56, - "Total Cost": 12.94 + "Total Cost": 13.88 } } ] diff --git a/report/match.md b/report/match.md index c921922..c878d80 100644 --- a/report/match.md +++ b/report/match.md @@ -34,19 +34,15 @@ ON string_encrypted_10000 USING GIN ( **Indexes used by the planner (per data set size):** -- 10,000: `string_encrypted_10000_gin_index` -- 100,000: `string_encrypted_100000_gin_index` -- 1,000,000: `string_encrypted_1000000_gin_index` -- 10,000,000: `string_encrypted_10000000_gin_index` - -*⚠️ = Query time exceeds 100ms* +- 10,000: `string_encrypted_v3_10000_match_gin_index` +- 100,000: `string_encrypted_v3_100000_match_gin_index` +- 1,000,000: `string_encrypted_v3_1000000_match_gin_index` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 10 | 411.27μs | 27.04ms | -| 100,000 | 10 | 1.77ms | 26.41ms | -| 1,000,000 | 10 | 14.48ms | 39.91ms | -| 10,000,000 | 10 | ⚠️ 144.09ms | ⚠️ 169.68ms | +| 10,000 | 10 | 451.02μs | 26.21ms | +| 100,000 | 10 | 1.94ms | 27.22ms | +| 1,000,000 | 10 | 15.91ms | 38.47ms | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -57,8 +53,8 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Bitmap Heap Scan on string_encrypted_10000 - Bitmap Index Scan using string_encrypted_10000_gin_index + Bitmap Heap Scan on string_encrypted_v3_10000 + Bitmap Index Scan using string_encrypted_v3_10000_match_gin_index ``` Full `EXPLAIN (FORMAT JSON)`: @@ -71,38 +67,38 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 649, "Plans": [ { - "Alias": "string_encrypted_10000", + "Alias": "string_encrypted_v3_10000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 649, "Plans": [ { "Async Capable": false, - "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1109,1596,61,1500,587,582,865,1845,1760,792,1057,1018,1637,421,710,1496,1751,830,1068,1183,895,1574,1031,2028,998,1143,1453,1735,1200,682}'::smallint[])", - "Index Name": "string_encrypted_10000_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK6geIMV!9#{o-M(hFFN~VR8PwMuWMt~Cw`xiU '{1109,1596,61,1500,587,582,865,1845,1760,792,1057,1018,1637,421,710,1496,1751,830,1068,1183,895,1574,1031,2028,998,1143,1453,1735,1200,682}'::smallint[])", - "Relation Name": "string_encrypted_10000", - "Startup Cost": 264.6, - "Total Cost": 269.11 + "Recheck Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK6geIMV!9#{o-M(hFFN~VR8PwMuWMt~Cw`xiU '{1637,1760,998,1845,1574,1453,582,1068,421,865,1143,1057,1751,1183,1031,710,1596,1018,830,587,1109,1200,682,895,792,1500,1496,1735,2028,61}'::smallint[])", - "Index Name": "string_encrypted_100000_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLE9E2f5{Z(7DX-`9~7F5*48R1ytR5Agx`ktr4Az!6uI~#kR6qwhp?$E>_AXr6YO@n@(5^dBRDN3J$dKi~^RA5Rx1Ea!IRTW-rrFLO#b!Eg5 '{1637,1760,998,1845,1574,1453,582,1068,421,865,1143,1057,1751,1183,1031,710,1596,1018,830,587,1109,1200,682,895,792,1500,1496,1735,2028,61}'::smallint[])", - "Relation Name": "string_encrypted_100000", - "Startup Cost": 458.48, - "Total Cost": 462.99 + "Recheck Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLE9E2f5{Z(7DX-`9~7F5*48R1ytR5Agx`ktr4Az!6uI~#kR6qwhp?$E>_AXr6YO@n@(5^dBRDN3J$dKi~^RA5Rx1Ea!IRTW-rrFLO#b!Eg5 '{1031,587,1200,998,1574,792,1183,865,1596,1109,1057,895,1143,1751,682,582,1735,1496,1018,2028,421,830,1845,1068,61,1637,1760,1500,1453,710}'::smallint[])", - "Index Name": "string_encrypted_1000000_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLtxJ*y)8G7e;FlzQ)wP)Pb4ESN&ek;C_ScK0!jl9Gl%f}S5o@rpaMNn4jp{G`01PtKKvz);2c!lu5IuJhKrFLO#b!Eg5 '{1031,587,1200,998,1574,792,1183,865,1596,1109,1057,895,1143,1751,682,582,1735,1496,1018,2028,421,830,1845,1068,61,1637,1760,1500,1453,710}'::smallint[])", - "Relation Name": "string_encrypted_1000000", - "Startup Cost": 1407.6, - "Total Cost": 1412.11 + "Recheck Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLtxJ*y)8G7e;FlzQ)wP)Pb4ESN&ek;C_ScK0!jl9Gl%f}S5o@rpaMNn4jp{G`01PtKKvz);2c!lu5IuJhKrFLO#b!Eg5 + +![Query Performance - MATCH/eql_bloom](query_match_eql_bloom_chart.png) + +## eql_bloom_noindex + +**Description:** Unknown query + +**** + +**Indexes available on the table:** +```sql +CREATE INDEX +string_encrypted_10000_hash_index +ON string_encrypted_10000 using hash ( + eql_v2.hmac_256(value) +); + +CREATE INDEX +string_encrypted_10000_gin_index +ON string_encrypted_10000 USING GIN ( + eql_v2.bloom_filter(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 57.49ms | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** ``` Limit - Bitmap Heap Scan on string_encrypted_10000000 - Bitmap Index Scan using string_encrypted_10000000_gin_index + Seq Scan on string_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -236,38 +269,24 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 649, "Plans": [ { - "Alias": "string_encrypted_10000000", + "Alias": "string_encrypted_v3_10000", "Async Capable": false, - "Node Type": "Bitmap Heap Scan", + "Filter": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK6geIMV!9#{o-M(hFFN~VR8PwMuWMt~Cw`xiU '{1453,421,61,2028,895,1596,1574,865,1845,792,587,1018,1735,998,1143,1496,1109,1031,1637,710,1200,1751,682,582,1760,1068,830,1183,1500,1057}'::smallint[])", - "Index Name": "string_encrypted_10000000_gin_index", - "Node Type": "Bitmap Index Scan", - "Parallel Aware": false, - "Parent Relationship": "Outer", - "Plan Rows": 1, - "Plan Width": 0, - "Startup Cost": 0.0, - "Total Cost": 11237.48 - } - ], - "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1453,421,61,2028,895,1596,1574,865,1845,792,587,1018,1735,998,1143,1496,1109,1031,1637,710,1200,1751,682,582,1760,1068,830,1183,1500,1057}'::smallint[])", - "Relation Name": "string_encrypted_10000000", - "Startup Cost": 11237.48, - "Total Cost": 11241.99 + "Plan Width": 649, + "Relation Name": "string_encrypted_v3_10000", + "Startup Cost": 0.0, + "Total Cost": 6033.0 } ], - "Startup Cost": 11237.48, - "Total Cost": 11241.99 + "Startup Cost": 0.0, + "Total Cost": 6033.0 } } ] @@ -275,8 +294,6 @@ Full `EXPLAIN (FORMAT JSON)`:
-![Query Performance - MATCH/eql_bloom](query_match_eql_bloom_chart.png) - ## eql_cast_firstname **Description:** Pattern matching on first name using EQL cast and LIKE @@ -307,17 +324,15 @@ ON string_encrypted_10000 USING GIN ( **Indexes used by the planner (per data set size):** -- 10,000: `string_encrypted_10000_gin_index` -- 100,000: `string_encrypted_100000_gin_index` -- 1,000,000: `string_encrypted_1000000_gin_index` -- 10,000,000: `string_encrypted_10000000_gin_index` +- 10,000: `string_encrypted_v3_10000_match_gin_index` +- 100,000: `string_encrypted_v3_100000_match_gin_index` +- 1,000,000: `string_encrypted_v3_1000000_match_gin_index` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 2 | 152.35μs | 24.28ms | -| 100,000 | 10 | 634.91μs | 26.58ms | -| 1,000,000 | 10 | 3.77ms | 30.13ms | -| 10,000,000 | 10 | 33.69ms | 58.11ms | +| 10,000 | 4 | 192.49μs | 25.29ms | +| 100,000 | 10 | 647.12μs | 26.80ms | +| 1,000,000 | 10 | 3.30ms | 29.18ms | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -328,8 +343,8 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Bitmap Heap Scan on string_encrypted_10000 - Bitmap Index Scan using string_encrypted_10000_gin_index + Bitmap Heap Scan on string_encrypted_v3_10000 + Bitmap Index Scan using string_encrypted_v3_10000_match_gin_index ``` Full `EXPLAIN (FORMAT JSON)`: @@ -342,38 +357,38 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 649, "Plans": [ { - "Alias": "string_encrypted_10000", + "Alias": "string_encrypted_v3_10000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 649, "Plans": [ { "Async Capable": false, - "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1033,91,1393,453,1554,461}'::smallint[])", - "Index Name": "string_encrypted_10000_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbMCHrS1~w;M;JIX$Z1@!3Db6&P7}cvVmd|7A998N!x%-FoK9K{3Q2oR3{jJqZ1`ZahL+C>^;yuL!X7naxfl1#8xZ7DGP_rFLO#b!Eg5 '{1033,91,1393,453,1554,461}'::smallint[])", - "Relation Name": "string_encrypted_10000", - "Startup Cost": 56.22, - "Total Cost": 60.73 + "Recheck Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbMCHrS1~w;M;JIX$Z1@!3Db6&P7}cvVmd|7A998N!x%-FoK9K{3Q2oR3{jJqZ1`ZahL+C>^;yuL!X7naxfl1#8xZ7DGP_rFLO#b!Eg5 '{91,461,1393,1033,1554,453}'::smallint[])", - "Index Name": "string_encrypted_100000_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbMLz~2cP@FT7`S21vuMQ&ci6~9jRjYwz<^4*v?e~*vfjs2_eCcMNTm06{}Y6Vr$M4t10C_aUbyg1XU@>B70@|IMkxe?&2rFLO#b!Eg5 '{91,461,1393,1033,1554,453}'::smallint[])", - "Relation Name": "string_encrypted_100000", - "Startup Cost": 93.35, - "Total Cost": 97.86 + "Recheck Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbMLz~2cP@FT7`S21vuMQ&ci6~9jRjYwz<^4*v?e~*vfjs2_eCcMNTm06{}Y6Vr$M4t10C_aUbyg1XU@>B70@|IMkxe?&2rFLO#b!Eg5 '{91,453,1033,1554,461,1393}'::smallint[])", - "Index Name": "string_encrypted_1000000_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJ_X{{~BP#>&#D7Y>RXZF*?6>C%&G83QGc|dYrvBqP`>Ll5pn|H(@aXk=W91Dul)AD0BwsiOFUeqs<(o@qL45|qKKu{3mrFLO#b!Eg5 '{91,453,1033,1554,461,1393}'::smallint[])", - "Relation Name": "string_encrypted_1000000", - "Startup Cost": 282.35, - "Total Cost": 286.86 + "Recheck Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJ_X{{~BP#>&#D7Y>RXZF*?6>C%&G83QGc|dYrvBqP`>Ll5pn|H(@aXk=W91Dul)AD0BwsiOFUeqs<(o@qL45|qKKu{3mrFLO#b!Eg5 + +![Query Performance - MATCH/eql_cast_firstname](query_match_eql_cast_firstname_chart.png) + +## eql_cast_firstname_noindex + +**Description:** Unknown query + +**** + +**Indexes available on the table:** +```sql +CREATE INDEX +string_encrypted_10000_hash_index +ON string_encrypted_10000 using hash ( + eql_v2.hmac_256(value) +); + +CREATE INDEX +string_encrypted_10000_gin_index +ON string_encrypted_10000 USING GIN ( + eql_v2.bloom_filter(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +*⚠️ = Query time exceeds 100ms* + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 4 | ⚠️ 188.79ms | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** ``` Limit - Bitmap Heap Scan on string_encrypted_10000000 - Bitmap Index Scan using string_encrypted_10000000_gin_index + Seq Scan on string_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -507,38 +561,24 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 649, "Plans": [ { - "Alias": "string_encrypted_10000000", + "Alias": "string_encrypted_v3_10000", "Async Capable": false, - "Node Type": "Bitmap Heap Scan", + "Filter": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbMCHrS1~w;M;JIX$Z1@!3Db6&P7}cvVmd|7A998N!x%-FoK9K{3Q2oR3{jJqZ1`ZahL+C>^;yuL!X7naxfl1#8xZ7DGP_rFLO#b!Eg5 '{1033,91,1554,461,453,1393}'::smallint[])", - "Index Name": "string_encrypted_10000000_gin_index", - "Node Type": "Bitmap Index Scan", - "Parallel Aware": false, - "Parent Relationship": "Outer", - "Plan Rows": 1, - "Plan Width": 0, - "Startup Cost": 0.0, - "Total Cost": 2249.97 - } - ], - "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1033,91,1554,461,453,1393}'::smallint[])", - "Relation Name": "string_encrypted_10000000", - "Startup Cost": 2249.97, - "Total Cost": 2254.48 + "Plan Width": 649, + "Relation Name": "string_encrypted_v3_10000", + "Startup Cost": 0.0, + "Total Cost": 6033.0 } ], - "Startup Cost": 2249.97, - "Total Cost": 2254.48 + "Startup Cost": 0.0, + "Total Cost": 6033.0 } } ] @@ -546,8 +586,6 @@ Full `EXPLAIN (FORMAT JSON)`:
-![Query Performance - MATCH/eql_cast_firstname](query_match_eql_cast_firstname_chart.png) - ## eql_cast_lastname **Description:** Pattern matching on last name using EQL cast and LIKE @@ -578,19 +616,15 @@ ON string_encrypted_10000 USING GIN ( **Indexes used by the planner (per data set size):** -- 10,000: `string_encrypted_10000_gin_index` -- 100,000: `string_encrypted_100000_gin_index` -- 1,000,000: `string_encrypted_1000000_gin_index` -- 10,000,000: `string_encrypted_10000000_gin_index` - -*⚠️ = Query time exceeds 100ms* +- 10,000: `string_encrypted_v3_10000_match_gin_index` +- 100,000: `string_encrypted_v3_100000_match_gin_index` +- 1,000,000: `string_encrypted_v3_1000000_match_gin_index` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 10 | 437.17μs | 27.30ms | -| 100,000 | 10 | 1.79ms | 28.08ms | -| 1,000,000 | 10 | 14.40ms | 39.25ms | -| 10,000,000 | 10 | ⚠️ 144.81ms | ⚠️ 168.13ms | +| 10,000 | 10 | 508.58μs | 26.48ms | +| 100,000 | 10 | 2.03ms | 27.45ms | +| 1,000,000 | 10 | 15.86ms | 38.34ms | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -601,8 +635,8 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Bitmap Heap Scan on string_encrypted_10000 - Bitmap Index Scan using string_encrypted_10000_gin_index + Bitmap Heap Scan on string_encrypted_v3_10000 + Bitmap Index Scan using string_encrypted_v3_10000_match_gin_index ``` Full `EXPLAIN (FORMAT JSON)`: @@ -615,38 +649,38 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 649, "Plans": [ { - "Alias": "string_encrypted_10000", + "Alias": "string_encrypted_v3_10000", "Async Capable": false, "Node Type": "Bitmap Heap Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 649, "Plans": [ { "Async Capable": false, - "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1574,1109,1637,710,61,792,1760,1143,1057,1068,865,1453,1031,1751,587,1200,1596,895,1496,1845,1500,998,830,421,582,2028,1735,682,1183,1018}'::smallint[])", - "Index Name": "string_encrypted_10000_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK@RHT_YQgengq0NT#Vn-ds8Nco=9U0`fwxj!r22fFSMo^acQ=8LbIMKu){Zb2|wb~7RQV8hZEg-4Ab(Ns{<6e>NueN@ETJDB{rFLO#b!Eg5 '{1574,1109,1637,710,61,792,1760,1143,1057,1068,865,1453,1031,1751,587,1200,1596,895,1496,1845,1500,998,830,421,582,2028,1735,682,1183,1018}'::smallint[])", - "Relation Name": "string_encrypted_10000", - "Startup Cost": 264.6, - "Total Cost": 269.11 + "Recheck Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK@RHT_YQgengq0NT#Vn-ds8Nco=9U0`fwxj!r22fFSMo^acQ=8LbIMKu){Zb2|wb~7RQV8hZEg-4Ab(Ns{<6e>NueN@ETJDB{rFLO#b!Eg5 '{895,1637,1183,582,1109,1845,1496,1031,865,682,1500,1760,1068,1200,1574,830,1453,1018,1735,792,1143,998,587,1057,2028,1751,421,710,61,1596}'::smallint[])", - "Index Name": "string_encrypted_100000_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK3c9YZ~YabiHj6ChG6PoPA86?R^#FT36G&YMDin={;E^5p$n{Rny;MEEKCbRP=$(U^*rFLO#b!Eg5 '{895,1637,1183,582,1109,1845,1496,1031,865,682,1500,1760,1068,1200,1574,830,1453,1018,1735,792,1143,998,587,1057,2028,1751,421,710,61,1596}'::smallint[])", - "Relation Name": "string_encrypted_100000", - "Startup Cost": 458.48, - "Total Cost": 462.99 + "Recheck Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK3c9YZ~YabiHj6ChG6PoPA86?R^#FT36G&YMDin={;E^5p$n{Rny;MEEKCbRP=$(U^*rFLO#b!Eg5 '{2028,1735,865,1845,1596,1637,1760,1031,792,682,1496,1751,1109,61,582,587,1500,1057,895,1143,998,1183,710,1574,1068,1018,1453,1200,421,830}'::smallint[])", - "Index Name": "string_encrypted_1000000_gin_index", + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJprUR4NIxndC;^h8FmqQK286&V4b '{2028,1735,865,1845,1596,1637,1760,1031,792,682,1496,1751,1109,61,582,587,1500,1057,895,1143,998,1183,710,1574,1068,1018,1453,1200,421,830}'::smallint[])", - "Relation Name": "string_encrypted_1000000", - "Startup Cost": 1407.6, - "Total Cost": 1412.11 + "Recheck Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJprUR4NIxndC;^h8FmqQK286&V4b + +![Query Performance - MATCH/eql_cast_lastname](query_match_eql_cast_lastname_chart.png) + +## eql_cast_lastname_noindex + +**Description:** Unknown query + +**** + +**Indexes available on the table:** +```sql +CREATE INDEX +string_encrypted_10000_hash_index +ON string_encrypted_10000 using hash ( + eql_v2.hmac_256(value) +); + +CREATE INDEX +string_encrypted_10000_gin_index +ON string_encrypted_10000 USING GIN ( + eql_v2.bloom_filter(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 55.60ms | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** ``` Limit - Bitmap Heap Scan on string_encrypted_10000000 - Bitmap Index Scan using string_encrypted_10000000_gin_index + Seq Scan on string_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -780,38 +851,24 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 1, - "Plan Width": 36, + "Plan Width": 649, "Plans": [ { - "Alias": "string_encrypted_10000000", + "Alias": "string_encrypted_v3_10000", "Async Capable": false, - "Node Type": "Bitmap Heap Scan", + "Filter": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK@RHT_YQgengq0NT#Vn-ds8Nco=9U0`fwxj!r22fFSMo^acQ=8LbIMKu){Zb2|wb~7RQV8hZEg-4Ab(Ns{<6e>NueN@ETJDB{rFLO#b!Eg5 '{830,1500,1143,1031,1574,1109,1068,1453,1845,895,1057,1496,1751,582,61,587,1183,998,2028,1735,1018,792,1760,710,865,1200,1637,421,682,1596}'::smallint[])", - "Index Name": "string_encrypted_10000000_gin_index", - "Node Type": "Bitmap Index Scan", - "Parallel Aware": false, - "Parent Relationship": "Outer", - "Plan Rows": 1, - "Plan Width": 0, - "Startup Cost": 0.0, - "Total Cost": 11237.48 - } - ], - "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{830,1500,1143,1031,1574,1109,1068,1453,1845,895,1057,1496,1751,582,61,587,1183,998,2028,1735,1018,792,1760,710,865,1200,1637,421,682,1596}'::smallint[])", - "Relation Name": "string_encrypted_10000000", - "Startup Cost": 11237.48, - "Total Cost": 11241.99 + "Plan Width": 649, + "Relation Name": "string_encrypted_v3_10000", + "Startup Cost": 0.0, + "Total Cost": 6033.0 } ], - "Startup Cost": 11237.48, - "Total Cost": 11241.99 + "Startup Cost": 0.0, + "Total Cost": 6033.0 } } ] @@ -819,5 +876,3 @@ Full `EXPLAIN (FORMAT JSON)`:
-![Query Performance - MATCH/eql_cast_lastname](query_match_eql_cast_lastname_chart.png) - diff --git a/report/ope.md b/report/ope.md new file mode 100644 index 0000000..466a995 --- /dev/null +++ b/report/ope.md @@ -0,0 +1,959 @@ +# OPE Queries + +[← Back to overview](./BENCHMARK_REPORT.md) + +Per-tier query performance. Each scenario lists its SQL, the indexes available on the target table, the indexes the planner actually picked per tier, the timing table, and the full EXPLAIN plan in a collapsed block. + +## range_gt_10 + +**Description:** Unknown query + +**** + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 124.26μs | 25.40ms | +| 100,000 | 10 | 126.02μs | 27.59ms | +| 1,000,000 | 10 | 119.24μs | 25.93ms | +| 10,000,000 | 10 | 127.50μs | 26.10ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbKOi_ajD8RR*KEc<~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4900, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000", + "Startup Cost": 0.0, + "Total Cost": 667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.36 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_100000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbJ}&XUD-x*pRImY=ziRm6wH7O8AtCGbtfs8RoE%qq?3vU?k$8NbfNAjF`?&j}TIg>yV(L?1L>$PCIfktJsGc%(32jW4JYLZx~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_100000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 49000, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_100000", + "Startup Cost": 0.0, + "Total Cost": 6667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.36 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_1000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbK+?~T_j#`TM@qnj*iH=a(!7LZxN6ukdL0nx1oml)*as3z!Jf2qpEAlsgc6z|IH`yBH)%q-Xzec<;TJAyT-&H#&y#-9D5>7{mIY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_1000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 489999, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_1000000", + "Startup Cost": 0.0, + "Total Cost": 66666.93 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.36 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbJ*D^%CH^pK*8eNzy+PiQd27MH8AXOFm^1`Y~3T6iZaN9zPUOl+XUAdm(#CHXW6rcMcPu2+gn3!Pn*r1z?aTD3E|d|Ja6rKNUZY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4900004, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000000", + "Startup Cost": 0.0, + "Total Cost": 666667.2 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.36 + } + } +] +``` + +
+ +![Query Performance - OPE/range_gt_10](query_ope_range_gt_10_chart.png) + +## range_gt_100 + +**Description:** Unknown query + +**** + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 100 | 359.32μs | 38.88ms | +| 100,000 | 100 | 1.05ms | 34.48ms | +| 1,000,000 | 100 | 352.02μs | 35.28ms | +| 10,000,000 | 100 | 349.36μs | 36.17ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbLs&G5#%sfy7<#%LR^)WDR)7I7n!?B?=f;uf!T&BfL$Wmx_~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4900, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000", + "Startup Cost": 0.0, + "Total Cost": 667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.61 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_100000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbJg#7PiKl7cIG3~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_100000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 49000, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_100000", + "Startup Cost": 0.0, + "Total Cost": 6667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.61 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_1000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbK^x+*{V9>s0@xqq8!@$@Ie7Hv#zmfs$2NNA)Arr0hEUddlL8e(9?Ai6MMMq+lgn2l=wZ$yw%`=a`HGHb9I67$@@1%pEHLZx~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_1000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 489999, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_1000000", + "Startup Cost": 0.0, + "Total Cost": 66666.93 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.61 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbLe4)1Uyz>(pXT)IoJmmYk?7GN?It1|j3GB}iQ(^@JTi*pzCuQEf#Adnq%>{7!fs*)%11%*B#nrpq4T!4k^0_9J})dwFJ5T$luY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4900004, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000000", + "Startup Cost": 0.0, + "Total Cost": 666667.2 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.61 + } + } +] +``` + +
+ +![Query Performance - OPE/range_gt_100](query_ope_range_gt_100_chart.png) + +## range_lt_10 + +**Description:** Unknown query + +**** + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 121.12μs | 25.28ms | +| 100,000 | 10 | 136.33μs | 27.61ms | +| 1,000,000 | 10 | 125.81μs | 25.60ms | +| 10,000,000 | 10 | 123.44μs | 26.04ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbK`7(rQMY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5099, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000", + "Startup Cost": 0.0, + "Total Cost": 667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.31 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_100000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbLTg=v9e4Yqyi9>ceKXo|DM7E3f^I%tzHtfr1Wua~@>kaKMk~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_100000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50999, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_100000", + "Startup Cost": 0.0, + "Total Cost": 6667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.31 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_1000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbLD8ij=<0B8ZygjgKfi6+d%76P1S=XL=`QPQLx;~t`H5PtZ*_i**ZAQ$JwRw%cxS!o=@!`yPKjBvotbFvcM7y~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_1000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 509997, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_1000000", + "Startup Cost": 0.0, + "Total Cost": 66666.93 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.31 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbJ}KN@m0Vt!q?H|+?q@!Gb;7OHRNfZTiRlhr}j(ldytUg~02ZMfCMAR}Q8>jjQ^*dZ^EXLiGP5&Q3~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5100003, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000000", + "Startup Cost": 0.0, + "Total Cost": 666667.2 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.31 + } + } +] +``` + +
+ +![Query Performance - OPE/range_lt_10](query_ope_range_lt_10_chart.png) + +## range_lt_100 + +**Description:** Unknown query + +**** + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 100 | 375.98μs | 36.05ms | +| 100,000 | 100 | 3.20ms | 31.73ms | +| 1,000,000 | 100 | 375.96μs | 34.03ms | +| 10,000,000 | 100 | 369.13μs | 36.35ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbLvE10t2Akl*opobYXOeVm@7TEpdcklge_K7Q?YL@CQMc_!rl84X4AWgv~tAx-BN9<(tIQKV1-U7S^~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5099, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000", + "Startup Cost": 0.0, + "Total Cost": 667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.08 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_100000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbJ%R0?+PM(81m9WxGq#ia(s77qsA;%~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_100000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50999, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_100000", + "Startup Cost": 0.0, + "Total Cost": 6667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.07 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_1000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbL*TdMC>F-tFWYV>tK-6fR77Gb5r_O}cXX52nQ{mHERx3mOd5A^TEAfu38=XVTgldQz&@P#7ScrGgG!7$tJGX|G6D(&_RwxxDqY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_1000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 509997, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_1000000", + "Startup Cost": 0.0, + "Total Cost": 66666.93 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.07 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_ope_v3_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbLdM+5GJke|qCGORG`xKKvK7F?Mgu)3q~=x~dENpA(a;icNDTXy8cAYTp~cDv-iprp`767t1j2lop6k1&OJU(wGg2@nCGZKZZ$Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5100003, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000000", + "Startup Cost": 0.0, + "Total Cost": 666667.2 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.07 + } + } +] +``` + +
+ +![Query Performance - OPE/range_lt_100](query_ope_range_lt_100_chart.png) + +## range_lt_ordered_10 + +**Description:** Unknown query + +**** + +**Indexes used by the planner (per data set size):** + +- 10,000: `integer_encrypted_ope_v3_10000_ope_index` +- 100,000: `integer_encrypted_ope_v3_100000_ope_index` +- 1,000,000: `integer_encrypted_ope_v3_1000000_ope_index` +- 10,000,000: `integer_encrypted_ope_v3_10000000_ope_index` + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 121.35μs | 25.20ms | +| 100,000 | 10 | 120.86μs | 26.32ms | +| 1,000,000 | 10 | 121.70μs | 25.84ms | +| 10,000,000 | 10 | 117.03μs | 26.03ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Index Scan using integer_encrypted_ope_v3_10000_ope_index on integer_encrypted_ope_v3_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 342, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000", + "Async Capable": false, + "Index Cond": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbL#Nr!vV5d4dUCz}Rt{Cm#C7A4r&Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Index Name": "integer_encrypted_ope_v3_10000_ope_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5099, + "Plan Width": 342, + "Relation Name": "integer_encrypted_ope_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.29, + "Total Cost": 1935.0 + } + ], + "Startup Cost": 0.29, + "Total Cost": 4.09 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Index Scan using integer_encrypted_ope_v3_100000_ope_index on integer_encrypted_ope_v3_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 342, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_100000", + "Async Capable": false, + "Index Cond": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbK7g!PJwK8UTvfXl!6v2XRn7Bj_VXw=|129ohRluho~2X@7`qRY+1ARo+^qDvRPLhyfvLG6yt_g@7}_fTgfr>|yg`HVRVNu_pSY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_100000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Index Name": "integer_encrypted_ope_v3_100000_ope_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50999, + "Plan Width": 342, + "Relation Name": "integer_encrypted_ope_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.42, + "Total Cost": 19293.98 + } + ], + "Startup Cost": 0.42, + "Total Cost": 4.21 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Index Scan using integer_encrypted_ope_v3_1000000_ope_index on integer_encrypted_ope_v3_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 342, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_1000000", + "Async Capable": false, + "Index Cond": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbKezDw|;`?yAXfWc`e9n|Z@77X~ROK@ra?bIjs@5QIeh?qk&>OD-vAY5O%d`OQ>VG;rYwUr3prv+UY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_1000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Index Name": "integer_encrypted_ope_v3_1000000_ope_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 509997, + "Plan Width": 342, + "Relation Name": "integer_encrypted_ope_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.43, + "Total Cost": 192851.31 + } + ], + "Startup Cost": 0.43, + "Total Cost": 4.21 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Index Scan using integer_encrypted_ope_v3_10000000_ope_index on integer_encrypted_ope_v3_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 342, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000000", + "Async Capable": false, + "Index Cond": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbL@j+;gjy@US)2m|md_5%dO7DrC@GK|Q=mXk-9KR0{>9EY9Fq>9MIAP;L)BNx=z^r}7cpPwMkOC9ix!@;H$cp(jY4`+CpVx@LrY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Index Name": "integer_encrypted_ope_v3_10000000_ope_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5100003, + "Plan Width": 342, + "Relation Name": "integer_encrypted_ope_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.57, + "Total Cost": 1928102.41 + } + ], + "Startup Cost": 0.57, + "Total Cost": 4.35 + } + } +] +``` + +
+ +![Query Performance - OPE/range_lt_ordered_10](query_ope_range_lt_ordered_10_chart.png) + diff --git a/report/ore.md b/report/ore.md index 06167f1..1a22094 100644 --- a/report/ore.md +++ b/report/ore.md @@ -28,17 +28,17 @@ ON integer_encrypted_10000 ( **Indexes used by the planner (per data set size):** -- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ -- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ -- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ -- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000: `integer_encrypted_v3_10000_ord_index` +- 100,000: `integer_encrypted_v3_100000_ord_index` +- 1,000,000: `integer_encrypted_v3_1000000_ord_index` +- 10,000,000: `integer_encrypted_v3_10000000_ord_index` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 10 | 629.63μs | 31.20ms | -| 100,000 | 10 | 568.25μs | 25.67ms | -| 1,000,000 | 10 | 699.44μs | 26.64ms | -| 10,000,000 | 10 | 605.03μs | 25.46ms | +| 10,000 | 10 | 502.66μs | 26.89ms | +| 100,000 | 10 | 541.35μs | 26.12ms | +| 1,000,000 | 10 | 541.58μs | 25.77ms | +| 10,000,000 | 10 | 549.02μs | 26.25ms | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -49,7 +49,7 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Seq Scan on integer_encrypted_10000 + Index Scan using integer_encrypted_v3_10000_ord_index on integer_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -62,24 +62,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 10, - "Plan Width": 1096, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_10000", + "Alias": "integer_encrypted_v3_10000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb2895058ceacf03e52bb407fe49acfa3b16b0ac37b95cd2d7c2de61fe1fe5c0653f7403fbfabc9e15ba1280c66d5cfbe9271bceba052138a29b6b9af48605878bec30891ce20d6c30dc13b435e8b698b06f1f10e88cf6bfc3d374fe394c575c12e87b18bacad46d3397f9ac10b82ec8becf12be4d8c253c2690718699d1e9d9125887e6d2413f2f4fff0e8ce299a3435f7adbe089c5749adda2b589569bcaf8b8c0e589eeae06a9565a4dfbd92d03c3efe15129d6b4f0a9503fd37f84516d96d67e313189e1dbfa5c6c969b299fedb83ad31b7c075888ea9a0e5b8b97d631aeaa16efaf41bf9eb702562c8e57d7f2e2e180d59b1179249bdb33c845146c1a9649cb7058859d3bf96bbefa66227e87acb5ab\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbLWBsRb)6eQXj+CUGLmauNb7J=5#Ijbu(MfY$S*X$T)tFQsFESJ|`4Gvy~+(%0~u-L8W$KY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22490886344f6e1d4cddadfb8776875fcf3c3e0abe2e76343ec6e50141fd235f9c9ee19780966731ee39b0b511d16e8bb36edee7dce9b67b0b6a4a38a49a1eae5d1e0bb93557f581daff17ecc75f9f2f9c17eccf907e6a38a8d409ae85f82542a420c88259d8565b0f1d4b813bd65dd1f0022d0f0826b18d7b3cfe226c5c6d47de8ebe6ffc4f235c645adeb69f6a6eee70b7cfd659a480ae4913ea1b3102db337a702401a344c7ef95836dce6d4cc3bb02f291ac164dac8a208fd0584e4d2574908de61026f54a98f534f85c85664d0b28518e3a52e39c88b8cc5eb124e1ff85b3f332a633b03b0541fbf45e07b67e1c5b96b63fcc4820f888b86a188b44c481aad4a47b515547b7fcde919d2163c57757\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 5050, - "Plan Width": 1096, - "Relation Name": "integer_encrypted_10000", - "Startup Cost": 0.0, - "Total Cost": 6580.0 + "Plan Rows": 4850, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.79, + "Total Cost": 7321.57 } ], - "Startup Cost": 0.0, - "Total Cost": 13.03 + "Startup Cost": 0.79, + "Total Cost": 15.88 } } ] @@ -89,7 +91,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on integer_encrypted_100000 + Index Scan using integer_encrypted_v3_100000_ord_index on integer_encrypted_v3_100000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -102,24 +104,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 10, - "Plan Width": 1100, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_100000", + "Alias": "integer_encrypted_v3_100000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28cdffed476d8949ad004e8503eee2d1ede277e72680cb4f49336cfc2d27d4d3d87c0d2b188c5667d06c772cd8943097e6bc09e35e82cd7eac79ff5f3601f84c13822ff353bf058a28c334a9152c678ab9f603654b31bbf1a670be0f43714bc2fb662770684b98854b4eee3e4d97b02ea06fd7daf2239bea2e3cbcf9522a5c452bae4b25f21a91080615a53f71d1b59525dd08f87cb9bcd6cad1a6eaad71c123101d4d9483ece39053b5515249f666037d3edaf4197fb129095640f52b1b0e981fa00af3f0ba265e155bccb963fc0afe38b99146b9e7a63813c896bbdbb795e99038271c6047475734c28a135e2aa1b72c282fd257cc7f45412f70e476f63bad5adb65cb1461b84caec0f8bfc07d92acd0\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbM7>vz?)OlK0@C8sAWl#gx17Gc|N!NlqitFJr$Tj%C!2JHMAXiB%lAlQHv^j3n!Upn$Ih$!;%{yCqgfO1vQ%cXW~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_100000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a224d70c5ea374cca13c04aaed3707721fe675e47b0fd068818959436da37ff1646c9c8e3fb17c006b23834b591f29bc5459622027791bfcbb080e9693c4c132dbeef804e87f52b24950fffe745a206dd6712f10cee0427ad228e3a61039afc59b0e6d82848f5c189a1328f9b9e9b8e5410af593917ff9f371c7f6d354b9ea47a16df425b34404c29e3d23b6049bf25fe8bd67c1f095171907a69ed1f9608aa1e2e424020526692f76d77e05771a91e0d7ca1de6ea87b061169deb3d797d7f43bf8dea32d21ff12e4aabdb2956c225defe9c17379d7e69b042353c5239a8673e11890048c4a1ecfa0a54fac43b4e5791ad2db7b8d56b1b24d3ef80a8e47e59909aac4c6a147403ae29cbbad6ceae9065ad4\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_100000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 49500, - "Plan Width": 1100, - "Relation Name": "integer_encrypted_100000", - "Startup Cost": 0.0, - "Total Cost": 65344.0 + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.92, + "Total Cost": 73448.67 } ], - "Startup Cost": 0.0, - "Total Cost": 13.2 + "Startup Cost": 0.92, + "Total Cost": 15.76 } } ] @@ -129,7 +133,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on integer_encrypted_1000000 + Index Scan using integer_encrypted_v3_1000000_ord_index on integer_encrypted_v3_1000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -142,24 +146,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 10, - "Plan Width": 1100, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_1000000", + "Alias": "integer_encrypted_v3_1000000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb282f84fb8bea947267022c54168884f13b299cb13e75fd502a59e9eeeb2841560bc59c69a676482a044359edbc2138c8f381eb13e4b765294ab3eaafa4751639312ead32fde25cb182fbfdcabb32af14a7e3a45dc406285c52e6e3a0ac1ed955d59fb786dd85b6c92608eab5a6f556e3aa9f401ef39d3453e149b01af85327bb8aa02bd78f191f969f1474d04917ec8360c9aa15a7d62181d1f0d29c5b90c6272c8668287f38405b6832c2807a362201945ec2100cdc5d4fda682f40eb0b891c39a3c2accf1d8fd685da9a5853e1c168e6f9c921acbc19ce840aa8f093228183d84c20f72c67758110a35bb1c9d048e04a8c9b476452b8784a4db734f50f0c72d735fd69e8f16f262ce66fe0815c8cdcbb\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbLmQ9%&7tznj=CG@e~bhK5(7L>6%{yVA%!jbf*8KAiiF~piFmi0BnAXzKt+KSI#^4ieD+h6Cz5E<*V_e%AWn%0hE17B_Wtfh8gY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_1000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a225cd2430565ba1a784083ff052802607d00cb7d7e94883d348720cb39e670c30fe11a955210cf6309c20887f0d02efac0806cbde21d80f3965bdb17c9cd42382e52d9d97d1017784e7b3f1e1dcfe15c224966ce98b12913cf9b4a0dc643ad00862d3868cd9e6e73b189b7be4ed120b51fa95d425a6c4222656b73726cc9a6e634315437b04a978949e948690d6efb3328493f6819bebffbc178bdc345a84481c2faa7ef50ce83c15c69a91aa4c7beef189211dd12c6ad83842b928a403171bef4aac1da9bfa84583a955108b85076ee2a8f2415813fec8d712531a24648e3450942f015bc12b79154b51dabd1502ff4dc999662015a348a93db7b46deddc37fd5649b5869208c225ffd72b8a5bb448521\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_1000000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 505003, - "Plan Width": 1100, - "Relation Name": "integer_encrypted_1000000", - "Startup Cost": 0.0, - "Total Cost": 652923.06 + "Plan Rows": 495003, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 1.05, + "Total Cost": 734361.89 } ], - "Startup Cost": 0.0, - "Total Cost": 12.93 + "Startup Cost": 1.05, + "Total Cost": 15.89 } } ] @@ -169,7 +175,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on integer_encrypted_10000000 + Index Scan using integer_encrypted_v3_10000000_ord_index on integer_encrypted_v3_10000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -182,24 +188,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 10, - "Plan Width": 1100, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_10000000", + "Alias": "integer_encrypted_v3_10000000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28ab3526a1f71312dd4b4012a56a854f8b6d50e0865458819e6ddb7e5a26c521c2351887d2b69273ee56010754f2e8e30383a63df6b667c659cd59c6e8fc5925653beafc5f1898c4d0f149f230b11ae10083b8316ff49fb1be201bab7464f3695804ce459307906047dd100a885fc13b467ebae0fbecffc31db1f56cf8e177b9ddc24bac3871f14f8475c446c4d0ea2b13d6e687dacf1d6f2647ed35d2e0f009f8ed3d843452ca2df663d840bd0d2dd90a11fadd0b32300a245b4ad2daa679186eea23a0a5fe20f789827344692613214cdc5d901715d26293a64a2ef96d0010dd7136981dc63ff16764bd1c6f5b223970f1ba23dc3855b0e2eea32d484436e2dba077bc5da5537f4fb5d03c23d011184f\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbLPsC~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a226aa4c7f033219508c87aafbb5d35ac5e55474798d0c0a4ad729691cdadbbfafb2d9ccbe3fab97a5c0ab07fc6c807de0cae7900f000cfb3cc09fb33996117d5b10eda8defd7533f233431030c6afe1b311e3685e493b26dae96452712d2da99d5e0c40f46e3813c84d883dd679ee03bb06322bf406c4625103e6e81c5c5ce351e4fcf8549ec05b2ec041708d73d3509ce5b537618b251502c8919138010dce9928fa9cb5e69185c52e4734a30b1dc2a44f73579b4c06f26a803f8e00e10d820aad10669b675796c4979906b8fa070780fba8fe01ef68b861512e52a8ce287691aefdf26c343cb59beccbde14b3db602a9cccfb1cf2d0a0f39a9f568882c6bfd9a93de2fdf945cc53e969581b00dd11d81\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 5050158, - "Plan Width": 1100, - "Relation Name": "integer_encrypted_10000000", - "Startup Cost": 0.0, - "Total Cost": 6528775.12 + "Plan Rows": 5050002, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 1.19, + "Total Cost": 7376457.78 } ], - "Startup Cost": 0.0, - "Total Cost": 12.93 + "Startup Cost": 1.19, + "Total Cost": 15.79 } } ] @@ -233,17 +241,17 @@ ON integer_encrypted_10000 ( **Indexes used by the planner (per data set size):** -- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ -- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ -- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ -- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000: `integer_encrypted_v3_10000_ord_index` +- 100,000: `integer_encrypted_v3_100000_ord_index` +- 1,000,000: `integer_encrypted_v3_1000000_ord_index` +- 10,000,000: `integer_encrypted_v3_10000000_ord_index` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 100 | 4.08ms | 46.72ms | -| 100,000 | 100 | 4.19ms | 42.46ms | -| 1,000,000 | 100 | 4.11ms | 46.26ms | -| 10,000,000 | 100 | 4.06ms | 45.98ms | +| 10,000 | 100 | 974.64μs | 42.60ms | +| 100,000 | 100 | 977.05μs | 34.16ms | +| 1,000,000 | 100 | 976.53μs | 35.87ms | +| 10,000,000 | 100 | 1.00ms | 37.31ms | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -254,7 +262,7 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Seq Scan on integer_encrypted_10000 + Index Scan using integer_encrypted_v3_10000_ord_index on integer_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -267,24 +275,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 100, - "Plan Width": 1096, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_10000", + "Alias": "integer_encrypted_v3_10000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28516c2cd5946c69af275e35b4d463d045361a1cf588bd7ce00b458793690af709d02b69d2e6752be608e71d0d74b4c86de79bffbb1a2eedb0d48d31c5e25f35c3d7b0b6d0ebb351be2de001a2e98897471c2de5ccef4c643f000cc2aa4a42b34d9ac46e80fb5e73cdd60cd305f2f65e3a825c3520a9f6700f3b3f332eb1162f56e805f3e43fcc54b611217b120bbf618dc909865ff5ae4724123e3f73465b786fcd127477cf4e0559e500c4fa8e0ff35081ba73c3d5a34a5da3137c37450ddc9fec6050a46b1a3876200fd83a21b7b84f683d2ae6cb0a1e648a227a800e26e7f7071d0a9851bc3c5eca490ef0a51102eaa215147b4f10bef5a9a88475c3fa128476ac2d4061d2f29e48ba5bdcfc772539\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbKU56O`Yy;m%(Dx9`_dev3L7Ufb$9A@2;5Kibtu6{_?$YJib)~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22f7940434ba5d8bd58e8012390a42164589e167363538df78ab9fe9fb7a378cab07a6534c6dff35c861f28333799c5ad21d84f5b40a6958bd229511ba57f0eece264ff386bfb6b05b1a834119b7a9086cd8f746b3376124ec58b137caea8bf427c238a49dde1ad7c983f5adf1acd84a8354c3480c9fcb5e7dd2a90e9ebc730faf80a83d279cdf6e7d064ba83bab30f7e9199e46b87dd235dd029450a878a33247724fc340886d9510d285e5bab097735b2cf2c6f92566da2c75d919af14c6eab5f7e7f62bc2e9324af2fa2203a082e15526501a5c945e07bf8859c93597e63d49119d63a14303505d65b9917b92aa03d54bbebf74bd1d1e2891d20675e292fec863bf1d14093ff9c5052a0a1afbcb8d93\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 5050, - "Plan Width": 1096, - "Relation Name": "integer_encrypted_10000", - "Startup Cost": 0.0, - "Total Cost": 6580.0 + "Plan Rows": 4850, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.79, + "Total Cost": 7321.57 } ], - "Startup Cost": 0.0, - "Total Cost": 130.3 + "Startup Cost": 0.79, + "Total Cost": 151.73 } } ] @@ -294,7 +304,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on integer_encrypted_100000 + Index Scan using integer_encrypted_v3_100000_ord_index on integer_encrypted_v3_100000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -307,24 +317,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 100, - "Plan Width": 1100, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_100000", + "Alias": "integer_encrypted_v3_100000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28fa32673493f0be9a0aeb3ba6c3df4f09b3aeab46f298065b776269777c3cf9a42c654c6745db2642d462699cb93ca8b476e2f4662fb7cf9056f5c67c34eb6fd472e5f3a395a4625a56c286821eebcfa6324006b3abdf6f21cd1dcb4708ceb9680f2363fd312604c638f72e3db772996c73df4b980caddfba6941d3a5944928755ff7cae1ba838a7ebd4fabe18f44a243d6f45bb097f77be87c981b3dd3a517ad71f9bbb0ebdf929e8161b5d0c4f7567e6d60ddf06e5516047d814f873fa339e4b4e3b641085e826fbd534cb79e0aadc6b3b96d25533fb166e88205cb32171bad7648bb4e5eb7dcc55b6b73beffa33d5caefe093e86744da6b82947761a9ac38f51439bcdb1f936439295d266b560fe08\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbK#i|jR0mIE6R#Vn9^v*k_176|=1zfZjEt{rEpMy*}GbhPXwt~FW2Ah@YpZ(4)~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_100000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a229befb2abf146a7b30e21e3e247c39b3a20af8bfc5fb5ff1f5bc9638fe19d3b793e9a2c623eb3e4647a72cc8cf24f5290e8c8f4c4b28518aebb48b56b74d35db66a4f09d7aa7bb1ff88da81ae5e48d56292d219fa4f52e21c151a073c66debaaeea91f181e1faddb6568ef19cd4baf5e47d34bbaaf1603d137d60f36d1529f69946d7d3fcbdaec09f018958356e59ee39cd6c23476429a5e1c81cab96b4033d50bf4559505de93c207bee3fa62e5e8c8832346b5787ad5a8cca98cfe989f5d5c80611bfb87fcf92f79e1528b77bb9b4b5b4311afd90773349d70677517c7c316470d28a475ce4dd2043af0f2e786b8ad5652194ea0c829248f3b38db8178319e900b6973b5bd4c351c119d9226e684232\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_100000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 49500, - "Plan Width": 1100, - "Relation Name": "integer_encrypted_100000", - "Startup Cost": 0.0, - "Total Cost": 65344.0 + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.92, + "Total Cost": 73448.67 } ], - "Startup Cost": 0.0, - "Total Cost": 132.01 + "Startup Cost": 0.92, + "Total Cost": 149.3 } } ] @@ -334,7 +346,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on integer_encrypted_1000000 + Index Scan using integer_encrypted_v3_1000000_ord_index on integer_encrypted_v3_1000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -347,24 +359,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 100, - "Plan Width": 1100, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_1000000", + "Alias": "integer_encrypted_v3_1000000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28e35161ead6beffd7663345c5318f66d1601b178b8b64bd03b9cb417932b68f4923776a54650ab7182e808668cfaa90543e34e7e4cf6d8dfdb524d45e3bf38f06e99980370109eff79345e4b9389ddb30026d6686c9ec5e1d36452c4b8b48dd5f6c4fe91054ef5518e2ceeac0d04695f32b16b4b5e093386bcacf6e0735402f482eb60618f0fc29f602147257485621aa8ac80a875e6597f48fb66a1895a989ca665ea38d46fccd031aa9230d997a4e6cea51831b3fddbeee566978d81f29c3732d68408cefb521676823a67cf770b733033941594d74afafc37ad96fa7be7d862ff77227be89b16f1f651eadbb2c3c3a5a034a098b9f595c07209177e3c4acae06718f5cbd99d07c4103a7b463d3f6b9\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbK2YcyBewbxQPWU}V@%St1}7Qzqlz}9)a$Ml_>v4_uxcrOf@r);gnAfoJNLqP7KH!)wfuPw1DdMBws&RD7UEU(=;M&(kcfTea}Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_1000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22e1cd5d41661cb22e5b2385b8b97e1a9f317d623b4bab1f6d4528b82da90b25ff919d14d7bec2bdaef50adc8c7e4951676f362392a11633a0986dfac9755d53509737858ad643fcd0b2fbb1b2be383fa693e33394ff427ac2592f63ee7cffecb58a916253bf9f55bd00a5fdeb73e037949477ef2458af2aff0106164139462075279af880b889e3045b66560012de8e1457d4a47d110dccf889f37f966b10a67907bc369a9f37195d17d9c9f4ba5b6170835fa1c15827b00a21ee00772448b0068244346a4acd273443577ec2404e1dd257799ad9fda26714c006f0968b24ef25a2b16b04b6f10e2ffb3fd87e52c57d7e131c76aba1efbd0dd997dcfda1fdaa7321e4cc1d15259472f6595680c965f56e\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_1000000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 505003, - "Plan Width": 1100, - "Relation Name": "integer_encrypted_1000000", - "Startup Cost": 0.0, - "Total Cost": 652923.06 + "Plan Rows": 495003, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 1.05, + "Total Cost": 734361.89 } ], - "Startup Cost": 0.0, - "Total Cost": 129.29 + "Startup Cost": 1.05, + "Total Cost": 149.41 } } ] @@ -374,7 +388,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on integer_encrypted_10000000 + Index Scan using integer_encrypted_v3_10000000_ord_index on integer_encrypted_v3_10000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -387,24 +401,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 100, - "Plan Width": 1100, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_10000000", + "Alias": "integer_encrypted_v3_10000000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb289ce2631903d6108b8bf2bdf62a911654684dc048f7060858c44bc617b98d87fda06546b08c80283edeb5488db636347b2b0cf949c93dc9e038f247774433cafbcd63bf91d129b31c52a56e4db0361d4f527df7c29e15380b9063b1e04a1e43b74fc095b98b17bb6551448320c938c455cd0ced12447e4c0fc8c05d9bb62593442d628e0386ee98a9abaac940b361b10249c58bbba2726fc2475a423aa5a5e3efe320e3374ba6d247d1864bffd741ae8b3e50734c2e31558d31396840e8d90455d0b2798c225048af2de3201c962b2e8df2edd69d2e172220aedcb05bedfcbe6e3beaa69920c9900f5bec3a2fddf9d589d4e6c6558df08bd9b8f3aecca4566c9b7da26f2dda2bd1eddb0a372119661a3e\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbL}UZVLggZ2PgHzVLUw9uQx7S$IQ{eMo*Jdj@d$_PAfiVqCvKeA}VAONW+@M$?#cOZn_9w9#KG~mY~%Ah`77lQj&l{H{8_oa4WY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2287e1ec8ee908056d639839e3ad5f07a78213def4d88544e05668bf927ebca7d36432b9044e4d898a0917da9f4bb6bfa716e059f123b7aac2d6214959e435ee36249a1a0a7a496d092a98d59f6a7dd30044ccddfb9c749c1bf888d0a311e193968b604e15a56bf3fd33c508bd0b28d5c8016bcc1d495036a87b5f2329fd57d2447a095a3b3c7a9a485386451add7815f96ff733be3f565e9aa0a41fd29f56ca2cb6f2e7d29b25d4775006e5c5da5f07a7ee28bccceeb145ea7e5b6022eada5ef31d1cdfb9d7b49a8da68b8ecc9b2d85b31e895b0e7e8c60df2f8947f11c9ede1fb2d091fda1c1c009292f0faf0592b7651514a67ab9bff6003651c5a885757d2c5c40b582eed3792645563a0bb2c1acf0\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 5050158, - "Plan Width": 1100, - "Relation Name": "integer_encrypted_10000000", - "Startup Cost": 0.0, - "Total Cost": 6528775.12 + "Plan Rows": 5050002, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 1.19, + "Total Cost": 7376457.78 } ], - "Startup Cost": 0.0, - "Total Cost": 129.28 + "Startup Cost": 1.19, + "Total Cost": 147.26 } } ] @@ -438,17 +454,17 @@ ON integer_encrypted_10000 ( **Indexes used by the planner (per data set size):** -- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ -- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ -- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ -- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000: `integer_encrypted_v3_10000_ord_index` +- 100,000: `integer_encrypted_v3_100000_ord_index` +- 1,000,000: `integer_encrypted_v3_1000000_ord_index` +- 10,000,000: `integer_encrypted_v3_10000000_ord_index` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 10 | 593.75μs | 28.77ms | -| 100,000 | 10 | 654.88μs | 29.26ms | -| 1,000,000 | 10 | 587.45μs | 26.92ms | -| 10,000,000 | 10 | 765.42μs | 28.62ms | +| 10,000 | 10 | 459.12μs | 25.99ms | +| 100,000 | 10 | 517.92μs | 25.91ms | +| 1,000,000 | 10 | 512.07μs | 26.72ms | +| 10,000,000 | 10 | 480.69μs | 26.00ms | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -459,7 +475,7 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Seq Scan on integer_encrypted_10000 + Index Scan using integer_encrypted_v3_10000_ord_index on integer_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -472,24 +488,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 10, - "Plan Width": 1096, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_10000", + "Alias": "integer_encrypted_v3_10000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28281514a62219c9e223b1b98519673056b9a5be40434e07d5bb2f217fc5e9d32fbee4b30897d67c09230375ac6ca91c9de55ce861c231520461bad34d8c6b4dc3f153de14b91b711829818e7037c964b2359ea8a038c5822c23bf0d35a0e68635c59c82dc31771fb6dc55614f583c2730b47cc153459a890943b9c4ce5d74e636b1293882943db6023ccdc3460d1a1647dce4a0861af21d65f33cec0528496cd813c2de31ba42d27e125ed3732c01a628229a7a3f7bc91e2f62bb333e92f4f3249478a190c117a45a03c00a1a4ea3b1b9942cd7566ee3052a2abd75b903bdab00476e90b9643e4758d203cd0e86edcf0f9ddab24394d50304f84b884d435ba096b6ed4d201d0a4315a4790152bcfd8743\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbLl{C%Ofl0~-A-(IfQl0o0Z7TILl#*xnD^%i>Yz!Km6L-a=g&)uxVAhnj6unq99%|*}#SxN~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a228a2443aca787f0fb57be71172c456978a43b8a5b775baf4830ae4e374c2351d8e3ded9ac485f5dbe9599ddc2bed03a2e44ba12bc2e5e2c82790bdb96b3e13b4141a0f3dc497958fb679b5d8063b72f903e577640446e5fd25c572ab64a5a0ef6697cad7017fd06421facb751a5572c4c0357519d4a629c7311eecf341e6de0ee55b84c6bfd20dbe3778d4e22412dac66532ff6de23b2451a0f49da3b97513fcab360994e62883f02f860799e6954f70dae27ace2887d7f42f698a481bc62de663332c06d7a6a3abb6a11d71ad827dda203b92695883a2043c2e0a0996bb71429c42a70c80d25904af5441ebb808adecd349bb24aacf15eee3861486f41aaae6558aad6baaa206a9f0af6a6c09e95ac1a\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 4949, - "Plan Width": 1096, - "Relation Name": "integer_encrypted_10000", - "Startup Cost": 0.0, - "Total Cost": 6580.0 + "Plan Rows": 5149, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.79, + "Total Cost": 7418.8 } ], - "Startup Cost": 0.0, - "Total Cost": 13.3 + "Startup Cost": 0.79, + "Total Cost": 15.19 } } ] @@ -499,7 +517,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on integer_encrypted_100000 + Index Scan using integer_encrypted_v3_100000_ord_index on integer_encrypted_v3_100000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -512,24 +530,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 10, - "Plan Width": 1100, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_100000", + "Alias": "integer_encrypted_v3_100000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb2818082cdcde08b3ec83a009cc965e2b3feb49c2fd9f35398709b0928121eb28e004ce488d915e1e277d5aaad38670a26d9f03fc6e160ad1aff6b665825d60af3b6b258ff799d72e7a9cc740da7654c2184e3044c78a660f91a093ceb87645f29e93f1b298d14d5a717d4b4aedeed621f2b4b40486787924e2eca5cc8711857806d9b570fcd8cca93af62e401c9af35f2458f83b251587508641cbe02fb3bf90c27a3e4c68ec890dcc2a8eddcfc2bf7999619122104e09064b3c12042914e24ad8fcb74fffc9268c06cc6d7093a545e14ea482fb8d85ac048edb6b882ad41d25c8c6f3e48b6f33df6dd86d3909846307fb8497181666303bfb821890299fdfbba60d9cf8ca0ed7104d78140514cdec9b21\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbKFTD{B2qpFwEUS!1SXX~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_100000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22c88c465fd65d2916b9ff115fe0cecc3ebefe1e965e1679461b1999d48c334982310fc4af06ed982586b1175159c160ef63859e5ea14e4dda15a488e29f78594c84ae95a1f82140f4e5c90d60a5a6c57be60faeaa4282bef523e469219b5fcf8df1b97d56128592c48d66a6b617645e999e0fbed42a1da276fac8cb4b04f158b1afed5aa27940fb92f2ffc0085a45bcd60ed05cb1f35f1c07102b19fb57ae85f789a1a6562e261ba3df1571a4e76a5ddaee311599814c9e014f30800049b05dbe42438bf7ccaa41f77266e6bea8bd9e9cb6ed92c66c799bc80d78b4ba9952fffb4e00f0ef3fe3ea51a39022bc4043d948985f0b2d5aa317dd2176575f4adb2fc089b455892fcdafe625c4aa35b7480432\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_100000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 50499, - "Plan Width": 1100, - "Relation Name": "integer_encrypted_100000", - "Startup Cost": 0.0, - "Total Cost": 65344.0 + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.92, + "Total Cost": 73774.16 } ], - "Startup Cost": 0.0, - "Total Cost": 12.94 + "Startup Cost": 0.92, + "Total Cost": 15.53 } } ] @@ -539,7 +559,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on integer_encrypted_1000000 + Index Scan using integer_encrypted_v3_1000000_ord_index on integer_encrypted_v3_1000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -552,24 +572,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 10, - "Plan Width": 1100, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_1000000", + "Alias": "integer_encrypted_v3_1000000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb282e91d2b8748554723eec099dc035833f94094f04a27dd8ed5f63bd409a8139d10d2b11e57772a0e591746c4668e8dc002068a91bf70ebdb4209b1692fe59c767f676f24a9fda124826331b1a715518b9f84fa85009b12429e59c9781aaf6bb4362435caaba5dce276cab29415bada9b340e36e96a2377ded7519e8eb30527761902980d7b087bc6336365e238c478989279982e9b7d808305f489af26cf8f8512d2b736935502391c6d2551e50e5c699dd1378be1b8d2ee6b0603658cf9b7ed58b7fc21bec0493cf001ed97b549b9b76dd4157d365f26bbfb019a99d4df555e3f4fc96bc79f254b55353df22614ea788caf528980fda2831cd483fd31f30b291d40f3d8b8dca1b4716a6eaae0c6ff57e\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbKXO((pb&-TKHzogfx6Th{@7JJGi@x~wAt5vp+M86W|kW9++Y$a;MAPDcUn`+#~$*tzvqFn?nAbMI@dhBP6=BAH}DSv3-zom9zY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_1000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22ead7035b93898b22b6be67d1fb64aca6f2caede02374ac8c6a1cbc6eb472121a86e1d001c89ec9c70d69c0542eb9761829d9e500050d2e8f3820878165c30c7326f717c2e803e21f01f27b42951963ee0998348cb3639ccd316c0bf71f2b30eb0a8473661604cfe0eb298de6b5d926ed306715bd34e5d97478616eac80e414ef32b7b5382a5aca4bfb9ca8dfea00e29af9ab50296c6e474ea61730c54ea0ff77274cc042dff2bbf92219228663fa9e29d8dd4d606883f92c3b0afaa071e381e9e811a6b4100744f7b818de57da629d1acac2a5c28eb1a93d6d64f22264e964eaa521bc724f5ad3a4ce651e54c334bc265be6dab56524fd1b438ef1697a76e85cb7cdce7134d5af04970e9ec0a0496eb9\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_1000000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 495002, - "Plan Width": 1100, - "Relation Name": "integer_encrypted_1000000", - "Startup Cost": 0.0, - "Total Cost": 652923.06 + "Plan Rows": 505002, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 1.05, + "Total Cost": 737652.95 } ], - "Startup Cost": 0.0, - "Total Cost": 13.19 + "Startup Cost": 1.05, + "Total Cost": 15.66 } } ] @@ -579,7 +601,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on integer_encrypted_10000000 + Index Scan using integer_encrypted_v3_10000000_ord_index on integer_encrypted_v3_10000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -592,24 +614,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 10, - "Plan Width": 1100, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_10000000", + "Alias": "integer_encrypted_v3_10000000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28f593f1586d1251937b77bd76c4a36fc688c54b1b1760abb18eda2851fccc74552ed80c0a772f803e41a02ec7ab03c4857e53354c7c07aa846e6aa04319816826eba5a69558565a14711bd9dbe930e3ed263b3c6b370ac260c1e12699539c78cdace31999339368554c76fd77a3a1b5a1497ef2fd3d92c730057add2cb55ee475e8fd91eaadb75ed02e7cccbe261730822a2c1afa46b057c79b2201186499e7f11e88644c7bd3616379938706ce2b9d82e8be8a761ce70ec2cfe28e31a4fb50d439755da13c318c2841ac2af4743137f8398a5d9d244be89b6a38777ea4dd01a7048e5733945a991d249e95f2b7d616e763f54923b3e40770d5b7fe6eea162e19c51366bdbcc0bf674f63af3f882e473a\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbLd@jaGvOfiXZh6S2Kt>Ht&7Gn>yay5es2-X+@8~q*d&W)-0_A$c5AQxYuS-dW93T%B+$3kDPh{Y|K-DWhu3obrMC^4{BwxxDqY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22c64e22de1875dbc1aa91b3918bdf16eda0eb462640a7a718dbcac6d51970b717b9f3a882d5b7ea24d6ae323f6766b239a6c08dcd7c31fab33f4e2e8fed569b0813d0d4915f0bfd0542c1fd57357c06b338df05d167b3fe2afcbd4adc50edf32bb0abb3dfa46664e22bfc90a150e9de133510098754506b2ebcc3787a999aa89773a1bcafa354cc0f90472a14c0a6af39d946162aec5622b10f246f0a24dc3fde6bbdc5fe5110e19fe6f0856135077c8293a38b8df9a6d6dc1a6b5049f22381d8edfff5db644320384bfa8fe3752a2ccaa82c4d32e0a69ffbb6a5fbaa43d875c8754fb7b0421accd1d3a7325bce897ac88f16f92b8c84aa859392632231b1221088005830210e3b03c97150d36eed201a\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 4950153, - "Plan Width": 1100, - "Relation Name": "integer_encrypted_10000000", - "Startup Cost": 0.0, - "Total Cost": 6528775.12 + "Plan Rows": 4950001, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 1.19, + "Total Cost": 7343539.07 } ], - "Startup Cost": 0.0, - "Total Cost": 13.19 + "Startup Cost": 1.19, + "Total Cost": 16.02 } } ] @@ -643,17 +667,17 @@ ON integer_encrypted_10000 ( **Indexes used by the planner (per data set size):** -- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ -- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ -- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ -- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000: `integer_encrypted_v3_10000_ord_index` +- 100,000: `integer_encrypted_v3_100000_ord_index` +- 1,000,000: `integer_encrypted_v3_1000000_ord_index` +- 10,000,000: `integer_encrypted_v3_10000000_ord_index` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 100 | 3.95ms | 45.93ms | -| 100,000 | 100 | 3.91ms | 47.31ms | -| 1,000,000 | 100 | 4.07ms | 44.32ms | -| 10,000,000 | 100 | 4.12ms | 46.31ms | +| 10,000 | 100 | 907.54μs | 43.01ms | +| 100,000 | 100 | 941.48μs | 33.38ms | +| 1,000,000 | 100 | 867.27μs | 41.76ms | +| 10,000,000 | 100 | 896.39μs | 36.92ms | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -664,7 +688,7 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Seq Scan on integer_encrypted_10000 + Index Scan using integer_encrypted_v3_10000_ord_index on integer_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -677,24 +701,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 100, - "Plan Width": 1096, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_10000", + "Alias": "integer_encrypted_v3_10000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb2842b46e630529ee0ad9f9da1dc9679eb9b63125d7c154536158c4bf3612c27decbdc3b89e5e239608510c120ec9fa347dd6e6e9e880ee6e45170a62e35c5f658d698b507dea059565113422ceb693ea2a38a1db6da4e6e1ba71cf3a804e364395be09331d90d897c75286796865ba0088c31dc4ad592ae1c7b577cc0bcb4b1f63cfa7d1946c25be95132827f5763c5237df5077e36fcc28d52dd7047b22f7554736e18d62a83d4a963ff23be234576d0fef6e5952c461d37f234597df886ff57f2db07497a038574bdb9949c48ea54d02c68c438ac86231763b1e7f92dfe39608aa2937b56d8bd076beddff41ee82f7c65fdc1aaa47c91e7c75a09795a50bf0bcaa5e8875702cfba1be4646f82affe75d\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbK)I?FpYxps3J?f(PG%{>If7PpY{-*4+!p?MHJKsJhNkZ_gMl`{s!AdG}a-(vN7Mf~u}Cm$k-M=GK89Q;$7KeK&;jKXY552bctY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2200151d9d8f251f9a8450cb7f8965238f6bb402c5a8912c063f8daefbccccc742bb890860e7df922f3d97fd797c481026337b5ff190ca8ed5db4ff2dc8b0831adab25ed5f366ed6985ba40b14db3d9efcbd2025949decabebe172a6bc0e3de33ea373c0f01020ebea7b4789385cdcbe2eb8a1bfb8c4a60540ee584c91ba5dd15f237d62304abcb81620a7ae713c1bb881c548b82615244149082f42ab897df38741fc8ed64b86b7c4d1c9706b9bc64efe80581f7f4200f4a5f3d776bb0ef661806b8737f0d2719b663109d228fcbf5b4c682319b3f1bf0d3eddea3f3855c2397a7373e2fb46c93129eb8a9fd62370526d142110b7761da40bf3b9a6968d2a77d4b9fc908854497b2418db64b4675da1d9\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 4949, - "Plan Width": 1096, - "Relation Name": "integer_encrypted_10000", - "Startup Cost": 0.0, - "Total Cost": 6580.0 + "Plan Rows": 5149, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.79, + "Total Cost": 7418.8 } ], - "Startup Cost": 0.0, - "Total Cost": 132.96 + "Startup Cost": 0.79, + "Total Cost": 144.85 } } ] @@ -704,7 +730,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on integer_encrypted_100000 + Index Scan using integer_encrypted_v3_100000_ord_index on integer_encrypted_v3_100000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -717,24 +743,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 100, - "Plan Width": 1100, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_100000", + "Alias": "integer_encrypted_v3_100000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb2890665bb1d27a5a79962d6606881dd9ab6a557fcda289c68cf30f1028fc14e63b6f55a97b9c37995eac10b7122224fb62889debe5c644da1d1e45f75d084b47096442f2b1aac1d0a180d4312b6d817c27d94edcbe1d2903cf91993971e19111ac7c7f7080a68df266b2697699d2e68168492356a64bcbed646de191f4172bc37bd2eb4091a723621e30afd761a205d42bfe3e025ac3240fa6a4480156ececf1f07d67ba3794609a149cf502ada96dc86100fa4c3534837ce8017741778834cb1803236971bb7bcf083e88e7b0f369d6ccc32ea5f15f499b354ea7ada520807d6d687867350ccafe99955b647ebc72b4efb0157e9359419d56532864699db3ab733ae60a3f5ee31ecd52ce5c11b8671942\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbKLXPjZ0wxB0~Y%m_Z{ihzp7M{lm2_~<2I!E2$C5n@KhCpvy95oljAbyP01^Sf*)8~r^ajk%0>WLZ1cp1!I2WS_jyjns>rKNUZY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_100000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22b63b960c2bc150eb18cf73aee22c17bbdbecc429c0a90997726b60a0d6127b83fab39e26bd8c9c6049babfe679ad1a5cffd0fa1f413526365cf252549dc1b9bed29d5ba969c24e2abd76cb8e9be4e98c718ed94a5417f4227dccc946e0f1d95f09719de46ef9383c6ed870cb1c9b2a70a8fbae841071aaa856f6b78fb230e8551aee998702d5baa038147a2621b440d5c1aea4df11474e33ed9e0420d6f885d8a5ee381a5fef942a4f930245b0f8845c26dfc4b71023cc357c197a7ce7f37f6b4283e400195a830d73568da2311fcb4eff4b788ae5343c0fde034249a15feec02a5c1b99256a2a77e00e9878275c15a20ef2e091c2a7611d92d267a5f785e1a9f6de9a9a362bb09d660ee996eeeec625\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_100000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 50499, - "Plan Width": 1100, - "Relation Name": "integer_encrypted_100000", - "Startup Cost": 0.0, - "Total Cost": 65344.0 + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.92, + "Total Cost": 73774.16 } ], - "Startup Cost": 0.0, - "Total Cost": 129.4 + "Startup Cost": 0.92, + "Total Cost": 147.01 } } ] @@ -744,7 +772,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on integer_encrypted_1000000 + Index Scan using integer_encrypted_v3_1000000_ord_index on integer_encrypted_v3_1000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -757,24 +785,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 100, - "Plan Width": 1100, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_1000000", + "Alias": "integer_encrypted_v3_1000000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb280f0a220b44bf138b1eeeff29fdf93ea9b1c0992b21396f165eee66f3c630a2f747674e1ec9ac0d28832db9749c921c9fc7ca8d65c423df4a3baa3ff31e48c7f7845f720da4bfb0a30bbf533be3327d1a78135d0fc446ad691c2212fc9f99221c31d2e39bde6b6440b5805915db927fbfa77c599d926f7d2ea09bf8a91abe3143c4882cd81fc268401a57f4be401b94341bc5ec2c143cc54e465c44a1d59a6cba892262c96fd9b5a8f2d5d4b6cd606a8b6623096b570b0d3a8b4813e507f56123ce438d1a4931ad76fbcb17930c20ddc8784c234aea0de7986520080708b50cb91ee2bc3970bc071195854660b3d374b85dcc3e2f3085f0d5d77a8d2e3df905ca5e9bf6aff650c799ee2fa7f67a5883cc\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbK1?UWs05B(c}lWsY?n>Dh;7M3x~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_1000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22525d6862ef1d96f693d80c1778bfc5f12fb17cd78c0abd7a5c66eaf97961b0fbccb2facb9a8b20764743ab536d3768686465a00d736cb03e605cad68f45064a4f5e0bc50d1c2512874928f746b8fb819da186cea14fa0f4f69e0bc32430239ee50b5fb928f937ef6058b84185dd0cb10584ed2ccb2221b5b9a5e1b8910e81846a2a5795b17b3f4659c34a30e6ac187ccdeab77588ace709d3f66094aca19470f9e98132123075d2fdc27f0edfb99314366ee59b912374161e3186118d1182a775f7a4c112b447ee0d9e67181a0bff4937087bd829d7c34bdcc0d7ce4e89b2e9cef8ab9e6a81c17d6198c3babf199ab7846c2117234541b7d32d9beb5051c4e37b8e56b3959193843e450de4f8178deef\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_1000000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 495002, - "Plan Width": 1100, - "Relation Name": "integer_encrypted_1000000", - "Startup Cost": 0.0, - "Total Cost": 652923.06 + "Plan Rows": 505002, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 1.05, + "Total Cost": 737652.95 } ], - "Startup Cost": 0.0, - "Total Cost": 131.9 + "Startup Cost": 1.05, + "Total Cost": 147.12 } } ] @@ -784,7 +814,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Seq Scan on integer_encrypted_10000000 + Index Scan using integer_encrypted_v3_10000000_ord_index on integer_encrypted_v3_10000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -797,24 +827,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 100, - "Plan Width": 1100, + "Plan Width": 1064, "Plans": [ { - "Alias": "integer_encrypted_10000000", + "Alias": "integer_encrypted_v3_10000000", "Async Capable": false, - "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb288760bfdc5090d4008746ffbbc9564c0557b9a0e0f6b3e8e756c45d0b080540b9871bbab03a4d65bc35ccdb62515535cfdcc6e8eaed2cf489c23a23985916b1c73381a4dd970edaac9111b97e40cc5de333d40f0db178d987d6b1343e6c2464e5ca2f06ec4203ca875b7ec69be9d25822bd2d9d9c9964afabf74d9c6e2ade4d6a5dac18936c675fd79c54af9570f7efbb01d85100a6f2970c956d2d15de7c7a617e54347296aca56c0b58a1154d8a20c77f5da0f2a28b473e2d7d3437593d1d787ee78884647dc976123b8e1c728227dd1fafd530c5422a758660d30785a5b19f4f35be342c8ade262968e31eb07fb05fea210d5e3baa46c251be7e8c75e42c788ae4e3d0a784e7f0161b2016c16cdee0\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Node Type": "Seq Scan", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbJ*qyP~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a220cbbfdd194506cd9d450d97af4846b14a16c993321bd4655404405d5180bdae7aa718f21ff459f7d4c98195a46ddd0841fcb2ee8db127774f5960efb80d26458ce40d96ffb2c1caedb96521595a2c3e83867c8c665da06f57f28e1ee60d9e883b058838f0e810f185951a325480644e7f384c2b2e08f59b0b57ca41e2e333554b92b76579f75662e439f3d0468aba6f2967a888df221bef3f0b9f49e2c6a16ac48d9b1e6869492d006caf44bef6bd5c4ed69fa19057bdf1bfb8cd2fc027371159846a2e45696bea01fa234b4197c7d90c18da79ca2a4bdcbf8f6c69e0e72053a272a7c3e7ed853a6d455c1bc806484746f9b2a09f32fe2a5413d3ae9c747695fb1e547a435ed266fd1af081ba1e32015\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000000_ord_index", + "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 4950153, - "Plan Width": 1100, - "Relation Name": "integer_encrypted_10000000", - "Startup Cost": 0.0, - "Total Cost": 6528775.12 + "Plan Rows": 4950001, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 1.19, + "Total Cost": 7343539.07 } ], - "Startup Cost": 0.0, - "Total Cost": 131.89 + "Startup Cost": 1.19, + "Total Cost": 149.54 } } ] @@ -841,17 +873,17 @@ ON integer_encrypted_10000 ( **Indexes used by the planner (per data set size):** -- 10,000: `integer_encrypted_10000_ore_index` -- 100,000: `integer_encrypted_100000_ore_index` -- 1,000,000: `integer_encrypted_1000000_ore_index` -- 10,000,000: `integer_encrypted_10000000_ore_index` +- 10,000: `integer_encrypted_v3_10000_ord_index` +- 100,000: `integer_encrypted_v3_100000_ord_index` +- 1,000,000: `integer_encrypted_v3_1000000_ord_index` +- 10,000,000: `integer_encrypted_v3_10000000_ord_index` | Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | |---------------|---------------|-------------------------|---------------------------| -| 10,000 | 10 | 477.00μs | 28.85ms | -| 100,000 | 10 | 508.19μs | 28.80ms | -| 1,000,000 | 10 | 513.33μs | 27.10ms | -| 10,000,000 | 10 | 519.51μs | 26.54ms | +| 10,000 | 10 | 526.53μs | 26.50ms | +| 100,000 | 10 | 549.42μs | 25.54ms | +| 1,000,000 | 10 | 533.49μs | 27.02ms | +| 10,000,000 | 10 | 543.56μs | 26.34ms | _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ @@ -862,7 +894,7 @@ _Rows Returned is the actual count from a one-shot pre-bench execution. For LIMI ``` Limit - Index Scan using integer_encrypted_10000_ore_index on integer_encrypted_10000 + Index Scan using integer_encrypted_v3_10000_ord_index on integer_encrypted_v3_10000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -875,26 +907,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 10, - "Plan Width": 1128, + "Plan Width": 1096, "Plans": [ { - "Alias": "integer_encrypted_10000", + "Alias": "integer_encrypted_v3_10000", "Async Capable": false, - "Index Cond": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb280e44626ed9555695a2cb4526032945fc0d94a21cfafd74507cf7f504d833e4819e5d2559755ed1dd33bb71349ef14cdaa984cdf81c1f9b45f9760429854a86d97e7b52eae8ce7e76b219a1ceefa8f145e7851dea9d92bca84caed4fc577f0b3248e8ffd00c6619cdbe25fd2a49dd3a81b514a128eac4d6458804c8e0c22807f7fa4513ef1ad9e4e716dc2534ba73178d710434d7f5d907116b7fc5816dc094e3ee443a5f106fedcbe7ffe37144ef757ca1a0efacac1de17b6ac06e4117df56d4564636004948f8d680a8573dfef9203bd349d89894380eff94f63759eb0aa34f3c78e8638327bfc60a02da53257846f5028e714cac8febfeb0ca58d5eb1f5ef4a52a981c694138d1fe0ef1aecf582290\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Index Name": "integer_encrypted_10000_ore_index", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbK-he;~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2200d8f72210923597a171ad266453b215e6473ab07a8e310ed7feb75e4ac69926402cc1248fca4f0819cf05fec3ef69433b550dac8f5993adc66b4820e630ac999c50617e3638ddebb8532dea97bc1e1215fa185340c6c2c14c9b1854dfda8eef328fad65dfaeab686add3b9ebd07fbbf90aa32f8fb596878e07d801979d1c34a3563720fedcf17855aca308e8341b5e37e41b2c8cb4624c18a747c91b038a116e6c3a07a326d0353af401f2aa9564ac66c19f87925f16085126490a27c16bb0b34eda3ce201b34827d4157d92fed075f3665fafe085a3971171c1bd3d5e0dd9b5bf4cdb655cd4faae80c0dff33b019f6c613838d9453980e2458b0b3ea45db71bc74d4340896927fe4d1ef40639fc025\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000_ord_index", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 4949, - "Plan Width": 1128, - "Relation Name": "integer_encrypted_10000", + "Plan Rows": 5149, + "Plan Width": 1096, + "Relation Name": "integer_encrypted_v3_10000", "Scan Direction": "Forward", - "Startup Cost": 0.54, - "Total Cost": 8796.38 + "Startup Cost": 0.79, + "Total Cost": 8706.05 } ], - "Startup Cost": 0.54, - "Total Cost": 18.31 + "Startup Cost": 0.79, + "Total Cost": 17.69 } } ] @@ -904,7 +936,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using integer_encrypted_100000_ore_index on integer_encrypted_100000 + Index Scan using integer_encrypted_v3_100000_ord_index on integer_encrypted_v3_100000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -917,26 +949,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 10, - "Plan Width": 1132, + "Plan Width": 1096, "Plans": [ { - "Alias": "integer_encrypted_100000", + "Alias": "integer_encrypted_v3_100000", "Async Capable": false, - "Index Cond": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28a04e1538aef13d7dd0274a9106e45bb7e18744c1d268a8ae635ab442f5b76e9b9e10d695c7879972bf817d8a33a9fab2cf79b718dec6b47366f1105c61315524ccf91773e719f53f72a98fe07d2476e14c4752c0a2f105826c66db0a731df6a563ba7f884a4cd390f816b7262b80858ef95cf204af0b7fd73d221e3c665bd0e4fdc8dd741f97e9ff2781272426a781392d476744643d2388572fae7e50ca46b5d6d67b3e56d8ff13375add7d0696a818d5c802719e46c3ca40965aabdefb7e7e22d68cc57ca67e4e7707cc4ccbcd4e333d71bdfd77a6c02a7a18852cac31842590781ca501d08b6f524a18b0f70f60bfba0c3c895a617e603375c8dbc2d0a1611d2fccd785f508e78172c74d34bc204f\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Index Name": "integer_encrypted_100000_ore_index", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbKMtz)X5AXWDA>)Ze{a9;?-7IUKW56CpW=hm!Q4<`~#)?1fbp6Oo1AR~9V??kFoo|kb;*$Kj@VH?U~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_100000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2208a4f2ea6045fd0227fd35672c13ed2b06acf3b1ff8e3ca02b607723f1fa9d102847fa67cf5bde64f39e76043d1c9462c541dc21a4584200bb99d9a4e1a66ff6c39eafb837e502f74b34f8038b1480b183d1caf36e67e1711f8c62a177685ed2ebb12be39b0f1a8838894e145efce628f13702a7e17f3d476f01caa87c53471528d3e031f700f4a5b3904b0599731316863164a746541cd8cba08be6ed4b3b44f6fe7e99f9e46ed77d512b27962fa0d284057f71e5ce25eac4f6b32beda95cd9acb3e33190af25d5b0d495429926a0a6095843e39012889c729c6bf98eefd8a14689b1a8d1f845e85aafddd9ce317ecdd93c359bc3c0f993f39d8eb9d1a0a885f29db45f9f2b28dfb1b8688843a15eb1\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_100000_ord_index", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", "Plan Rows": 50499, - "Plan Width": 1132, - "Relation Name": "integer_encrypted_100000", + "Plan Width": 1096, + "Relation Name": "integer_encrypted_v3_100000", "Scan Direction": "Forward", - "Startup Cost": 0.67, - "Total Cost": 86629.25 + "Startup Cost": 0.92, + "Total Cost": 86398.91 } ], - "Startup Cost": 0.67, - "Total Cost": 17.82 + "Startup Cost": 0.92, + "Total Cost": 18.03 } } ] @@ -946,7 +978,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using integer_encrypted_1000000_ore_index on integer_encrypted_1000000 + Index Scan using integer_encrypted_v3_1000000_ord_index on integer_encrypted_v3_1000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -959,26 +991,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 10, - "Plan Width": 1132, + "Plan Width": 1096, "Plans": [ { - "Alias": "integer_encrypted_1000000", + "Alias": "integer_encrypted_v3_1000000", "Async Capable": false, - "Index Cond": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28c42a974dd413be8197f39a39743b9753fb03ac7a0090988ceed596fc5f2eba8b3a4abd0bfc406e9574de6dfa828633cba8a23a99e5e94c4b769193fd0650114e95a993e451581068267bbb24ce7a639c28974d095366345a81fbe99d57aa9bd954e3e3ffc3c7ee1f18d58cad41b6b32fbec55da6048406616f338a39631e2e84690816e56858ac0d7e517c256131aeb42295fec3a55af4071c5f2dfa0e7ceed54cd4a61153f53806d6e2abaf9f5d36a2c80237b1d7e5baf94dbbb9ba979a269609e5f053f738bbcbc89fbca1a83dc642ef6a578ae5a6d419780fc64837551b1659f91170b8922aa92f8f51d970d45172736424fa44542400d359bfa102f701ad05b10414e6eca20bda1f2964ca7f1322\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Index Name": "integer_encrypted_1000000_ore_index", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbKu&>F~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_1000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2201ac5855cc2df164043fb66b64b9870102bf83134a98c3d38125ec4a49c055afb2b22a0d5f21141f5394467d53147beef7e4a32d34dd3f0c4baaf2782374ab1b6351ff48477b49bdf4eeaaec2abf0eff153c247a5693e277e3af8293f89272bbcf3fb9d25229dcac6207143cb565cecac64726265b78a8834f22c248afad6174f0a1b050569a227baada68744b40e20a7fa976694eeabd8cb534f5fb746d70cff8d995847e85a8ad8bc09fb66c3d7be22722a306c933bfb927f0d1ca314f7e3b58fed5084f39039f7d298c857e60ca5cfc7048ab2adfed30181d53b21a148841e011fc24d33394150a237a2781435e07fdc38a2737f779c7999be5f88da07d4a9c62c9c14d3227d27832ea78b06d0593\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_1000000_ord_index", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 495002, - "Plan Width": 1132, - "Relation Name": "integer_encrypted_1000000", + "Plan Rows": 505002, + "Plan Width": 1096, + "Relation Name": "integer_encrypted_v3_1000000", "Scan Direction": "Forward", - "Startup Cost": 0.8, - "Total Cost": 858388.62 + "Startup Cost": 1.05, + "Total Cost": 863903.45 } ], - "Startup Cost": 0.8, - "Total Cost": 18.14 + "Startup Cost": 1.05, + "Total Cost": 18.16 } } ] @@ -988,7 +1020,7 @@ Full `EXPLAIN (FORMAT JSON)`: ``` Limit - Index Scan using integer_encrypted_10000000_ore_index on integer_encrypted_10000000 + Index Scan using integer_encrypted_v3_10000000_ord_index on integer_encrypted_v3_10000000 ``` Full `EXPLAIN (FORMAT JSON)`: @@ -1001,26 +1033,26 @@ Full `EXPLAIN (FORMAT JSON)`: "Node Type": "Limit", "Parallel Aware": false, "Plan Rows": 10, - "Plan Width": 1132, + "Plan Width": 1096, "Plans": [ { - "Alias": "integer_encrypted_10000000", + "Alias": "integer_encrypted_v3_10000000", "Async Capable": false, - "Index Cond": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb280c255538e575a2753d81ac25925e6e969bb0185a5dc30563df8af424efb304dac7cabc859d0694466c688bf93c2a2442b293763a5ad34a2d6536df4985eb7f0db964c73be7605c18917aec9b6cc58c756c6bfa3c147164f40778499953e816ffd650afae1d4687b519c846d8ce849f2c40d787edb645b20459ad945b1aa86183198c4ab4ebe63c0c0bc89979cf088e025ab91d061f1dce453c8358034893ad2fbe6422dfc34d1b590abe1d6ac9aa223505cc8dd058eb4a4d672e53363c7cfda6d15aa600642077855f590e0df12e0f2ef1cf5c49e56a88affc372b8cfcf5f6a8b866763620d68333ffb15668e72fca5df89a3410446dcfc39a0194d9584518d484a816f719b684bea68e4f6aa80eaed5\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", - "Index Name": "integer_encrypted_10000000_ore_index", + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbLM!LZm@RyJ%Bi*J#RGi4^k7Ktp1y)VEanN$@nNtg)i5pfhZqzBH#Ag_q$u=7zUnpYI*dvfopY{m%`0YD8Se;KqpG5ZizEv0s0Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2298db740f0e43f420833b65d7338d47bcf878829cd80b00ae4ea0ea7d9aa2f236494ad4fbf9f06a4efb59f1b7203520abd9e77e9fea9478eee17f8eafaab26a1f397c513575061606a79c178bd990f7e5c36af0b7da0565dae1f0bfafd9b06508da4b0b9dd0ed9430f2b0ee6d203e083033e6a44bad70b2bf0cdda811ffeaa6f6181b55fe8582fc0e7e7c19334163c65f8755d87d790beea9f7c57b38956e64a17bb2b23725ab712ce81a135c2922b14cabcca408a0dc57971e33cd4ba22c429db0b57df7bccf4434c3e177ed5c240fa371955889c54dafa8e08c834e2afa6df20948a2cf1925a8bfd0607a7bd03e6d981b3a5304f5faf9f76c1ca3dfd2114ce902db6407c7bfe847f405f15dc53487b8\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000000_ord_index", "Node Type": "Index Scan", "Parallel Aware": false, "Parent Relationship": "Outer", - "Plan Rows": 4950153, - "Plan Width": 1132, - "Relation Name": "integer_encrypted_10000000", + "Plan Rows": 4950001, + "Plan Width": 1096, + "Relation Name": "integer_encrypted_v3_10000000", "Scan Direction": "Forward", - "Startup Cost": 0.94, - "Total Cost": 8581229.33 + "Startup Cost": 1.19, + "Total Cost": 8581039.32 } ], - "Startup Cost": 0.94, - "Total Cost": 18.27 + "Startup Cost": 1.19, + "Total Cost": 18.52 } } ] diff --git a/report/plaintext.md b/report/plaintext.md new file mode 100644 index 0000000..79dc394 --- /dev/null +++ b/report/plaintext.md @@ -0,0 +1,982 @@ +# PLAINTEXT Queries + +[← Back to overview](./BENCHMARK_REPORT.md) + +Per-tier query performance. Each scenario lists its SQL, the indexes available on the target table, the indexes the planner actually picked per tier, the timing table, and the full EXPLAIN plan in a collapsed block. + +## exact_eq + +**Description:** Unknown query + +**** + +**Indexes used by the planner (per data set size):** + +- 10,000: `string_plaintext_10000_value_idx` +- 100,000: `string_plaintext_100000_value_idx` +- 1,000,000: `string_plaintext_1000000_value_idx` +- 10,000,000: `string_plaintext_10000000_value_idx` + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 1 | 93.70μs | N/A | +| 100,000 | 1 | 93.66μs | N/A | +| 1,000,000 | 1 | 94.84μs | N/A | +| 10,000,000 | 1 | 93.39μs | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Index Scan using string_plaintext_10000_value_idx on string_plaintext_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 37, + "Plans": [ + { + "Alias": "string_plaintext_10000", + "Async Capable": false, + "Index Cond": "(value = '267f4e4740f4d3598ed11f9332de54a0'::text)", + "Index Name": "string_plaintext_10000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 37, + "Relation Name": "string_plaintext_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.29, + "Total Cost": 8.3 + } + ], + "Startup Cost": 0.29, + "Total Cost": 8.3 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Index Scan using string_plaintext_100000_value_idx on string_plaintext_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 37, + "Plans": [ + { + "Alias": "string_plaintext_100000", + "Async Capable": false, + "Index Cond": "(value = 'd76d68cf03e259209831f84f5cfa3bfc'::text)", + "Index Name": "string_plaintext_100000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 37, + "Relation Name": "string_plaintext_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.42, + "Total Cost": 8.44 + } + ], + "Startup Cost": 0.42, + "Total Cost": 8.44 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Index Scan using string_plaintext_1000000_value_idx on string_plaintext_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 37, + "Plans": [ + { + "Alias": "string_plaintext_1000000", + "Async Capable": false, + "Index Cond": "(value = '77156d51418f4afaec005ee57a10ba1e'::text)", + "Index Name": "string_plaintext_1000000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 37, + "Relation Name": "string_plaintext_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.42, + "Total Cost": 8.44 + } + ], + "Startup Cost": 0.42, + "Total Cost": 8.44 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Index Scan using string_plaintext_10000000_value_idx on string_plaintext_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 37, + "Plans": [ + { + "Alias": "string_plaintext_10000000", + "Async Capable": false, + "Index Cond": "(value = '311751f432da063c08c83d20cb7cd05b'::text)", + "Index Name": "string_plaintext_10000000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 37, + "Relation Name": "string_plaintext_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.56, + "Total Cost": 8.58 + } + ], + "Startup Cost": 0.56, + "Total Cost": 8.58 + } + } +] +``` + +
+ +![Query Performance - PLAINTEXT/exact_eq](query_plaintext_exact_eq_chart.png) + +## json_contains + +**Description:** Unknown query + +**** + +**Indexes used by the planner (per data set size):** + +- 10,000: `json_small_plaintext_10000_gin_idx` +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 110.15μs | N/A | +| 100,000 | 10 | 230.86μs | N/A | +| 1,000,000 | 10 | 286.21μs | N/A | +| 10,000,000 | 10 | 152.78μs | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Bitmap Heap Scan on json_small_plaintext_10000 + Bitmap Index Scan using json_small_plaintext_10000_gin_idx +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 101, + "Plan Width": 4, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "(value @> '{\"age\": 97}'::jsonb)", + "Index Name": "json_small_plaintext_10000_gin_idx", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 101, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 13.33 + } + ], + "Recheck Cond": "(value @> '{\"age\": 97}'::jsonb)", + "Relation Name": "json_small_plaintext_10000", + "Startup Cost": 13.36, + "Total Cost": 213.28 + } + ], + "Startup Cost": 13.36, + "Total Cost": 33.15 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Seq Scan on json_small_plaintext_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_100000", + "Async Capable": false, + "Filter": "(value @> '{\"age\": 63}'::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1010, + "Plan Width": 4, + "Relation Name": "json_small_plaintext_100000", + "Startup Cost": 0.0, + "Total Cost": 3953.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 39.14 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Seq Scan on json_small_plaintext_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_1000000", + "Async Capable": false, + "Filter": "(value @> '{\"age\": 74}'::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10101, + "Plan Width": 4, + "Relation Name": "json_small_plaintext_1000000", + "Startup Cost": 0.0, + "Total Cost": 39528.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 39.13 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Seq Scan on json_small_plaintext_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_10000000", + "Async Capable": false, + "Filter": "(value @> '{\"age\": 63}'::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 202020, + "Plan Width": 4, + "Relation Name": "json_small_plaintext_10000000", + "Startup Cost": 0.0, + "Total Cost": 395271.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 19.57 + } + } +] +``` + +
+ +![Query Performance - PLAINTEXT/json_contains](query_plaintext_json_contains_chart.png) + +## json_field_eq + +**Description:** Unknown query + +**** + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 218.80μs | N/A | +| 100,000 | 10 | 223.32μs | N/A | +| 1,000,000 | 10 | 288.18μs | N/A | +| 10,000,000 | 10 | 146.63μs | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Seq Scan on json_small_plaintext_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_10000", + "Async Capable": false, + "Filter": "((value -> 'age'::text) = '97'::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50, + "Plan Width": 4, + "Relation Name": "json_small_plaintext_10000", + "Startup Cost": 0.0, + "Total Cost": 421.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 84.2 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Seq Scan on json_small_plaintext_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_100000", + "Async Capable": false, + "Filter": "((value -> 'age'::text) = '63'::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 4, + "Relation Name": "json_small_plaintext_100000", + "Startup Cost": 0.0, + "Total Cost": 4203.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 84.06 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Seq Scan on json_small_plaintext_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_1000000", + "Async Capable": false, + "Filter": "((value -> 'age'::text) = '74'::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5000, + "Plan Width": 4, + "Relation Name": "json_small_plaintext_1000000", + "Startup Cost": 0.0, + "Total Cost": 42028.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 84.06 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Seq Scan on json_small_plaintext_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_10000000", + "Async Capable": false, + "Filter": "((value -> 'age'::text) = '63'::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50000, + "Plan Width": 4, + "Relation Name": "json_small_plaintext_10000000", + "Startup Cost": 0.0, + "Total Cost": 420271.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 84.05 + } + } +] +``` + +
+ +![Query Performance - PLAINTEXT/json_field_eq](query_plaintext_json_field_eq_chart.png) + +## range_gt_10 + +**Description:** Unknown query + +**** + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 96.72μs | N/A | +| 100,000 | 10 | 87.60μs | N/A | +| 1,000,000 | 10 | 92.98μs | N/A | +| 10,000,000 | 10 | 89.40μs | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Seq Scan on integer_plaintext_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_10000", + "Async Capable": false, + "Filter": "(value > 5000)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5019, + "Plan Width": 8, + "Relation Name": "integer_plaintext_10000", + "Startup Cost": 0.0, + "Total Cost": 170.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 0.34 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Seq Scan on integer_plaintext_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_100000", + "Async Capable": false, + "Filter": "(value > 5000)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 49805, + "Plan Width": 8, + "Relation Name": "integer_plaintext_100000", + "Startup Cost": 0.0, + "Total Cost": 1693.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 0.34 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Seq Scan on integer_plaintext_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_1000000", + "Async Capable": false, + "Filter": "(value > 5000)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500922, + "Plan Width": 8, + "Relation Name": "integer_plaintext_1000000", + "Startup Cost": 0.0, + "Total Cost": 16925.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 0.34 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Seq Scan on integer_plaintext_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_10000000", + "Async Capable": false, + "Filter": "(value > 5000)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4944950, + "Plan Width": 8, + "Relation Name": "integer_plaintext_10000000", + "Startup Cost": 0.0, + "Total Cost": 169248.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 0.34 + } + } +] +``` + +
+ +![Query Performance - PLAINTEXT/range_gt_10](query_plaintext_range_gt_10_chart.png) + +## range_lt_ordered_10 + +**Description:** Unknown query + +**** + +**Indexes used by the planner (per data set size):** + +- 10,000: `integer_plaintext_10000_value_idx` +- 100,000: `integer_plaintext_100000_value_idx` +- 1,000,000: `integer_plaintext_1000000_value_idx` +- 10,000,000: `integer_plaintext_10000000_value_idx` + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 99.48μs | N/A | +| 100,000 | 10 | 102.40μs | N/A | +| 1,000,000 | 10 | 101.72μs | N/A | +| 10,000,000 | 10 | 97.27μs | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Index Scan using integer_plaintext_10000_value_idx on integer_plaintext_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_10000", + "Async Capable": false, + "Index Cond": "(value < 5000)", + "Index Name": "integer_plaintext_10000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4980, + "Plan Width": 8, + "Relation Name": "integer_plaintext_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.29, + "Total Cost": 327.43 + } + ], + "Startup Cost": 0.29, + "Total Cost": 0.94 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Index Scan using integer_plaintext_100000_value_idx on integer_plaintext_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_100000", + "Async Capable": false, + "Index Cond": "(value < 5000)", + "Index Name": "integer_plaintext_100000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50194, + "Plan Width": 8, + "Relation Name": "integer_plaintext_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.29, + "Total Cost": 3206.69 + } + ], + "Startup Cost": 0.29, + "Total Cost": 0.93 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Index Scan using integer_plaintext_1000000_value_idx on integer_plaintext_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_1000000", + "Async Capable": false, + "Index Cond": "(value < 5000)", + "Index Name": "integer_plaintext_1000000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 499077, + "Plan Width": 8, + "Relation Name": "integer_plaintext_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.42, + "Total Cost": 31914.21 + } + ], + "Startup Cost": 0.42, + "Total Cost": 1.06 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Index Scan using integer_plaintext_10000000_value_idx on integer_plaintext_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_10000000", + "Async Capable": false, + "Index Cond": "(value < 5000)", + "Index Name": "integer_plaintext_10000000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5055049, + "Plan Width": 8, + "Relation Name": "integer_plaintext_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.43, + "Total Cost": 320895.98 + } + ], + "Startup Cost": 0.43, + "Total Cost": 1.07 + } + } +] +``` + +
+ +![Query Performance - PLAINTEXT/range_lt_ordered_10](query_plaintext_range_lt_ordered_10_chart.png) + diff --git a/report/query_combo_bloom_ore_order_limit_chart.png b/report/query_combo_bloom_ore_order_limit_chart.png index 369bdfe..ab6a5ae 100644 Binary files a/report/query_combo_bloom_ore_order_limit_chart.png and b/report/query_combo_bloom_ore_order_limit_chart.png differ diff --git a/report/query_combo_filtered_group_by_chart.png b/report/query_combo_filtered_group_by_chart.png index 5febff5..9808d21 100644 Binary files a/report/query_combo_filtered_group_by_chart.png and b/report/query_combo_filtered_group_by_chart.png differ diff --git a/report/query_combo_top_n_filtered_group_by_chart.png b/report/query_combo_top_n_filtered_group_by_chart.png index d7288fc..afb19f2 100644 Binary files a/report/query_combo_top_n_filtered_group_by_chart.png and b/report/query_combo_top_n_filtered_group_by_chart.png differ diff --git a/report/query_exact_eql_cast_chart.png b/report/query_exact_eql_cast_chart.png index 6df2150..e130b8f 100644 Binary files a/report/query_exact_eql_cast_chart.png and b/report/query_exact_eql_cast_chart.png differ diff --git a/report/query_exact_eql_hash_chart.png b/report/query_exact_eql_hash_chart.png index 635d649..0a1c60b 100644 Binary files a/report/query_exact_eql_hash_chart.png and b/report/query_exact_eql_hash_chart.png differ diff --git a/report/query_group_by_low_cardinality_groups_encrypted_chart.png b/report/query_group_by_low_cardinality_groups_encrypted_chart.png index 15216fa..83d81bb 100644 Binary files a/report/query_group_by_low_cardinality_groups_encrypted_chart.png and b/report/query_group_by_low_cardinality_groups_encrypted_chart.png differ diff --git a/report/query_group_by_low_cardinality_groups_plaintext_chart.png b/report/query_group_by_low_cardinality_groups_plaintext_chart.png index ee13ed5..d5cda54 100644 Binary files a/report/query_group_by_low_cardinality_groups_plaintext_chart.png and b/report/query_group_by_low_cardinality_groups_plaintext_chart.png differ diff --git a/report/query_group_by_top_n_groups_encrypted_chart.png b/report/query_group_by_top_n_groups_encrypted_chart.png index b824c1b..5a57979 100644 Binary files a/report/query_group_by_top_n_groups_encrypted_chart.png and b/report/query_group_by_top_n_groups_encrypted_chart.png differ diff --git a/report/query_group_by_top_n_groups_plaintext_chart.png b/report/query_group_by_top_n_groups_plaintext_chart.png index 00d306c..6c814ea 100644 Binary files a/report/query_group_by_top_n_groups_plaintext_chart.png and b/report/query_group_by_top_n_groups_plaintext_chart.png differ diff --git a/report/query_json_contains_functional_chart.png b/report/query_json_contains_functional_chart.png index 10a859a..d4ccf26 100644 Binary files a/report/query_json_contains_functional_chart.png and b/report/query_json_contains_functional_chart.png differ diff --git a/report/query_json_field_eq_bare_chart.png b/report/query_json_field_eq_bare_chart.png index 3aff0c5..cc262c2 100644 Binary files a/report/query_json_field_eq_bare_chart.png and b/report/query_json_field_eq_bare_chart.png differ diff --git a/report/query_json_field_eq_extractor_chart.png b/report/query_json_field_eq_extractor_chart.png index 8be1467..04e813a 100644 Binary files a/report/query_json_field_eq_extractor_chart.png and b/report/query_json_field_eq_extractor_chart.png differ diff --git a/report/query_json_field_eq_functional_chart.png b/report/query_json_field_eq_functional_chart.png index a72e520..173d355 100644 Binary files a/report/query_json_field_eq_functional_chart.png and b/report/query_json_field_eq_functional_chart.png differ diff --git a/report/query_json_field_gt_functional_chart.png b/report/query_json_field_gt_functional_chart.png new file mode 100644 index 0000000..88192fc Binary files /dev/null and b/report/query_json_field_gt_functional_chart.png differ diff --git a/report/query_json_field_order_functional_chart.png b/report/query_json_field_order_functional_chart.png index 7938e52..fa48429 100644 Binary files a/report/query_json_field_order_functional_chart.png and b/report/query_json_field_order_functional_chart.png differ diff --git a/report/query_match_eql_bloom_chart.png b/report/query_match_eql_bloom_chart.png index ea33ea1..9798a43 100644 Binary files a/report/query_match_eql_bloom_chart.png and b/report/query_match_eql_bloom_chart.png differ diff --git a/report/query_match_eql_cast_firstname_chart.png b/report/query_match_eql_cast_firstname_chart.png index 83e6a29..3daf1c1 100644 Binary files a/report/query_match_eql_cast_firstname_chart.png and b/report/query_match_eql_cast_firstname_chart.png differ diff --git a/report/query_match_eql_cast_lastname_chart.png b/report/query_match_eql_cast_lastname_chart.png index 5805815..973f8c2 100644 Binary files a/report/query_match_eql_cast_lastname_chart.png and b/report/query_match_eql_cast_lastname_chart.png differ diff --git a/report/query_ope_range_gt_100_chart.png b/report/query_ope_range_gt_100_chart.png new file mode 100644 index 0000000..8c062a5 Binary files /dev/null and b/report/query_ope_range_gt_100_chart.png differ diff --git a/report/query_ope_range_gt_10_chart.png b/report/query_ope_range_gt_10_chart.png new file mode 100644 index 0000000..8adbd6d Binary files /dev/null and b/report/query_ope_range_gt_10_chart.png differ diff --git a/report/query_ope_range_lt_100_chart.png b/report/query_ope_range_lt_100_chart.png new file mode 100644 index 0000000..20a4cee Binary files /dev/null and b/report/query_ope_range_lt_100_chart.png differ diff --git a/report/query_ope_range_lt_10_chart.png b/report/query_ope_range_lt_10_chart.png new file mode 100644 index 0000000..e3c6e83 Binary files /dev/null and b/report/query_ope_range_lt_10_chart.png differ diff --git a/report/query_ope_range_lt_ordered_10_chart.png b/report/query_ope_range_lt_ordered_10_chart.png new file mode 100644 index 0000000..51bf25b Binary files /dev/null and b/report/query_ope_range_lt_ordered_10_chart.png differ diff --git a/report/query_ore_range_gt_100_chart.png b/report/query_ore_range_gt_100_chart.png index 26b1922..2c2ec13 100644 Binary files a/report/query_ore_range_gt_100_chart.png and b/report/query_ore_range_gt_100_chart.png differ diff --git a/report/query_ore_range_gt_10_chart.png b/report/query_ore_range_gt_10_chart.png index 978e6fd..40a4d6c 100644 Binary files a/report/query_ore_range_gt_10_chart.png and b/report/query_ore_range_gt_10_chart.png differ diff --git a/report/query_ore_range_lt_100_chart.png b/report/query_ore_range_lt_100_chart.png index 79da405..41d3549 100644 Binary files a/report/query_ore_range_lt_100_chart.png and b/report/query_ore_range_lt_100_chart.png differ diff --git a/report/query_ore_range_lt_10_chart.png b/report/query_ore_range_lt_10_chart.png index d1f4246..b013c4b 100644 Binary files a/report/query_ore_range_lt_10_chart.png and b/report/query_ore_range_lt_10_chart.png differ diff --git a/report/query_ore_range_lt_ordered_10_chart.png b/report/query_ore_range_lt_ordered_10_chart.png index e23d52c..320fea2 100644 Binary files a/report/query_ore_range_lt_ordered_10_chart.png and b/report/query_ore_range_lt_ordered_10_chart.png differ diff --git a/report/query_plaintext_exact_eq_chart.png b/report/query_plaintext_exact_eq_chart.png new file mode 100644 index 0000000..3ea9bd5 Binary files /dev/null and b/report/query_plaintext_exact_eq_chart.png differ diff --git a/report/query_plaintext_json_contains_chart.png b/report/query_plaintext_json_contains_chart.png new file mode 100644 index 0000000..dba07c4 Binary files /dev/null and b/report/query_plaintext_json_contains_chart.png differ diff --git a/report/query_plaintext_json_field_eq_chart.png b/report/query_plaintext_json_field_eq_chart.png new file mode 100644 index 0000000..3e4c9b3 Binary files /dev/null and b/report/query_plaintext_json_field_eq_chart.png differ diff --git a/report/query_plaintext_range_gt_10_chart.png b/report/query_plaintext_range_gt_10_chart.png new file mode 100644 index 0000000..fb88109 Binary files /dev/null and b/report/query_plaintext_range_gt_10_chart.png differ diff --git a/report/query_plaintext_range_lt_ordered_10_chart.png b/report/query_plaintext_range_lt_ordered_10_chart.png new file mode 100644 index 0000000..cc16f79 Binary files /dev/null and b/report/query_plaintext_range_lt_ordered_10_chart.png differ diff --git a/report/scalar_smoke.md b/report/scalar_smoke.md new file mode 100644 index 0000000..f2f721e --- /dev/null +++ b/report/scalar_smoke.md @@ -0,0 +1,138 @@ +# SCALAR_SMOKE Queries + +[← Back to overview](./BENCHMARK_REPORT.md) + +Per-tier query performance. Each scenario lists its SQL, the indexes available on the target table, the indexes the planner actually picked per tier, the timing table, and the full EXPLAIN plan in a collapsed block. + +## bigint_ord/range_gt_10 + +**Description:** Unknown query + +**** + +| Data Set Size | Rows (est.) | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|-------------|-------------------------|---------------------------| +| 10,000 | — | 777.22μs | N/A | + +_Rows are the planner's estimate from `EXPLAIN` captured before the bench loop; re-run the bench with the current source to capture actual row counts._ + +## bigint_ord/range_gt_ordered_10 + +**Description:** Unknown query + +**** + +| Data Set Size | Rows (est.) | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|-------------|-------------------------|---------------------------| +| 10,000 | — | 580.85μs | N/A | + +_Rows are the planner's estimate from `EXPLAIN` captured before the bench loop; re-run the bench with the current source to capture actual row counts._ + +## boolean/select_back + +**Description:** Unknown query + +**** + +| Data Set Size | Rows (est.) | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|-------------|-------------------------|---------------------------| +| 10,000 | — | 98.49μs | N/A | + +_Rows are the planner's estimate from `EXPLAIN` captured before the bench loop; re-run the bench with the current source to capture actual row counts._ + +## date_ord/range_gt_10 + +**Description:** Unknown query + +**** + +| Data Set Size | Rows (est.) | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|-------------|-------------------------|---------------------------| +| 10,000 | — | 1.48ms | N/A | + +_Rows are the planner's estimate from `EXPLAIN` captured before the bench loop; re-run the bench with the current source to capture actual row counts._ + +## date_ord/range_gt_ordered_10 + +**Description:** Unknown query + +**** + +| Data Set Size | Rows (est.) | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|-------------|-------------------------|---------------------------| +| 10,000 | — | 1.34ms | N/A | + +_Rows are the planner's estimate from `EXPLAIN` captured before the bench loop; re-run the bench with the current source to capture actual row counts._ + +## double_ord/range_gt_10 + +**Description:** Unknown query + +**** + +| Data Set Size | Rows (est.) | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|-------------|-------------------------|---------------------------| +| 10,000 | — | 1.07ms | N/A | + +_Rows are the planner's estimate from `EXPLAIN` captured before the bench loop; re-run the bench with the current source to capture actual row counts._ + +## double_ord/range_gt_ordered_10 + +**Description:** Unknown query + +**** + +| Data Set Size | Rows (est.) | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|-------------|-------------------------|---------------------------| +| 10,000 | — | 617.01μs | N/A | + +_Rows are the planner's estimate from `EXPLAIN` captured before the bench loop; re-run the bench with the current source to capture actual row counts._ + +## numeric_ord/range_gt_10 + +**Description:** Unknown query + +**** + +| Data Set Size | Rows (est.) | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|-------------|-------------------------|---------------------------| +| 10,000 | — | 1.02ms | N/A | + +_Rows are the planner's estimate from `EXPLAIN` captured before the bench loop; re-run the bench with the current source to capture actual row counts._ + +## numeric_ord/range_gt_ordered_10 + +**Description:** Unknown query + +**** + +| Data Set Size | Rows (est.) | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|-------------|-------------------------|---------------------------| +| 10,000 | — | 744.64μs | N/A | + +_Rows are the planner's estimate from `EXPLAIN` captured before the bench loop; re-run the bench with the current source to capture actual row counts._ + +## timestamp_ord/range_gt_10 + +**Description:** Unknown query + +**** + +| Data Set Size | Rows (est.) | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|-------------|-------------------------|---------------------------| +| 10,000 | — | 949.15μs | N/A | + +_Rows are the planner's estimate from `EXPLAIN` captured before the bench loop; re-run the bench with the current source to capture actual row counts._ + +## timestamp_ord/range_gt_ordered_10 + +**Description:** Unknown query + +**** + +| Data Set Size | Rows (est.) | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|-------------|-------------------------|---------------------------| +| 10,000 | — | 678.64μs | N/A | + +_Rows are the planner's estimate from `EXPLAIN` captured before the bench loop; re-run the bench with the current source to capture actual row counts._ + diff --git a/report/v2/BENCHMARK_REPORT.md b/report/v2/BENCHMARK_REPORT.md new file mode 100644 index 0000000..d214afc --- /dev/null +++ b/report/v2/BENCHMARK_REPORT.md @@ -0,0 +1,121 @@ +# Benchmark Report + +This report summarises the performance benchmarks for encrypted database operations. Per-query-type detail lives on its own page — click through from the Query Performance section below. + +## Table of Contents + +1. [Ingest Throughput](#ingest-throughput) + - [Int](#int) + - [Json Large](#json-large) + - [Json Small](#json-small) + - [Ste Vec Small](#ste-vec-small) + - [String](#string) +2. [Query Performance](#query-performance) + - [COMBO Queries](combo.md) + - [EXACT Queries](exact.md) + - [GROUP_BY Queries](group_by.md) + - [JSON Queries](json.md) + - [MATCH Queries](match.md) + - [ORE Queries](ore.md) + +--- + +## Ingest Throughput + +This section measures the throughput of inserting encrypted records into the database. + +### Comparison at 10,000 Records + +Comparing all benchmark types at 10,000 records. + +![Throughput Comparison at 10,000 records](ingest_comparison_throughput_10000.png) + +![Total Time Comparison at 10,000 records](ingest_comparison_time_10000.png) + +![Total Time Comparison at 10,000 records (excluding ste_vec_large)](ingest_comparison_time_10000_filtered.png) + +### Int + +Tests insertion of encrypted integer values. + +| Records | Throughput (records/sec) | Total Time | Avg Memory | +|---------|--------------------------|------------|------------| +| 500 | 698.69 | 0.72s | 17.22 MB | +| 1,000 | 1.59K | 0.63s | 20.39 MB | +| 10,000 | 2.13K | 4.70s | 22.25 MB | + +![Ingest Throughput - int](ingest_int_throughput_chart.png) + +![Ingest Total Time - int](ingest_int_time_chart.png) + +### Json Large + +Tests insertion of large encrypted JSON objects with complex nested structures (user info, company, addresses, orders). + +| Records | Throughput (records/sec) | Total Time | Avg Memory | +|---------|--------------------------|------------|------------| +| 500 | 734.25 | 0.68s | 55.98 MB | +| 1,000 | 2.13K | 0.47s | 95.58 MB | +| 10,000 | 3.59K | 2.79s | 162.06 MB | + +![Ingest Throughput - json_large](ingest_json_large_throughput_chart.png) + +![Ingest Total Time - json_large](ingest_json_large_time_chart.png) + +### Json Small + +Tests insertion of small encrypted JSON objects (first_name, last_name, age, email). + +| Records | Throughput (records/sec) | Total Time | Avg Memory | +|---------|--------------------------|------------|------------| +| 500 | 665.29 | 0.75s | 16.22 MB | +| 1,000 | 3.68K | 0.27s | 18.05 MB | +| 10,000 | 11.42K | 0.88s | 20.22 MB | + +![Ingest Throughput - json_small](ingest_json_small_throughput_chart.png) + +![Ingest Total Time - json_small](ingest_json_small_time_chart.png) + +### Ste Vec Small + +Tests insertion of small JSON objects with SteVec (searchable encrypted vector) indexing. + +| Records | Throughput (records/sec) | Total Time | Avg Memory | +|---------|--------------------------|------------|------------| +| 10,000 | 4.03K | 2.48s | 31.90 MB | + +![Ingest Throughput - ste_vec_small](ingest_ste_vec_small_throughput_chart.png) + +![Ingest Total Time - ste_vec_small](ingest_ste_vec_small_time_chart.png) + +### String + +Tests insertion of encrypted string values. + +| Records | Throughput (records/sec) | Total Time | Avg Memory | +|---------|--------------------------|------------|------------| +| 500 | 966.23 | 0.52s | 16.48 MB | +| 1,000 | 3.99K | 0.25s | 18.66 MB | +| 10,000 | 9.65K | 1.04s | 21.23 MB | + +![Ingest Throughput - string](ingest_string_throughput_chart.png) + +![Ingest Total Time - string](ingest_string_time_chart.png) + +## Query Performance + +Per-query-type detail is broken out into separate pages — click into a scenario family for the SQL, per-tier timings, the indexes the planner picked, and the EXPLAIN plan tree. + +| Query Type | Scenarios | Tiers | Largest-tier median (no decrypt) | Detail | +|-|-|-|-|-| +| COMBO | `bloom_ore_order_limit`, `filtered_group_by`, `top_n_filtered_group_by` | 10,000, 100,000, 1,000,000, 10,000,000 | 86.89ms | [open](combo.md) | +| EXACT | `eql_cast`, `eql_hash` | 10,000, 100,000, 1,000,000, 10,000,000 | 108.58μs | [open](exact.md) | +| GROUP_BY | `low_cardinality_groups_encrypted`, `low_cardinality_groups_plaintext`, `top_n_groups_encrypted`, `top_n_groups_plaintext` | 10,000, 100,000, 1,000,000, 10,000,000 | 568.48ms | [open](group_by.md) | +| JSON | `contains/functional`, `field_eq/bare`, `field_eq/extractor`, `field_eq/functional`, `field_order/functional` | 10,000, 100,000, 1,000,000, 10,000,000 | 370.33μs | [open](json.md) | +| MATCH | `eql_bloom`, `eql_cast_firstname`, `eql_cast_lastname` | 10,000, 100,000, 1,000,000, 10,000,000 | 107.51ms | [open](match.md) | +| ORE | `range_gt_10`, `range_gt_100`, `range_lt_10`, `range_lt_100`, `range_lt_ordered_10` | 10,000, 100,000, 1,000,000, 10,000,000 | 2.01ms | [open](ore.md) | + + +--- + +*Report generated by `report_benchmarks.py`* diff --git a/report/README.md b/report/v2/README.md similarity index 100% rename from report/README.md rename to report/v2/README.md diff --git a/report/v2/combo.md b/report/v2/combo.md new file mode 100644 index 0000000..d50a1d0 --- /dev/null +++ b/report/v2/combo.md @@ -0,0 +1,1187 @@ +# COMBO Queries + +[← Back to overview](./BENCHMARK_REPORT.md) + +Per-tier query performance. Each scenario lists its SQL, the indexes available on the target table, the indexes the planner actually picked per tier, the timing table, and the full EXPLAIN plan in a collapsed block. + +## bloom_ore_order_limit + +**Description:** Composite predicate: filter by name pattern (bloom), order by age (ORE), limit 10 + +**SQL Query:** +```sql +SELECT id FROM {TABLE} WHERE name LIKE $1 ORDER BY eql_v2.ore_block_u64_8_256(age) LIMIT 10 +``` + +**Parameter:** `Bob` + +**Table: `combo_encrypted_{rows}` with three encrypted columns — `name` (match + hmac), `age` (ORE), `category` (hmac). Indexes: functional GIN on `eql_v2.bloom_filter(name)`, functional btree on `eql_v2.ore_block_u64_8_256(age)`, functional hash on `eql_v2.hmac_256(category)`. **The bloom GIN index engages for the LIKE predicate**, narrowing the input to ~0.01–0.1% of rows; the planner then sorts the small filtered set by `eql_v2.ore_block_u64_8_256(age)` and returns the top 10. The ORE btree doesn't engage here — PostgreSQL can't merge two unrelated indexes on different columns (bloom on `name`, btree on `age`), so the ORDER BY is satisfied by a Sort node above the Bitmap Heap Scan. With the bloom narrowing so aggressively, that Sort is cheap; the cost is dominated by the bloom + heap fetch.** + +**Indexes available on the table:** +```sql +CREATE INDEX +combo_encrypted_10000_name_gin_index +ON combo_encrypted_10000 USING GIN ( + eql_v2.bloom_filter(name) +); + +CREATE INDEX +combo_encrypted_10000_age_ore_index +ON combo_encrypted_10000 ( + eql_v2.ore_block_u64_8_256(age) +); + +CREATE INDEX +combo_encrypted_10000_category_hash_index +ON combo_encrypted_10000 USING hash ( + eql_v2.hmac_256(category) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: `combo_encrypted_10000_name_gin_index` +- 100,000: `combo_encrypted_100000_name_gin_index` +- 1,000,000: `combo_encrypted_1000000_name_gin_index` +- 10,000,000: `combo_encrypted_10000000_name_gin_index` + +*⚠️ = Query time exceeds 100ms* + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 4 | 303.27μs | N/A | +| 100,000 | 10 | 2.11ms | N/A | +| 1,000,000 | 10 | 16.53ms | N/A | +| 10,000,000 | 10 | ⚠️ 159.30ms | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Sort + Bitmap Heap Scan on combo_encrypted_10000 + Bitmap Index Scan using combo_encrypted_10000_name_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "combo_encrypted_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1554,461,1033,91,1393,453}'::smallint[])", + "Index Name": "combo_encrypted_10000_name_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 56.22 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1554,461,1033,91,1393,453}'::smallint[])", + "Relation Name": "combo_encrypted_10000", + "Startup Cost": 56.22, + "Total Cost": 60.73 + } + ], + "Sort Key": [ + "(eql_v2.ore_block_u64_8_256(age))" + ], + "Startup Cost": 60.74, + "Total Cost": 60.75 + } + ], + "Startup Cost": 60.74, + "Total Cost": 60.75 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Sort + Bitmap Heap Scan on combo_encrypted_100000 + Bitmap Index Scan using combo_encrypted_100000_name_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "combo_encrypted_100000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,1554,453,1393,91,461}'::smallint[])", + "Index Name": "combo_encrypted_100000_name_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 93.35 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,1554,453,1393,91,461}'::smallint[])", + "Relation Name": "combo_encrypted_100000", + "Startup Cost": 93.35, + "Total Cost": 97.86 + } + ], + "Sort Key": [ + "(eql_v2.ore_block_u64_8_256(age))" + ], + "Startup Cost": 97.87, + "Total Cost": 97.87 + } + ], + "Startup Cost": 97.87, + "Total Cost": 97.87 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Sort + Bitmap Heap Scan on combo_encrypted_1000000 + Bitmap Index Scan using combo_encrypted_1000000_name_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "combo_encrypted_1000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,91,461,1393,453,1554}'::smallint[])", + "Index Name": "combo_encrypted_1000000_name_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 282.35 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,91,461,1393,453,1554}'::smallint[])", + "Relation Name": "combo_encrypted_1000000", + "Startup Cost": 282.35, + "Total Cost": 286.86 + } + ], + "Sort Key": [ + "(eql_v2.ore_block_u64_8_256(age))" + ], + "Startup Cost": 286.87, + "Total Cost": 286.87 + } + ], + "Startup Cost": 286.87, + "Total Cost": 286.87 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Sort + Bitmap Heap Scan on combo_encrypted_10000000 + Bitmap Index Scan using combo_encrypted_10000000_name_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "combo_encrypted_10000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1393,461,1033,1554,453,91}'::smallint[])", + "Index Name": "combo_encrypted_10000000_name_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 2258.22 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1393,461,1033,1554,453,91}'::smallint[])", + "Relation Name": "combo_encrypted_10000000", + "Startup Cost": 2258.22, + "Total Cost": 2262.73 + } + ], + "Sort Key": [ + "(eql_v2.ore_block_u64_8_256(age))" + ], + "Startup Cost": 2262.74, + "Total Cost": 2262.75 + } + ], + "Startup Cost": 2262.74, + "Total Cost": 2262.75 + } + } +] +``` + +
+ +![Query Performance - COMBO/bloom_ore_order_limit](query_combo_bloom_ore_order_limit_chart.png) + +## filtered_group_by + +**Description:** Composite predicate: filter by name pattern, GROUP BY category + +**SQL Query:** +```sql +SELECT eql_v2.hmac_256(category), count(*) FROM {TABLE} WHERE name LIKE $1 GROUP BY 1 +``` + +**Parameter:** `Bob` + +**Table: `combo_encrypted_{rows}`. Query: `SELECT eql_v2.hmac_256(category), count(*) FROM tbl WHERE name LIKE $1 GROUP BY 1`. Bloom filter on `name` filters the input set; HashAggregate then groups the small post-filter set by the 32-byte category HMAC. With ~0.01-0.1% of names matching a typical bloom pattern and 250 category buckets, the aggregate stage is essentially free — the cost is bloom filter scan plus per-matching-row HMAC.** + +**Indexes available on the table:** +```sql +CREATE INDEX +combo_encrypted_10000_name_gin_index +ON combo_encrypted_10000 USING GIN ( + eql_v2.bloom_filter(name) +); + +CREATE INDEX +combo_encrypted_10000_age_ore_index +ON combo_encrypted_10000 ( + eql_v2.ore_block_u64_8_256(age) +); + +CREATE INDEX +combo_encrypted_10000_category_hash_index +ON combo_encrypted_10000 USING hash ( + eql_v2.hmac_256(category) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: `combo_encrypted_10000_name_gin_index` +- 100,000: `combo_encrypted_100000_name_gin_index` +- 1,000,000: `combo_encrypted_1000000_name_gin_index` +- 10,000,000: `combo_encrypted_10000000_name_gin_index` + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 4 | 177.62μs | N/A | +| 100,000 | 52 | 679.25μs | N/A | +| 1,000,000 | 231 | 9.10ms | N/A | +| 10,000,000 | 250 | 50.09ms | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Aggregate (Sorted) + Sort + Bitmap Heap Scan on combo_encrypted_10000 + Bitmap Index Scan using combo_encrypted_10000_name_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Group Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Alias": "combo_encrypted_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,91,453,1554,461,1393}'::smallint[])", + "Index Name": "combo_encrypted_10000_name_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 56.22 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,91,453,1554,461,1393}'::smallint[])", + "Relation Name": "combo_encrypted_10000", + "Startup Cost": 56.22, + "Total Cost": 60.49 + } + ], + "Sort Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Startup Cost": 60.5, + "Total Cost": 60.5 + } + ], + "Startup Cost": 60.5, + "Strategy": "Sorted", + "Total Cost": 60.52 + } + } +] +``` + +**100,000 rows** + +``` +Aggregate (Sorted) + Sort + Bitmap Heap Scan on combo_encrypted_100000 + Bitmap Index Scan using combo_encrypted_100000_name_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Group Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Alias": "combo_encrypted_100000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1554,91,1033,453,461,1393}'::smallint[])", + "Index Name": "combo_encrypted_100000_name_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 93.35 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1554,91,1033,453,461,1393}'::smallint[])", + "Relation Name": "combo_encrypted_100000", + "Startup Cost": 93.35, + "Total Cost": 97.61 + } + ], + "Sort Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Startup Cost": 97.62, + "Total Cost": 97.63 + } + ], + "Startup Cost": 97.62, + "Strategy": "Sorted", + "Total Cost": 97.64 + } + } +] +``` + +**1,000,000 rows** + +``` +Aggregate (Sorted) + Sort + Bitmap Heap Scan on combo_encrypted_1000000 + Bitmap Index Scan using combo_encrypted_1000000_name_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Group Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Alias": "combo_encrypted_1000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,1033,91,461,1393,1554}'::smallint[])", + "Index Name": "combo_encrypted_1000000_name_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 282.35 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,1033,91,461,1393,1554}'::smallint[])", + "Relation Name": "combo_encrypted_1000000", + "Startup Cost": 282.35, + "Total Cost": 286.61 + } + ], + "Sort Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Startup Cost": 286.62, + "Total Cost": 286.63 + } + ], + "Startup Cost": 286.62, + "Strategy": "Sorted", + "Total Cost": 286.64 + } + } +] +``` + +**10,000,000 rows** + +``` +Aggregate (Sorted) + Sort + Bitmap Heap Scan on combo_encrypted_10000000 + Bitmap Index Scan using combo_encrypted_10000000_name_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Group Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Alias": "combo_encrypted_10000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,453,461,1554,91,1393}'::smallint[])", + "Index Name": "combo_encrypted_10000000_name_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 2258.22 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,453,461,1554,91,1393}'::smallint[])", + "Relation Name": "combo_encrypted_10000000", + "Startup Cost": 2258.22, + "Total Cost": 2262.49 + } + ], + "Sort Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Startup Cost": 2262.5, + "Total Cost": 2262.5 + } + ], + "Startup Cost": 2262.5, + "Strategy": "Sorted", + "Total Cost": 2262.52 + } + } +] +``` + +
+ +![Query Performance - COMBO/filtered_group_by](query_combo_filtered_group_by_chart.png) + +## top_n_filtered_group_by + +**Description:** Dashboard analytic: top 10 categories for customers matching a name pattern + +**SQL Query:** +```sql +SELECT eql_v2.hmac_256(category), count(*) FROM {TABLE} WHERE name LIKE $1 GROUP BY 1 ORDER BY count(*) DESC LIMIT 10 +``` + +**Parameter:** `Bob` + +**Table: `combo_encrypted_{rows}`. Query: `SELECT eql_v2.hmac_256(category), count(*) FROM tbl WHERE name LIKE $1 GROUP BY 1 ORDER BY count(*) DESC LIMIT 10`. Same shape as `filtered_group_by` with an outer Top-N sort + LIMIT 10. Realistic analytics shape for surfacing the categories that contain the most customers matching a filter, without revealing the underlying names or category labels.** + +**Indexes available on the table:** +```sql +CREATE INDEX +combo_encrypted_10000_name_gin_index +ON combo_encrypted_10000 USING GIN ( + eql_v2.bloom_filter(name) +); + +CREATE INDEX +combo_encrypted_10000_age_ore_index +ON combo_encrypted_10000 ( + eql_v2.ore_block_u64_8_256(age) +); + +CREATE INDEX +combo_encrypted_10000_category_hash_index +ON combo_encrypted_10000 USING hash ( + eql_v2.hmac_256(category) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: `combo_encrypted_10000_name_gin_index` +- 100,000: `combo_encrypted_100000_name_gin_index` +- 1,000,000: `combo_encrypted_1000000_name_gin_index` +- 10,000,000: `combo_encrypted_10000000_name_gin_index` + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 4 | 177.00μs | N/A | +| 100,000 | 10 | 1.01ms | N/A | +| 1,000,000 | 10 | 5.32ms | N/A | +| 10,000,000 | 10 | 52.33ms | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Sort + Aggregate (Sorted) + Sort + Bitmap Heap Scan on combo_encrypted_10000 + Bitmap Index Scan using combo_encrypted_10000_name_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Alias": "combo_encrypted_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,1554,91,1393,461,453}'::smallint[])", + "Index Name": "combo_encrypted_10000_name_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 56.22 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{1033,1554,91,1393,461,453}'::smallint[])", + "Relation Name": "combo_encrypted_10000", + "Startup Cost": 56.22, + "Total Cost": 60.49 + } + ], + "Sort Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Startup Cost": 60.5, + "Total Cost": 60.5 + } + ], + "Startup Cost": 60.5, + "Strategy": "Sorted", + "Total Cost": 60.52 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 60.53, + "Total Cost": 60.53 + } + ], + "Startup Cost": 60.53, + "Total Cost": 60.53 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Sort + Aggregate (Sorted) + Sort + Bitmap Heap Scan on combo_encrypted_100000 + Bitmap Index Scan using combo_encrypted_100000_name_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Alias": "combo_encrypted_100000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,461,1033,1554,1393,91}'::smallint[])", + "Index Name": "combo_encrypted_100000_name_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 93.35 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,461,1033,1554,1393,91}'::smallint[])", + "Relation Name": "combo_encrypted_100000", + "Startup Cost": 93.35, + "Total Cost": 97.61 + } + ], + "Sort Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Startup Cost": 97.62, + "Total Cost": 97.63 + } + ], + "Startup Cost": 97.62, + "Strategy": "Sorted", + "Total Cost": 97.64 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 97.65, + "Total Cost": 97.66 + } + ], + "Startup Cost": 97.65, + "Total Cost": 97.66 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Sort + Aggregate (Sorted) + Sort + Bitmap Heap Scan on combo_encrypted_1000000 + Bitmap Index Scan using combo_encrypted_1000000_name_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Alias": "combo_encrypted_1000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,91,1554,461,1033,1393}'::smallint[])", + "Index Name": "combo_encrypted_1000000_name_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 282.35 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,91,1554,461,1033,1393}'::smallint[])", + "Relation Name": "combo_encrypted_1000000", + "Startup Cost": 282.35, + "Total Cost": 286.61 + } + ], + "Sort Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Startup Cost": 286.62, + "Total Cost": 286.63 + } + ], + "Startup Cost": 286.62, + "Strategy": "Sorted", + "Total Cost": 286.64 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 286.65, + "Total Cost": 286.66 + } + ], + "Startup Cost": 286.65, + "Total Cost": 286.66 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Sort + Aggregate (Sorted) + Sort + Bitmap Heap Scan on combo_encrypted_10000000 + Bitmap Index Scan using combo_encrypted_10000000_name_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Alias": "combo_encrypted_10000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,1554,461,91,1033,1393}'::smallint[])", + "Index Name": "combo_encrypted_10000000_name_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 2258.22 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(name))::smallint[] @> '{453,1554,461,91,1033,1393}'::smallint[])", + "Relation Name": "combo_encrypted_10000000", + "Startup Cost": 2258.22, + "Total Cost": 2262.49 + } + ], + "Sort Key": [ + "((((category).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Startup Cost": 2262.5, + "Total Cost": 2262.5 + } + ], + "Startup Cost": 2262.5, + "Strategy": "Sorted", + "Total Cost": 2262.52 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 2262.53, + "Total Cost": 2262.53 + } + ], + "Startup Cost": 2262.53, + "Total Cost": 2262.53 + } + } +] +``` + +
+ +![Query Performance - COMBO/top_n_filtered_group_by](query_combo_top_n_filtered_group_by_chart.png) + diff --git a/report/v2/exact.md b/report/v2/exact.md new file mode 100644 index 0000000..d2ce848 --- /dev/null +++ b/report/v2/exact.md @@ -0,0 +1,444 @@ +# EXACT Queries + +[← Back to overview](./BENCHMARK_REPORT.md) + +Per-tier query performance. Each scenario lists its SQL, the indexes available on the target table, the indexes the planner actually picked per tier, the timing table, and the full EXPLAIN plan in a collapsed block. + +## eql_cast + +**Description:** Exact match using EQL cast operator + +**SQL Query:** +```sql +SELECT value FROM {TABLE} WHERE value = $1 LIMIT 1 +``` + +**Parameter:** `Bob Johnson` + +**Table: `string_encrypted_{rows}` with encrypted string values. Index: UNIQUE index on the encrypted value column.** + +**Indexes available on the table:** +```sql +CREATE INDEX +string_encrypted_10000_hash_index +ON string_encrypted_10000 using hash ( + eql_v2.hmac_256(value) +); + +CREATE INDEX +string_encrypted_10000_gin_index +ON string_encrypted_10000 USING GIN ( + eql_v2.bloom_filter(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: `string_encrypted_10000_hash_index` +- 100,000: `string_encrypted_100000_hash_index` +- 1,000,000: `string_encrypted_1000000_hash_index` +- 10,000,000: `string_encrypted_10000000_hash_index` + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 1 | 119.29μs | 24.05ms | +| 100,000 | 1 | 112.11μs | 23.86ms | +| 1,000,000 | 1 | 114.68μs | 23.74ms | +| 10,000,000 | 1 | 102.98μs | 24.26ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Index Scan using string_encrypted_10000_hash_index on string_encrypted_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_10000", + "Async Capable": false, + "Index Cond": "(((value).data ->> 'hm'::text) = '0379ecd88462a47250b720767ba169469b55dc5cdda2763c6f29a3e2e3011af4'::text)", + "Index Name": "string_encrypted_10000_hash_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Relation Name": "string_encrypted_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.0, + "Total Cost": 8.27 + } + ], + "Startup Cost": 0.0, + "Total Cost": 8.27 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Index Scan using string_encrypted_100000_hash_index on string_encrypted_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_100000", + "Async Capable": false, + "Index Cond": "(((value).data ->> 'hm'::text) = '1cc588acb3d87df5f7b66ccec01912ddba6f9f66fb96939cd2055d45af937af4'::text)", + "Index Name": "string_encrypted_100000_hash_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Relation Name": "string_encrypted_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.0, + "Total Cost": 8.27 + } + ], + "Startup Cost": 0.0, + "Total Cost": 8.27 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Index Scan using string_encrypted_1000000_hash_index on string_encrypted_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_1000000", + "Async Capable": false, + "Index Cond": "(((value).data ->> 'hm'::text) = '30906de41a8760c9f4c3a500a5e111c24f8fdde7f8a3bcdbc95cbe76d3697bb3'::text)", + "Index Name": "string_encrypted_1000000_hash_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 2, + "Plan Width": 36, + "Relation Name": "string_encrypted_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.0, + "Total Cost": 12.54 + } + ], + "Startup Cost": 0.0, + "Total Cost": 6.27 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Index Scan using string_encrypted_10000000_hash_index on string_encrypted_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_10000000", + "Async Capable": false, + "Index Cond": "(((value).data ->> 'hm'::text) = 'e361bf6d2ee8c36944302cb9963da12b0e6bbdc563f5e088f8b970b7779cc2fb'::text)", + "Index Name": "string_encrypted_10000000_hash_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 8, + "Plan Width": 36, + "Relation Name": "string_encrypted_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.0, + "Total Cost": 38.14 + } + ], + "Startup Cost": 0.0, + "Total Cost": 4.77 + } + } +] +``` + +
+ +![Query Performance - EXACT/eql_cast](query_exact_eql_cast_chart.png) + +## eql_hash + +**Description:** Exact match using EQL HMAC-256 hash function + +**SQL Query:** +```sql +SELECT value FROM {TABLE} WHERE eql_v2.hmac_256(value) = eql_v2.hmac_256($1::jsonb) LIMIT 1 +``` + +**Parameter:** `Bob Johnson` + +**Table: `string_encrypted_{rows}` with encrypted string values. Index: Hash-based unique index using `eql_v2.hmac_256`.** + +**Indexes available on the table:** +```sql +CREATE INDEX +string_encrypted_10000_hash_index +ON string_encrypted_10000 using hash ( + eql_v2.hmac_256(value) +); + +CREATE INDEX +string_encrypted_10000_gin_index +ON string_encrypted_10000 USING GIN ( + eql_v2.bloom_filter(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: `string_encrypted_10000_hash_index` +- 100,000: `string_encrypted_100000_hash_index` +- 1,000,000: `string_encrypted_1000000_hash_index` +- 10,000,000: `string_encrypted_10000000_hash_index` + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 1 | 110.71μs | 24.82ms | +| 100,000 | 1 | 109.71μs | 23.94ms | +| 1,000,000 | 1 | 104.06μs | 24.05ms | +| 10,000,000 | 1 | 107.06μs | 23.66ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Index Scan using string_encrypted_10000_hash_index on string_encrypted_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_10000", + "Async Capable": false, + "Index Cond": "(((value).data ->> 'hm'::text) = '0379ecd88462a47250b720767ba169469b55dc5cdda2763c6f29a3e2e3011af4'::text)", + "Index Name": "string_encrypted_10000_hash_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Relation Name": "string_encrypted_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.0, + "Total Cost": 8.27 + } + ], + "Startup Cost": 0.0, + "Total Cost": 8.27 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Index Scan using string_encrypted_100000_hash_index on string_encrypted_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_100000", + "Async Capable": false, + "Index Cond": "(((value).data ->> 'hm'::text) = '1cc588acb3d87df5f7b66ccec01912ddba6f9f66fb96939cd2055d45af937af4'::text)", + "Index Name": "string_encrypted_100000_hash_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Relation Name": "string_encrypted_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.0, + "Total Cost": 8.27 + } + ], + "Startup Cost": 0.0, + "Total Cost": 8.27 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Index Scan using string_encrypted_1000000_hash_index on string_encrypted_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_1000000", + "Async Capable": false, + "Index Cond": "(((value).data ->> 'hm'::text) = '30906de41a8760c9f4c3a500a5e111c24f8fdde7f8a3bcdbc95cbe76d3697bb3'::text)", + "Index Name": "string_encrypted_1000000_hash_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 2, + "Plan Width": 36, + "Relation Name": "string_encrypted_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.0, + "Total Cost": 12.54 + } + ], + "Startup Cost": 0.0, + "Total Cost": 6.27 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Index Scan using string_encrypted_10000000_hash_index on string_encrypted_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_10000000", + "Async Capable": false, + "Index Cond": "(((value).data ->> 'hm'::text) = 'e361bf6d2ee8c36944302cb9963da12b0e6bbdc563f5e088f8b970b7779cc2fb'::text)", + "Index Name": "string_encrypted_10000000_hash_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 8, + "Plan Width": 36, + "Relation Name": "string_encrypted_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.0, + "Total Cost": 38.14 + } + ], + "Startup Cost": 0.0, + "Total Cost": 4.77 + } + } +] +``` + +
+ +![Query Performance - EXACT/eql_hash](query_exact_eql_hash_chart.png) + diff --git a/report/v2/group_by.md b/report/v2/group_by.md new file mode 100644 index 0000000..399e136 --- /dev/null +++ b/report/v2/group_by.md @@ -0,0 +1,1616 @@ +# GROUP_BY Queries + +[← Back to overview](./BENCHMARK_REPORT.md) + +Per-tier query performance. Each scenario lists its SQL, the indexes available on the target table, the indexes the planner actually picked per tier, the timing table, and the full EXPLAIN plan in a collapsed block. + +## low_cardinality_groups_encrypted + +**Description:** Low-cardinality GROUP BY (~250 buckets) on `eql_v2.hmac_256(value)`, wrapped in `count(*)` to isolate aggregation cost from emit cost + +**SQL Query:** +```sql +SELECT count(*) FROM (SELECT 1 FROM {TABLE} GROUP BY eql_v2.hmac_256(value)) g +``` + +**Table: `category_encrypted_{rows}` with encrypted categorical values (`CAT_001`..`CAT_250`, uniform random — ~250 distinct buckets). The encrypted value carries an `hm` HMAC term via the `unique` search index. **Index: hash index on `eql_v2.hmac_256(value)`, but `GROUP BY` doesn't engage it directly** — the planner picks `HashAggregate`, building an in-memory hash table keyed on the 32-byte HMAC. With only 250 distinct keys the hash table fits comfortably in default `work_mem`. The outer `count(*)` keeps the result-set emission at exactly one row, so wall-clock time tracks aggregation cost. The companion `low_cardinality_groups_plaintext` scenario runs the same query shape against an unindexed TEXT column for a baseline.** + +**Indexes available on the table:** +```sql +CREATE INDEX +category_encrypted_10000_hash_index +ON category_encrypted_10000 using hash ( + eql_v2.hmac_256(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +*⚠️ = Query time exceeds 100ms* + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 1 | 2.21ms | N/A | +| 100,000 | 1 | 20.10ms | N/A | +| 1,000,000 | 1 | 95.95ms | N/A | +| 10,000,000 | 1 | ⚠️ 789.77ms | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Aggregate + Aggregate (Hashed) + Seq Scan on category_encrypted_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((category_encrypted_10000.value).data ->> 'hm'::text))::eql_v2.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 36, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_10000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 32, + "Relation Name": "category_encrypted_10000", + "Startup Cost": 0.0, + "Total Cost": 602.0 + } + ], + "Startup Cost": 627.0, + "Strategy": "Hashed", + "Total Cost": 630.12 + } + ], + "Startup Cost": 633.25, + "Strategy": "Plain", + "Total Cost": 633.26 + } + } +] +``` + +**100,000 rows** + +``` +Aggregate + Aggregate (Hashed) + Seq Scan on category_encrypted_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((category_encrypted_100000.value).data ->> 'hm'::text))::eql_v2.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 36, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_100000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 32, + "Relation Name": "category_encrypted_100000", + "Startup Cost": 0.0, + "Total Cost": 6066.0 + } + ], + "Startup Cost": 6316.0, + "Strategy": "Hashed", + "Total Cost": 6319.12 + } + ], + "Startup Cost": 6322.25, + "Strategy": "Plain", + "Total Cost": 6322.26 + } + } +] +``` + +**1,000,000 rows** + +``` +Aggregate + Group + Gather Merge + Sort + Aggregate (Hashed) + Seq Scan on category_encrypted_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((category_encrypted_1000000.value).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Node Type": "Group", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((category_encrypted_1000000.value).data ->> 'hm'::text))::eql_v2.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 32, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_1000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 416656, + "Plan Width": 32, + "Relation Name": "category_encrypted_1000000", + "Startup Cost": 0.0, + "Total Cost": 52840.2 + } + ], + "Startup Cost": 53881.84, + "Strategy": "Hashed", + "Total Cost": 53884.96 + } + ], + "Sort Key": [ + "((((category_encrypted_1000000.value).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Startup Cost": 53894.92, + "Total Cost": 53895.55 + } + ], + "Startup Cost": 54894.94, + "Total Cost": 54953.28, + "Workers Planned": 2 + } + ], + "Startup Cost": 54894.94, + "Total Cost": 54955.16 + } + ], + "Startup Cost": 54958.28, + "Strategy": "Plain", + "Total Cost": 54958.29 + } + } +] +``` + +**10,000,000 rows** + +``` +Aggregate + Group + Gather Merge + Sort + Aggregate (Hashed) + Seq Scan on category_encrypted_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((category_encrypted_10000000.value).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Node Type": "Group", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((category_encrypted_10000000.value).data ->> 'hm'::text))::eql_v2.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 32, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_10000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 4166822, + "Plan Width": 32, + "Relation Name": "category_encrypted_10000000", + "Startup Cost": 0.0, + "Total Cost": 528325.28 + } + ], + "Startup Cost": 538742.33, + "Strategy": "Hashed", + "Total Cost": 538745.46 + } + ], + "Sort Key": [ + "((((category_encrypted_10000000.value).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Startup Cost": 538755.41, + "Total Cost": 538756.04 + } + ], + "Startup Cost": 539755.44, + "Total Cost": 539813.77, + "Workers Planned": 2 + } + ], + "Startup Cost": 539755.44, + "Total Cost": 539815.65 + } + ], + "Startup Cost": 539818.77, + "Strategy": "Plain", + "Total Cost": 539818.78 + } + } +] +``` + +
+ +![Query Performance - GROUP_BY/low_cardinality_groups_encrypted](query_group_by_low_cardinality_groups_encrypted_chart.png) + +## low_cardinality_groups_plaintext + +**Description:** Plaintext baseline: low-cardinality GROUP BY on a plain TEXT column, same query shape as the encrypted scenario + +**SQL Query:** +```sql +SELECT count(*) FROM (SELECT 1 FROM {TABLE} GROUP BY value) g +``` + +**Table: `category_plaintext_{rows}` with the same `CAT_001`..`CAT_250` distribution (uniform random, populated by SQL via `mise run prepare:category_plaintext` — no encryption-client dependency). Index: none. The wall-clock delta between this and `low_cardinality_groups_encrypted` is the EQL recipe's overhead relative to a bare-PG aggregate at the same row count and cardinality.** + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +*⚠️ = Query time exceeds 100ms* + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 1 | 1.17ms | N/A | +| 100,000 | 1 | 9.14ms | N/A | +| 1,000,000 | 1 | 40.41ms | N/A | +| 10,000,000 | 1 | ⚠️ 341.69ms | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Aggregate + Aggregate (Hashed) + Seq Scan on category_plaintext_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "category_plaintext_10000.value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 12, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_10000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 8, + "Relation Name": "category_plaintext_10000", + "Startup Cost": 0.0, + "Total Cost": 155.0 + } + ], + "Startup Cost": 180.0, + "Strategy": "Hashed", + "Total Cost": 182.5 + } + ], + "Startup Cost": 185.62, + "Strategy": "Plain", + "Total Cost": 185.63 + } + } +] +``` + +**100,000 rows** + +``` +Aggregate + Aggregate (Hashed) + Seq Scan on category_plaintext_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "category_plaintext_100000.value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 12, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_100000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 8, + "Relation Name": "category_plaintext_100000", + "Startup Cost": 0.0, + "Total Cost": 1544.0 + } + ], + "Startup Cost": 1794.0, + "Strategy": "Hashed", + "Total Cost": 1796.5 + } + ], + "Startup Cost": 1799.62, + "Strategy": "Plain", + "Total Cost": 1799.63 + } + } +] +``` + +**1,000,000 rows** + +``` +Aggregate + Group + Gather Merge + Sort + Aggregate (Hashed) + Seq Scan on category_plaintext_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "category_plaintext_1000000.value" + ], + "Node Type": "Group", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 12, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "category_plaintext_1000000.value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 8, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_1000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 416667, + "Plan Width": 8, + "Relation Name": "category_plaintext_1000000", + "Startup Cost": 0.0, + "Total Cost": 9574.67 + } + ], + "Startup Cost": 10616.33, + "Strategy": "Hashed", + "Total Cost": 10618.83 + } + ], + "Sort Key": [ + "category_plaintext_1000000.value" + ], + "Startup Cost": 10628.79, + "Total Cost": 10629.42 + } + ], + "Startup Cost": 11628.82, + "Total Cost": 11687.15, + "Workers Planned": 2 + } + ], + "Startup Cost": 11628.82, + "Total Cost": 11688.4 + } + ], + "Startup Cost": 11691.53, + "Strategy": "Plain", + "Total Cost": 11691.54 + } + } +] +``` + +**10,000,000 rows** + +``` +Aggregate + Group + Gather Merge + Sort + Aggregate (Hashed) + Seq Scan on category_plaintext_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "category_plaintext_10000000.value" + ], + "Node Type": "Group", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 12, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "category_plaintext_10000000.value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 8, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_10000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 4166275, + "Plan Width": 8, + "Relation Name": "category_plaintext_10000000", + "Startup Cost": 0.0, + "Total Cost": 95774.75 + } + ], + "Startup Cost": 106190.43, + "Strategy": "Hashed", + "Total Cost": 106192.93 + } + ], + "Sort Key": [ + "category_plaintext_10000000.value" + ], + "Startup Cost": 106202.89, + "Total Cost": 106203.52 + } + ], + "Startup Cost": 107202.91, + "Total Cost": 107261.25, + "Workers Planned": 2 + } + ], + "Startup Cost": 107202.91, + "Total Cost": 107262.5 + } + ], + "Startup Cost": 107265.63, + "Strategy": "Plain", + "Total Cost": 107265.64 + } + } +] +``` + +
+ +![Query Performance - GROUP_BY/low_cardinality_groups_plaintext](query_group_by_low_cardinality_groups_plaintext_chart.png) + +## top_n_groups_encrypted + +**Description:** Dashboard analytic: top 10 categories by frequency, EQL recipe form + +**SQL Query:** +```sql +SELECT eql_v2.hmac_256(value), count(*) FROM {TABLE} GROUP BY 1 ORDER BY count(*) DESC LIMIT 10 +``` + +**Table: `category_encrypted_{rows}` (same data as the `low_cardinality_*` scenarios above). Query: `SELECT eql_v2.hmac_256(value), count(*) FROM tbl GROUP BY 1 ORDER BY count(*) DESC LIMIT 10`. The bench always emits 10 rows regardless of input size, so the cost is dominated by the inner HashAggregate (per-row HMAC + hash-table insert) plus a tiny sort over the 250 group entries. Realistic shape for analytics queries that surface the most common categories in an encrypted dataset.** + +**Indexes available on the table:** +```sql +CREATE INDEX +category_encrypted_10000_hash_index +ON category_encrypted_10000 using hash ( + eql_v2.hmac_256(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +*⚠️ = Query time exceeds 100ms* + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 2.53ms | N/A | +| 100,000 | 10 | 20.28ms | N/A | +| 1,000,000 | 10 | 92.97ms | N/A | +| 10,000,000 | 10 | ⚠️ 815.42ms | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Sort + Aggregate (Hashed) + Seq Scan on category_encrypted_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((value).data ->> 'hm'::text))::eql_v2.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 40, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_10000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 32, + "Relation Name": "category_encrypted_10000", + "Startup Cost": 0.0, + "Total Cost": 602.0 + } + ], + "Startup Cost": 652.0, + "Strategy": "Hashed", + "Total Cost": 655.12 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 660.53, + "Total Cost": 661.15 + } + ], + "Startup Cost": 660.53, + "Total Cost": 660.55 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Sort + Aggregate (Hashed) + Seq Scan on category_encrypted_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((value).data ->> 'hm'::text))::eql_v2.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 40, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_100000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 32, + "Relation Name": "category_encrypted_100000", + "Startup Cost": 0.0, + "Total Cost": 6066.0 + } + ], + "Startup Cost": 6566.0, + "Strategy": "Hashed", + "Total Cost": 6569.12 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 6574.53, + "Total Cost": 6575.15 + } + ], + "Startup Cost": 6574.53, + "Total Cost": 6574.55 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Sort + Aggregate (Sorted) + Gather Merge + Sort + Aggregate (Hashed) + Seq Scan on category_encrypted_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((value).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Finalize", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((value).data ->> 'hm'::text))::eql_v2.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 40, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_1000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 416656, + "Plan Width": 32, + "Relation Name": "category_encrypted_1000000", + "Startup Cost": 0.0, + "Total Cost": 52840.2 + } + ], + "Startup Cost": 54923.48, + "Strategy": "Hashed", + "Total Cost": 54926.6 + } + ], + "Sort Key": [ + "((((value).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Startup Cost": 54936.56, + "Total Cost": 54937.19 + } + ], + "Startup Cost": 55936.58, + "Total Cost": 55994.92, + "Workers Planned": 2 + } + ], + "Startup Cost": 55936.58, + "Strategy": "Sorted", + "Total Cost": 56000.55 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 56005.95, + "Total Cost": 56006.57 + } + ], + "Startup Cost": 56005.95, + "Total Cost": 56005.97 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Sort + Aggregate (Sorted) + Gather Merge + Sort + Aggregate (Hashed) + Seq Scan on category_encrypted_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((value).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Finalize", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((value).data ->> 'hm'::text))::eql_v2.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 40, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_10000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 4166822, + "Plan Width": 32, + "Relation Name": "category_encrypted_10000000", + "Startup Cost": 0.0, + "Total Cost": 528325.28 + } + ], + "Startup Cost": 549159.39, + "Strategy": "Hashed", + "Total Cost": 549162.51 + } + ], + "Sort Key": [ + "((((value).data ->> 'hm'::text))::eql_v2.hmac_256)" + ], + "Startup Cost": 549172.47, + "Total Cost": 549173.09 + } + ], + "Startup Cost": 550172.49, + "Total Cost": 550230.83, + "Workers Planned": 2 + } + ], + "Startup Cost": 550172.49, + "Strategy": "Sorted", + "Total Cost": 550236.45 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 550241.86, + "Total Cost": 550242.48 + } + ], + "Startup Cost": 550241.86, + "Total Cost": 550241.88 + } + } +] +``` + +
+ +![Query Performance - GROUP_BY/top_n_groups_encrypted](query_group_by_top_n_groups_encrypted_chart.png) + +## top_n_groups_plaintext + +**Description:** Plaintext baseline: top 10 categories by frequency on a plain TEXT column + +**SQL Query:** +```sql +SELECT value, count(*) FROM {TABLE} GROUP BY 1 ORDER BY count(*) DESC LIMIT 10 +``` + +**Table: `category_plaintext_{rows}`. Same query shape as the encrypted top-N scenario; the delta is the EQL recipe's overhead for the same shape on the same cardinality data.** + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +*⚠️ = Query time exceeds 100ms* + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 1.20ms | N/A | +| 100,000 | 10 | 9.52ms | N/A | +| 1,000,000 | 10 | 40.21ms | N/A | +| 10,000,000 | 10 | ⚠️ 350.21ms | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Sort + Aggregate (Hashed) + Seq Scan on category_plaintext_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 16, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_10000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 8, + "Relation Name": "category_plaintext_10000", + "Startup Cost": 0.0, + "Total Cost": 155.0 + } + ], + "Startup Cost": 205.0, + "Strategy": "Hashed", + "Total Cost": 207.5 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 212.9, + "Total Cost": 213.53 + } + ], + "Startup Cost": 212.9, + "Total Cost": 212.93 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Sort + Aggregate (Hashed) + Seq Scan on category_plaintext_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 16, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_100000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 8, + "Relation Name": "category_plaintext_100000", + "Startup Cost": 0.0, + "Total Cost": 1544.0 + } + ], + "Startup Cost": 2044.0, + "Strategy": "Hashed", + "Total Cost": 2046.5 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 2051.9, + "Total Cost": 2052.53 + } + ], + "Startup Cost": 2051.9, + "Total Cost": 2051.93 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Sort + Aggregate (Sorted) + Gather Merge + Sort + Aggregate (Hashed) + Seq Scan on category_plaintext_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Finalize", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 16, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_1000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 416667, + "Plan Width": 8, + "Relation Name": "category_plaintext_1000000", + "Startup Cost": 0.0, + "Total Cost": 9574.67 + } + ], + "Startup Cost": 11658.0, + "Strategy": "Hashed", + "Total Cost": 11660.5 + } + ], + "Sort Key": [ + "value" + ], + "Startup Cost": 11670.46, + "Total Cost": 11671.08 + } + ], + "Startup Cost": 12670.48, + "Total Cost": 12728.82, + "Workers Planned": 2 + } + ], + "Startup Cost": 12670.48, + "Strategy": "Sorted", + "Total Cost": 12733.82 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 12739.22, + "Total Cost": 12739.85 + } + ], + "Startup Cost": 12739.22, + "Total Cost": 12739.25 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Sort + Aggregate (Sorted) + Gather Merge + Sort + Aggregate (Hashed) + Seq Scan on category_plaintext_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Finalize", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 16, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_10000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 4166275, + "Plan Width": 8, + "Relation Name": "category_plaintext_10000000", + "Startup Cost": 0.0, + "Total Cost": 95774.75 + } + ], + "Startup Cost": 116606.12, + "Strategy": "Hashed", + "Total Cost": 116608.62 + } + ], + "Sort Key": [ + "value" + ], + "Startup Cost": 116618.58, + "Total Cost": 116619.2 + } + ], + "Startup Cost": 117618.6, + "Total Cost": 117676.94, + "Workers Planned": 2 + } + ], + "Startup Cost": 117618.6, + "Strategy": "Sorted", + "Total Cost": 117681.94 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 117687.34, + "Total Cost": 117687.97 + } + ], + "Startup Cost": 117687.34, + "Total Cost": 117687.37 + } + } +] +``` + +
+ +![Query Performance - GROUP_BY/top_n_groups_plaintext](query_group_by_top_n_groups_plaintext_chart.png) + diff --git a/report/v2/ingest_comparison_throughput_10000.png b/report/v2/ingest_comparison_throughput_10000.png new file mode 100644 index 0000000..dc4ce53 Binary files /dev/null and b/report/v2/ingest_comparison_throughput_10000.png differ diff --git a/report/v2/ingest_comparison_time_10000.png b/report/v2/ingest_comparison_time_10000.png new file mode 100644 index 0000000..ea0b2a0 Binary files /dev/null and b/report/v2/ingest_comparison_time_10000.png differ diff --git a/report/v2/ingest_comparison_time_10000_filtered.png b/report/v2/ingest_comparison_time_10000_filtered.png new file mode 100644 index 0000000..d9387fc Binary files /dev/null and b/report/v2/ingest_comparison_time_10000_filtered.png differ diff --git a/report/v2/ingest_int_throughput_chart.png b/report/v2/ingest_int_throughput_chart.png new file mode 100644 index 0000000..c80d1c6 Binary files /dev/null and b/report/v2/ingest_int_throughput_chart.png differ diff --git a/report/v2/ingest_int_time_chart.png b/report/v2/ingest_int_time_chart.png new file mode 100644 index 0000000..ef9a807 Binary files /dev/null and b/report/v2/ingest_int_time_chart.png differ diff --git a/report/ingest_json_large_throughput_chart.png b/report/v2/ingest_json_large_throughput_chart.png similarity index 100% rename from report/ingest_json_large_throughput_chart.png rename to report/v2/ingest_json_large_throughput_chart.png diff --git a/report/ingest_json_large_time_chart.png b/report/v2/ingest_json_large_time_chart.png similarity index 100% rename from report/ingest_json_large_time_chart.png rename to report/v2/ingest_json_large_time_chart.png diff --git a/report/ingest_json_small_throughput_chart.png b/report/v2/ingest_json_small_throughput_chart.png similarity index 100% rename from report/ingest_json_small_throughput_chart.png rename to report/v2/ingest_json_small_throughput_chart.png diff --git a/report/ingest_json_small_time_chart.png b/report/v2/ingest_json_small_time_chart.png similarity index 100% rename from report/ingest_json_small_time_chart.png rename to report/v2/ingest_json_small_time_chart.png diff --git a/report/v2/ingest_ste_vec_small_throughput_chart.png b/report/v2/ingest_ste_vec_small_throughput_chart.png new file mode 100644 index 0000000..b7db65a Binary files /dev/null and b/report/v2/ingest_ste_vec_small_throughput_chart.png differ diff --git a/report/v2/ingest_ste_vec_small_time_chart.png b/report/v2/ingest_ste_vec_small_time_chart.png new file mode 100644 index 0000000..5b755ec Binary files /dev/null and b/report/v2/ingest_ste_vec_small_time_chart.png differ diff --git a/report/v2/ingest_string_throughput_chart.png b/report/v2/ingest_string_throughput_chart.png new file mode 100644 index 0000000..fc25858 Binary files /dev/null and b/report/v2/ingest_string_throughput_chart.png differ diff --git a/report/v2/ingest_string_time_chart.png b/report/v2/ingest_string_time_chart.png new file mode 100644 index 0000000..94193ff Binary files /dev/null and b/report/v2/ingest_string_time_chart.png differ diff --git a/report/v2/json.md b/report/v2/json.md new file mode 100644 index 0000000..9f30674 --- /dev/null +++ b/report/v2/json.md @@ -0,0 +1,1205 @@ +# JSON Queries + +[← Back to overview](./BENCHMARK_REPORT.md) + +Per-tier query performance. Each scenario lists its SQL, the indexes available on the target table, the indexes the planner actually picked per tier, the timing table, and the full EXPLAIN plan in a collapsed block. + +## contains/functional + +**Description:** Whole-document JSON containment via `ste_vec(...) @> ste_vec(...)` + +**SQL Query:** +```sql +SELECT id FROM {TABLE} WHERE eql_v2.ste_vec(value) @> eql_v2.ste_vec($1::jsonb::eql_v2_encrypted) LIMIT 10 +``` + +**Parameter:** `` + +**Table: `json_ste_vec_small_encrypted_{rows}` with encrypted JSON documents (small four-field shape — first_name / last_name / age / email). Index: functional GIN on `eql_v2.ste_vec(value)`. Both sides of `@>` resolve to `eql_v2_encrypted[]`, which matches the GIN opclass directly. The needle is a sampled row's value, so the query matches at least that source row. + +Note: the bare form `WHERE value @> $1::eql_v2_encrypted` does NOT engage the GIN today. `eql_v2."@>"` is marked inlinable SQL but wraps `ste_vec_contains()` which is PL/pgSQL — inlining stops at the wrapper, leaving the planner with a black-box function call and no path to the indexed expression. The bench omits the bare form because it would not complete at the 1M / 10M tiers.** + +**Indexes available on the table:** +```sql +-- EQL 2.3 functional GIN indexes for the json ste_vec bench. +-- +-- jsonb_array — whole-document containment (contains/functional): +-- eql_v2.jsonb_array(value) @> eql_v2.jsonb_array($1). +-- stevec_query — typed field-level containment (field_eq/extractor): +-- value @> $1::eql_v2.stevec_query inlines to a native +-- jsonb @> over eql_v2.to_stevec_query(value)::jsonb. +-- XOR-aware: one index covers hm- and oc-bearing selectors. +-- +-- Replaces the pre-2.3 eql_v2.ste_vec / eql_v2.hmac_256_terms GIN indexes +-- (hmac_256_terms was removed in EQL 2.3 — see cipherstash/eql#223). + +CREATE INDEX +json_ste_vec_small_encrypted_10000_jsonb_array_index +ON json_ste_vec_small_encrypted_10000 USING GIN ( + eql_v2.jsonb_array(value) +); + +CREATE INDEX +json_ste_vec_small_encrypted_10000_stevec_query_index +ON json_ste_vec_small_encrypted_10000 USING GIN ( + (eql_v2.to_stevec_query(value)::jsonb) jsonb_path_ops +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: `json_ste_vec_small_encrypted_10000_jsonb_array_index` +- 100,000: `json_ste_vec_small_encrypted_100000_jsonb_array_index` +- 1,000,000: `json_ste_vec_small_encrypted_1000000_jsonb_array_index` +- 10,000,000: `json_ste_vec_small_encrypted_10000000_jsonb_array_index` + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 1 | 238.33μs | N/A | +| 100,000 | 1 | 287.01μs | N/A | +| 1,000,000 | 1 | 433.92μs | N/A | +| 10,000,000 | 1 | 853.79μs | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Bitmap Heap Scan on json_ste_vec_small_encrypted_10000 + Bitmap Index Scan using json_ste_vec_small_encrypted_10000_jsonb_array_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db49711c282c9945019a0d5d828669b07666c22835fea10dec1a7c1b6a6f19643526e9fc2f711acceb0290e4deab64aa2b340c662c9\\\"}\",\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db5d403405be41b6282af7f22db8d658eb80dd800b412c08aa4b2cc3a75b9f4ce55d3df3c2335e40f7e45297ada\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e403ea3be1fea72fbc01ec952a09371fc9612b428b7ded13cecfef3b2cd8fcf7cb40c4b548f4c91d187ad027907127860abcc58b92b1670f85e5178cfeda25766f3f6de0327c7813de3e52dbd36b43d96e847acf1153f5e023bdff8fdff1a784fd2a8f33ddb78b3849e8e5372a2519a2e3ac83c226bbd0643ee330d80e925bfe30c189b749ee761281403e3e9332f03f5c731be4a94c42f14eedd5afde4f40601554d424a5a\\\"}\",\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0984d4957290b0eb89f172928170998bc114ac343a673440e682d03234d35c039ae0ba9a5bba6f3901e018ba8c10f88db4cfa3e37e6357\\\"}\"}'::jsonb[])", + "Index Name": "json_ste_vec_small_encrypted_10000_jsonb_array_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 68.86 + } + ], + "Recheck Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db49711c282c9945019a0d5d828669b07666c22835fea10dec1a7c1b6a6f19643526e9fc2f711acceb0290e4deab64aa2b340c662c9\\\"}\",\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db5d403405be41b6282af7f22db8d658eb80dd800b412c08aa4b2cc3a75b9f4ce55d3df3c2335e40f7e45297ada\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e403ea3be1fea72fbc01ec952a09371fc9612b428b7ded13cecfef3b2cd8fcf7cb40c4b548f4c91d187ad027907127860abcc58b92b1670f85e5178cfeda25766f3f6de0327c7813de3e52dbd36b43d96e847acf1153f5e023bdff8fdff1a784fd2a8f33ddb78b3849e8e5372a2519a2e3ac83c226bbd0643ee330d80e925bfe30c189b749ee761281403e3e9332f03f5c731be4a94c42f14eedd5afde4f40601554d424a5a\\\"}\",\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0984d4957290b0eb89f172928170998bc114ac343a673440e682d03234d35c039ae0ba9a5bba6f3901e018ba8c10f88db4cfa3e37e6357\\\"}\"}'::jsonb[])", + "Relation Name": "json_ste_vec_small_encrypted_10000", + "Startup Cost": 68.86, + "Total Cost": 73.13 + } + ], + "Startup Cost": 68.86, + "Total Cost": 73.13 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Bitmap Heap Scan on json_ste_vec_small_encrypted_100000 + Bitmap Index Scan using json_ste_vec_small_encrypted_100000_jsonb_array_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_100000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db4971212d5f2ebe58b72e7b8fa9d528196612fc962cd5f14cc85a882d495c5b8ceb74335081e41aebe9001cefa\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e403ea40004cb28aaac8579a40c9c68653f7a1c8d9218ad7259f4c37e28164a5a9f1db7ecb4dea34907606105b4452af42e910a89810c847757038d7ebf79c9a6872a60a39e10541852a9e017fe49d2cf3ec12edbb2421f0d9b4f528de812be40d57dd4943c3a26424f3fec93108c779a185f6fa2ffe1f2d0e2140cb54042b17262a629b52ceca7af4d8f8c9aed1d963e206c1665b0e991d8a6e0fa9ce055393f253aae9a3d4deb0c90f023b5010edb624f036e23c373a974fdd10f0664040cdbf9692db261\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0a3129231c38a147def14a10589ac6578debca348aa74b3bc9d81b55e6679aafb3f791a0549e371ad4d1a962a1c24fcd3c33beaf6012e9\\\"}\",\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db49711c141b2cd54aca1d3dc8a37a02a141772209033e93fe56b3ef7bce24c1636c1edc48440f71a57f084f0498568a3af3e15f7fe\\\"}\"}'::jsonb[])", + "Index Name": "json_ste_vec_small_encrypted_100000_jsonb_array_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 90.19 + } + ], + "Recheck Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db4971212d5f2ebe58b72e7b8fa9d528196612fc962cd5f14cc85a882d495c5b8ceb74335081e41aebe9001cefa\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e403ea40004cb28aaac8579a40c9c68653f7a1c8d9218ad7259f4c37e28164a5a9f1db7ecb4dea34907606105b4452af42e910a89810c847757038d7ebf79c9a6872a60a39e10541852a9e017fe49d2cf3ec12edbb2421f0d9b4f528de812be40d57dd4943c3a26424f3fec93108c779a185f6fa2ffe1f2d0e2140cb54042b17262a629b52ceca7af4d8f8c9aed1d963e206c1665b0e991d8a6e0fa9ce055393f253aae9a3d4deb0c90f023b5010edb624f036e23c373a974fdd10f0664040cdbf9692db261\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0a3129231c38a147def14a10589ac6578debca348aa74b3bc9d81b55e6679aafb3f791a0549e371ad4d1a962a1c24fcd3c33beaf6012e9\\\"}\",\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db49711c141b2cd54aca1d3dc8a37a02a141772209033e93fe56b3ef7bce24c1636c1edc48440f71a57f084f0498568a3af3e15f7fe\\\"}\"}'::jsonb[])", + "Relation Name": "json_ste_vec_small_encrypted_100000", + "Startup Cost": 90.19, + "Total Cost": 94.45 + } + ], + "Startup Cost": 90.19, + "Total Cost": 94.45 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Bitmap Heap Scan on json_ste_vec_small_encrypted_1000000 + Bitmap Index Scan using json_ste_vec_small_encrypted_1000000_jsonb_array_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_1000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db5d4045f7eae249da635745e1a5e6691a7feb66fed367ce633d7792fef78397cb5ba02b5c0da766c5ace2e9b3c\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e403ea40004cb28aaac8579a40c9c68653f7a1c8d93be87493ade620ca595abd48e66e220c9e30c77842a002a700b059d4d59250090b87f4a38fa321bf852c5d7458ab0d670443ebf9a445e27bfe098819e341e0c431b2b50e889d713e682b1937939d1370f0dd64421ea3610fae0a279833dc61c14ef788dffca9f26246050d98430966dac692632292260560226b1ea6cec1e2f57a80fe979f14c65bf9dd364449f136ba3\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0984d495716bf9ae2c0a31447b038fd5bd56472d846a1a2cb71a3b9f5436ef8fc2c6c25c58e2e9e6fc05934730282d950e9b98d221f899\\\"}\",\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db4984a02b345757574904a5f1c307b11290aaa1b1b4542856950ff97176a23e23b1ca676713a1a2384ea826486\\\"}\"}'::jsonb[])", + "Index Name": "json_ste_vec_small_encrypted_1000000_jsonb_array_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 111.51 + } + ], + "Recheck Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db5d4045f7eae249da635745e1a5e6691a7feb66fed367ce633d7792fef78397cb5ba02b5c0da766c5ace2e9b3c\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e403ea40004cb28aaac8579a40c9c68653f7a1c8d93be87493ade620ca595abd48e66e220c9e30c77842a002a700b059d4d59250090b87f4a38fa321bf852c5d7458ab0d670443ebf9a445e27bfe098819e341e0c431b2b50e889d713e682b1937939d1370f0dd64421ea3610fae0a279833dc61c14ef788dffca9f26246050d98430966dac692632292260560226b1ea6cec1e2f57a80fe979f14c65bf9dd364449f136ba3\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0984d495716bf9ae2c0a31447b038fd5bd56472d846a1a2cb71a3b9f5436ef8fc2c6c25c58e2e9e6fc05934730282d950e9b98d221f899\\\"}\",\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db4984a02b345757574904a5f1c307b11290aaa1b1b4542856950ff97176a23e23b1ca676713a1a2384ea826486\\\"}\"}'::jsonb[])", + "Relation Name": "json_ste_vec_small_encrypted_1000000", + "Startup Cost": 111.51, + "Total Cost": 115.78 + } + ], + "Startup Cost": 111.51, + "Total Cost": 115.78 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Bitmap Heap Scan on json_ste_vec_small_encrypted_10000000 + Bitmap Index Scan using json_ste_vec_small_encrypted_10000000_jsonb_array_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_10000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e4113e9f962fbe6fe249a5de0f12ba7ed560c524ef29c96018408b83c94c4c76ef043485fdb4c0d3dbe1c73986f14fea459d4976516c1b96cdd3820f5b5f9a3517a94cf901aea6edf910824dc75cb38166bc34693f784dde67958dbda26a643bbca03014b39e7d2aef06e009af176dccb11c27947e4ff7f9394632439395b3c101d8e8c721c6c5600da3d64a9aeea4520829440901344c2377277039617\\\"}\",\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db4971212d687dc77e2922544be2e3a767b9e6e92cae4e7f344ae9bf59a6986cfacd75f6cd0867c19ad4280b0919b6a3e929b02cd6ddf62d400008e47943e3d6fcb89d5046e32912438f622e77d\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0984d494d6304819280964b36414fc29e4ea7f18c10a0b42d088191c96642d1a2434e91c0d4dcb0fa2fd386a20f67a128a29dc864feec2\\\"}\",\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db49711c282c9945019a194351fb299f75ed665afb97d57ea0658a61a53b755e69da35ab919\\\"}\"}'::jsonb[])", + "Index Name": "json_ste_vec_small_encrypted_10000000_jsonb_array_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 132.79 + } + ], + "Recheck Cond": "(eql_v2.jsonb_array(value) @> '{\"{\\\"s\\\": \\\"cfef1685f0e51a1fe1da955e7ad10044\\\", \\\"hm\\\": \\\"fb73e0f40bc991cf4b1090d0801f6447\\\"}\",\"{\\\"s\\\": \\\"0342d803ea283195499ef8b163ee9a3f\\\", \\\"oc\\\": \\\"8d5c371e4113e9f962fbe6fe249a5de0f12ba7ed560c524ef29c96018408b83c94c4c76ef043485fdb4c0d3dbe1c73986f14fea459d4976516c1b96cdd3820f5b5f9a3517a94cf901aea6edf910824dc75cb38166bc34693f784dde67958dbda26a643bbca03014b39e7d2aef06e009af176dccb11c27947e4ff7f9394632439395b3c101d8e8c721c6c5600da3d64a9aeea4520829440901344c2377277039617\\\"}\",\"{\\\"s\\\": \\\"2bab9d9c2aa600f519eb82a8ac3b7cdb\\\", \\\"oc\\\": \\\"8d5c371db4971212d687dc77e2922544be2e3a767b9e6e92cae4e7f344ae9bf59a6986cfacd75f6cd0867c19ad4280b0919b6a3e929b02cd6ddf62d400008e47943e3d6fcb89d5046e32912438f622e77d\\\"}\",\"{\\\"s\\\": \\\"9a2d817b8ec7abe623a1fcb4d9681003\\\", \\\"oc\\\": \\\"8c01e097b7b04c9c7bfc0984d494d6304819280964b36414fc29e4ea7f18c10a0b42d088191c96642d1a2434e91c0d4dcb0fa2fd386a20f67a128a29dc864feec2\\\"}\",\"{\\\"s\\\": \\\"746e042de28c05e98d1ff821a43d52b5\\\", \\\"oc\\\": \\\"8d5c371db49711c282c9945019a194351fb299f75ed665afb97d57ea0658a61a53b755e69da35ab919\\\"}\"}'::jsonb[])", + "Relation Name": "json_ste_vec_small_encrypted_10000000", + "Startup Cost": 132.79, + "Total Cost": 137.05 + } + ], + "Startup Cost": 132.79, + "Total Cost": 137.05 + } + } +] +``` + +
+ +![Query Performance - JSON/contains/functional](query_json_contains_functional_chart.png) + +## field_eq/bare + +**Description:** Field-level equality via `value -> 'sel' = $1::eql_v2_encrypted` (no index) + +**SQL Query:** +```sql +SELECT id FROM {TABLE} WHERE (value -> ''::text) = $1::jsonb::eql_v2_encrypted LIMIT 10 +``` + +**Parameter:** `` + +**Table: `json_ste_vec_small_encrypted_{rows}`. `eql_v2."->"` is plpgsql (not inlinable), so the planner cannot match any functional index against the LHS — forces Seq Scan + per-row sv walk. This is the natural form a JS/ORM caller would write; the bench includes it to show the cost of *not* having an inlinable extractor on `->`.** + +**Indexes available on the table:** +```sql +-- EQL 2.3 functional GIN indexes for the json ste_vec bench. +-- +-- jsonb_array — whole-document containment (contains/functional): +-- eql_v2.jsonb_array(value) @> eql_v2.jsonb_array($1). +-- stevec_query — typed field-level containment (field_eq/extractor): +-- value @> $1::eql_v2.stevec_query inlines to a native +-- jsonb @> over eql_v2.to_stevec_query(value)::jsonb. +-- XOR-aware: one index covers hm- and oc-bearing selectors. +-- +-- Replaces the pre-2.3 eql_v2.ste_vec / eql_v2.hmac_256_terms GIN indexes +-- (hmac_256_terms was removed in EQL 2.3 — see cipherstash/eql#223). + +CREATE INDEX +json_ste_vec_small_encrypted_10000_jsonb_array_index +ON json_ste_vec_small_encrypted_10000 USING GIN ( + eql_v2.jsonb_array(value) +); + +CREATE INDEX +json_ste_vec_small_encrypted_10000_stevec_query_index +ON json_ste_vec_small_encrypted_10000 USING GIN ( + (eql_v2.to_stevec_query(value)::jsonb) jsonb_path_ops +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: `json_ste_vec_small_encrypted_10000_field_eq_idx` +- 100,000: `json_ste_vec_small_encrypted_100000_field_eq_idx` +- 1,000,000: `json_ste_vec_small_encrypted_1000000_field_eq_idx` +- 10,000,000: `json_ste_vec_small_encrypted_10000000_field_eq_idx` + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 109.04μs | N/A | +| 100,000 | 10 | 106.46μs | N/A | +| 1,000,000 | 10 | 99.38μs | N/A | +| 10,000,000 | 10 | 109.18μs | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Index Scan using json_ste_vec_small_encrypted_10000_field_eq_idx on json_ste_vec_small_encrypted_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_10000", + "Async Capable": false, + "Index Cond": "(eql_v2.eq_term((value -> 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbLP(i?F+N4}@Yd7+CEvBh%4WvWGA-Clm>I7>+FpI2@T`6kjE%$~vnW*H{GSQRxTsN%B(Hto#H*A)ql=&pvnJm04OwTPpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_10000\"}, \"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"v\": 2, \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}'::jsonb)::eql_v2.ste_vec_entry))", + "Index Name": "json_ste_vec_small_encrypted_10000_field_eq_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.54, + "Total Cost": 2046.54 + } + ], + "Startup Cost": 0.54, + "Total Cost": 2.58 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Index Scan using json_ste_vec_small_encrypted_100000_field_eq_idx on json_ste_vec_small_encrypted_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_100000", + "Async Capable": false, + "Index Cond": "(eql_v2.eq_term((value -> 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbJ#Az`rN2!?|a+B*-Bmmq?~X$Xb;T3=`{)vYGWIVl1O4v-;wGe0L(${xlw#6&~c2+OgUrj#oFGkUC;JCyf+BZwxob;Y*Mape$W+(md@rfSN5Ye@09b#rnIlsO#puh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_100000\"}, \"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"v\": 2, \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}'::jsonb)::eql_v2.ste_vec_entry))", + "Index Name": "json_ste_vec_small_encrypted_100000_field_eq_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.54, + "Total Cost": 19741.54 + } + ], + "Startup Cost": 0.54, + "Total Cost": 2.52 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Index Scan using json_ste_vec_small_encrypted_1000000_field_eq_idx on json_ste_vec_small_encrypted_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_1000000", + "Async Capable": false, + "Index Cond": "(eql_v2.eq_term((value -> 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbJeS~GW(rh_Ip#L(=Tk4TQhWW<9ljWmSq7yFQK{3){*^3mrvZVb*R$1K>{#a~UP>9qrQVA&6A(*plc?p!)G6K6VxXRF-Ao<%8ZuHeK?nJ3--0Nm!1=ln2Xui4i>S)gYG;I(F^bd2`!ND6isp!LMOUBn>CRQ!LHS7`%z%ZEdL=*l4D?dx-| 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbJLhWn-J_XuAF@lJV1yj2RsWY00Q2F%S?!W`})*vltb>7kZ*|BK4On8t^sSE)U-JiRV)L + +![Query Performance - JSON/field_eq/bare](query_json_field_eq_bare_chart.png) + +## field_eq/extractor + +**Description:** Field-level equality via `hmac_256_terms @> [{s,hm}]` (functional GIN) + +**SQL Query:** +```sql +SELECT id FROM {TABLE} WHERE eql_v2.hmac_256_terms(value) @> $1::jsonb LIMIT 10 +``` + +**Parameter:** `[{"s":"","hm":""}]` + +**Table: `json_ste_vec_small_encrypted_{rows}`. Index: functional GIN on `eql_v2.hmac_256_terms(value)`. One index covers field-level equality across every selector that carries `hm`, vs the per-selector recipe below. The bench picks a (selector, hmac) pair from `sv[0]` of a sample row at startup; needle is `[{"s":"","hm":""}]`.** + +**Indexes available on the table:** +```sql +-- EQL 2.3 functional GIN indexes for the json ste_vec bench. +-- +-- jsonb_array — whole-document containment (contains/functional): +-- eql_v2.jsonb_array(value) @> eql_v2.jsonb_array($1). +-- stevec_query — typed field-level containment (field_eq/extractor): +-- value @> $1::eql_v2.stevec_query inlines to a native +-- jsonb @> over eql_v2.to_stevec_query(value)::jsonb. +-- XOR-aware: one index covers hm- and oc-bearing selectors. +-- +-- Replaces the pre-2.3 eql_v2.ste_vec / eql_v2.hmac_256_terms GIN indexes +-- (hmac_256_terms was removed in EQL 2.3 — see cipherstash/eql#223). + +CREATE INDEX +json_ste_vec_small_encrypted_10000_jsonb_array_index +ON json_ste_vec_small_encrypted_10000 USING GIN ( + eql_v2.jsonb_array(value) +); + +CREATE INDEX +json_ste_vec_small_encrypted_10000_stevec_query_index +ON json_ste_vec_small_encrypted_10000 USING GIN ( + (eql_v2.to_stevec_query(value)::jsonb) jsonb_path_ops +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 506.68μs | N/A | +| 100,000 | 10 | 477.53μs | N/A | +| 1,000,000 | 10 | 465.99μs | N/A | +| 10,000,000 | 10 | 432.23μs | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Seq Scan on json_ste_vec_small_encrypted_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_10000", + "Async Capable": false, + "Filter": "((eql_v2.to_stevec_query(value))::jsonb @> (('{\"sv\": [{\"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}]}'::jsonb)::eql_v2.stevec_query)::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 9999, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_10000", + "Startup Cost": 0.0, + "Total Cost": 4474.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 4.47 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Seq Scan on json_ste_vec_small_encrypted_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_100000", + "Async Capable": false, + "Filter": "((eql_v2.to_stevec_query(value))::jsonb @> (('{\"sv\": [{\"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}]}'::jsonb)::eql_v2.stevec_query)::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 99990, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_100000", + "Startup Cost": 0.0, + "Total Cost": 44132.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 4.41 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Seq Scan on json_ste_vec_small_encrypted_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_1000000", + "Async Capable": false, + "Filter": "((eql_v2.to_stevec_query(value))::jsonb @> (('{\"sv\": [{\"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}]}'::jsonb)::eql_v2.stevec_query)::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1002304, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_1000000", + "Startup Cost": 0.0, + "Total Cost": 432237.06 + } + ], + "Startup Cost": 0.0, + "Total Cost": 4.31 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Seq Scan on json_ste_vec_small_encrypted_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_10000000", + "Async Capable": false, + "Filter": "((eql_v2.to_stevec_query(value))::jsonb @> (('{\"sv\": [{\"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}]}'::jsonb)::eql_v2.stevec_query)::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 9985164, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_10000000", + "Startup Cost": 0.0, + "Total Cost": 4313101.2 + } + ], + "Startup Cost": 0.0, + "Total Cost": 4.32 + } + } +] +``` + +
+ +![Query Performance - JSON/field_eq/extractor](query_json_field_eq_extractor_chart.png) + +## field_eq/functional + +**Description:** Field-level equality via per-selector `hmac_256(col, 'sel')` + +**SQL Query:** +```sql +SELECT id FROM {TABLE} WHERE eql_v2.hmac_256(value, '') = eql_v2.hmac_256($1::eql_v2_encrypted) LIMIT 10 +``` + +**Parameter:** `` + +**Table: `json_ste_vec_small_encrypted_{rows}`. Would engage `hash (eql_v2.hmac_256(col, ''))` if one existed; benches/main only creates the `hmac_256_terms` GIN (one index for all selectors), so this scenario serves as a baseline showing the cost of the per-selector recipe without a matching index.** + +**Indexes available on the table:** +```sql +-- EQL 2.3 functional GIN indexes for the json ste_vec bench. +-- +-- jsonb_array — whole-document containment (contains/functional): +-- eql_v2.jsonb_array(value) @> eql_v2.jsonb_array($1). +-- stevec_query — typed field-level containment (field_eq/extractor): +-- value @> $1::eql_v2.stevec_query inlines to a native +-- jsonb @> over eql_v2.to_stevec_query(value)::jsonb. +-- XOR-aware: one index covers hm- and oc-bearing selectors. +-- +-- Replaces the pre-2.3 eql_v2.ste_vec / eql_v2.hmac_256_terms GIN indexes +-- (hmac_256_terms was removed in EQL 2.3 — see cipherstash/eql#223). + +CREATE INDEX +json_ste_vec_small_encrypted_10000_jsonb_array_index +ON json_ste_vec_small_encrypted_10000 USING GIN ( + eql_v2.jsonb_array(value) +); + +CREATE INDEX +json_ste_vec_small_encrypted_10000_stevec_query_index +ON json_ste_vec_small_encrypted_10000 USING GIN ( + (eql_v2.to_stevec_query(value)::jsonb) jsonb_path_ops +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: `json_ste_vec_small_encrypted_10000_field_eq_idx` +- 100,000: `json_ste_vec_small_encrypted_100000_field_eq_idx` +- 1,000,000: `json_ste_vec_small_encrypted_1000000_field_eq_idx` +- 10,000,000: `json_ste_vec_small_encrypted_10000000_field_eq_idx` + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 105.03μs | N/A | +| 100,000 | 10 | 102.71μs | N/A | +| 1,000,000 | 10 | 103.47μs | N/A | +| 10,000,000 | 10 | 106.50μs | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Index Scan using json_ste_vec_small_encrypted_10000_field_eq_idx on json_ste_vec_small_encrypted_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_10000", + "Async Capable": false, + "Index Cond": "(eql_v2.eq_term((value -> 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbLP(i?F+N4}@Yd7+CEvBh%4WvWGA-Clm>I7>+FpI2@T`6kjE%$~vnW*H{GSQRxTsN%B(Hto#H*A)ql=&pvnJm04OwTPpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_10000\"}, \"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"v\": 2, \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}'::jsonb)::eql_v2.ste_vec_entry))", + "Index Name": "json_ste_vec_small_encrypted_10000_field_eq_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.54, + "Total Cost": 2046.54 + } + ], + "Startup Cost": 0.54, + "Total Cost": 2.58 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Index Scan using json_ste_vec_small_encrypted_100000_field_eq_idx on json_ste_vec_small_encrypted_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_100000", + "Async Capable": false, + "Index Cond": "(eql_v2.eq_term((value -> 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbJ#Az`rN2!?|a+B*-Bmmq?~X$Xb;T3=`{)vYGWIVl1O4v-;wGe0L(${xlw#6&~c2+OgUrj#oFGkUC;JCyf+BZwxob;Y*Mape$W+(md@rfSN5Ye@09b#rnIlsO#puh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_100000\"}, \"s\": \"cfef1685f0e51a1fe1da955e7ad10044\", \"v\": 2, \"hm\": \"fb73e0f40bc991cf4b1090d0801f6447\"}'::jsonb)::eql_v2.ste_vec_entry))", + "Index Name": "json_ste_vec_small_encrypted_100000_field_eq_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.54, + "Total Cost": 19741.54 + } + ], + "Startup Cost": 0.54, + "Total Cost": 2.52 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Index Scan using json_ste_vec_small_encrypted_1000000_field_eq_idx on json_ste_vec_small_encrypted_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_1000000", + "Async Capable": false, + "Index Cond": "(eql_v2.eq_term((value -> 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbJeS~GW(rh_Ip#L(=Tk4TQhWW<9ljWmSq7yFQK{3){*^3mrvZVb*R$1K>{#a~UP>9qrQVA&6A(*plc?p!)G6K6VxXRF-Ao<%8ZuHeK?nJ3--0Nm!1=ln2Xui4i>S)gYG;I(F^bd2`!ND6isp!LMOUBn>CRQ!LHS7`%z%ZEdL=*l4D?dx-| 'cfef1685f0e51a1fe1da955e7ad10044'::text)) = eql_v2.eq_term(('{\"a\": false, \"c\": \"mBbJLhWn-J_XuAF@lJV1yj2RsWY00Q2F%S?!W`})*vltb>7kZ*|BK4On8t^sSE)U-JiRV)L + +![Query Performance - JSON/field_eq/functional](query_json_field_eq_functional_chart.png) + +## field_order/functional + +**Description:** Field-level ORDER BY via ORE extractor on `value -> 'sel'` + +**SQL Query:** +```sql +SELECT id FROM {TABLE} ORDER BY (value -> ''::text) LIMIT 10 +``` + +**Table: `json_ste_vec_small_encrypted_{rows}`. Index: functional btree on `(value -> ''::text)` using the appropriate opclass for the term type. `` is selected at bench startup based on which orderable tag the sampled sv element carries: + - `oc` → `eql_v2.ore_cllw` (Standard mode, ORE CLLW — requires the `eql_v2.ore_cllw_ops` btree opclass from EQL #221) + - `op` → `eql_v2.ope_cllw` (Compat mode, OPE CLLW) + - `ob` → `eql_v2.ore_block_u64_8_256` (Block ORE — root scalars only) +When the table's `oc` index is present, the plan engages Index Scan + LIMIT (no Sort node). When absent (older bench run / index not yet rebuilt), falls back to Seq Scan + Top-N sort.** + +**Indexes available on the table:** +```sql +-- EQL 2.3 functional GIN indexes for the json ste_vec bench. +-- +-- jsonb_array — whole-document containment (contains/functional): +-- eql_v2.jsonb_array(value) @> eql_v2.jsonb_array($1). +-- stevec_query — typed field-level containment (field_eq/extractor): +-- value @> $1::eql_v2.stevec_query inlines to a native +-- jsonb @> over eql_v2.to_stevec_query(value)::jsonb. +-- XOR-aware: one index covers hm- and oc-bearing selectors. +-- +-- Replaces the pre-2.3 eql_v2.ste_vec / eql_v2.hmac_256_terms GIN indexes +-- (hmac_256_terms was removed in EQL 2.3 — see cipherstash/eql#223). + +CREATE INDEX +json_ste_vec_small_encrypted_10000_jsonb_array_index +ON json_ste_vec_small_encrypted_10000 USING GIN ( + eql_v2.jsonb_array(value) +); + +CREATE INDEX +json_ste_vec_small_encrypted_10000_stevec_query_index +ON json_ste_vec_small_encrypted_10000 USING GIN ( + (eql_v2.to_stevec_query(value)::jsonb) jsonb_path_ops +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: `json_ste_vec_small_encrypted_10000_field_order_idx` +- 100,000: `json_ste_vec_small_encrypted_100000_field_order_idx` +- 1,000,000: `json_ste_vec_small_encrypted_1000000_field_order_idx` +- 10,000,000: `json_ste_vec_small_encrypted_10000000_field_order_idx` + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 324.65μs | N/A | +| 100,000 | 10 | 315.29μs | N/A | +| 1,000,000 | 10 | 367.56μs | N/A | +| 10,000,000 | 10 | 367.54μs | N/A | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Index Scan using json_ste_vec_small_encrypted_10000_field_order_idx on json_ste_vec_small_encrypted_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 36, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_10000", + "Async Capable": false, + "Index Name": "json_ste_vec_small_encrypted_10000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 36, + "Relation Name": "json_ste_vec_small_encrypted_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.41, + "Total Cost": 13014.19 + } + ], + "Startup Cost": 0.41, + "Total Cost": 13.42 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Index Scan using json_ste_vec_small_encrypted_100000_field_order_idx on json_ste_vec_small_encrypted_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 36, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_100000", + "Async Capable": false, + "Index Name": "json_ste_vec_small_encrypted_100000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 36, + "Relation Name": "json_ste_vec_small_encrypted_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.42, + "Total Cost": 127618.52 + } + ], + "Startup Cost": 0.42, + "Total Cost": 13.18 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Index Scan using json_ste_vec_small_encrypted_1000000_field_order_idx on json_ste_vec_small_encrypted_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 36, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_1000000", + "Async Capable": false, + "Index Name": "json_ste_vec_small_encrypted_1000000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1002404, + "Plan Width": 36, + "Relation Name": "json_ste_vec_small_encrypted_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.55, + "Total Cost": 1238292.08 + } + ], + "Startup Cost": 0.55, + "Total Cost": 12.9 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Index Scan using json_ste_vec_small_encrypted_10000000_field_order_idx on json_ste_vec_small_encrypted_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 36, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_10000000", + "Async Capable": false, + "Index Name": "json_ste_vec_small_encrypted_10000000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 9986163, + "Plan Width": 36, + "Relation Name": "json_ste_vec_small_encrypted_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.56, + "Total Cost": 12366683.86 + } + ], + "Startup Cost": 0.56, + "Total Cost": 12.94 + } + } +] +``` + +
+ +![Query Performance - JSON/field_order/functional](query_json_field_order_functional_chart.png) + diff --git a/report/v2/match.md b/report/v2/match.md new file mode 100644 index 0000000..c921922 --- /dev/null +++ b/report/v2/match.md @@ -0,0 +1,823 @@ +# MATCH Queries + +[← Back to overview](./BENCHMARK_REPORT.md) + +Per-tier query performance. Each scenario lists its SQL, the indexes available on the target table, the indexes the planner actually picked per tier, the timing table, and the full EXPLAIN plan in a collapsed block. + +## eql_bloom + +**Description:** Pattern matching using EQL bloom filter containment + +**SQL Query:** +```sql +SELECT id,value::jsonb FROM {TABLE} WHERE eql_v2.bloom_filter(value) @> eql_v2.bloom_filter($1) LIMIT 10 +``` + +**Parameter:** `Johnson` + +**Table: `string_encrypted_{rows}` with encrypted string values. Index: Bloom filter index using `eql_v2.bloom_filter`. Query returns LIMIT 10 results.** + +**Indexes available on the table:** +```sql +CREATE INDEX +string_encrypted_10000_hash_index +ON string_encrypted_10000 using hash ( + eql_v2.hmac_256(value) +); + +CREATE INDEX +string_encrypted_10000_gin_index +ON string_encrypted_10000 USING GIN ( + eql_v2.bloom_filter(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: `string_encrypted_10000_gin_index` +- 100,000: `string_encrypted_100000_gin_index` +- 1,000,000: `string_encrypted_1000000_gin_index` +- 10,000,000: `string_encrypted_10000000_gin_index` + +*⚠️ = Query time exceeds 100ms* + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 411.27μs | 27.04ms | +| 100,000 | 10 | 1.77ms | 26.41ms | +| 1,000,000 | 10 | 14.48ms | 39.91ms | +| 10,000,000 | 10 | ⚠️ 144.09ms | ⚠️ 169.68ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Bitmap Heap Scan on string_encrypted_10000 + Bitmap Index Scan using string_encrypted_10000_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1109,1596,61,1500,587,582,865,1845,1760,792,1057,1018,1637,421,710,1496,1751,830,1068,1183,895,1574,1031,2028,998,1143,1453,1735,1200,682}'::smallint[])", + "Index Name": "string_encrypted_10000_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 264.6 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1109,1596,61,1500,587,582,865,1845,1760,792,1057,1018,1637,421,710,1496,1751,830,1068,1183,895,1574,1031,2028,998,1143,1453,1735,1200,682}'::smallint[])", + "Relation Name": "string_encrypted_10000", + "Startup Cost": 264.6, + "Total Cost": 269.11 + } + ], + "Startup Cost": 264.6, + "Total Cost": 269.11 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Bitmap Heap Scan on string_encrypted_100000 + Bitmap Index Scan using string_encrypted_100000_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_100000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1637,1760,998,1845,1574,1453,582,1068,421,865,1143,1057,1751,1183,1031,710,1596,1018,830,587,1109,1200,682,895,792,1500,1496,1735,2028,61}'::smallint[])", + "Index Name": "string_encrypted_100000_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 458.47 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1637,1760,998,1845,1574,1453,582,1068,421,865,1143,1057,1751,1183,1031,710,1596,1018,830,587,1109,1200,682,895,792,1500,1496,1735,2028,61}'::smallint[])", + "Relation Name": "string_encrypted_100000", + "Startup Cost": 458.48, + "Total Cost": 462.99 + } + ], + "Startup Cost": 458.48, + "Total Cost": 462.99 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Bitmap Heap Scan on string_encrypted_1000000 + Bitmap Index Scan using string_encrypted_1000000_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_1000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1031,587,1200,998,1574,792,1183,865,1596,1109,1057,895,1143,1751,682,582,1735,1496,1018,2028,421,830,1845,1068,61,1637,1760,1500,1453,710}'::smallint[])", + "Index Name": "string_encrypted_1000000_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 1407.6 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1031,587,1200,998,1574,792,1183,865,1596,1109,1057,895,1143,1751,682,582,1735,1496,1018,2028,421,830,1845,1068,61,1637,1760,1500,1453,710}'::smallint[])", + "Relation Name": "string_encrypted_1000000", + "Startup Cost": 1407.6, + "Total Cost": 1412.11 + } + ], + "Startup Cost": 1407.6, + "Total Cost": 1412.11 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Bitmap Heap Scan on string_encrypted_10000000 + Bitmap Index Scan using string_encrypted_10000000_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_10000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1453,421,61,2028,895,1596,1574,865,1845,792,587,1018,1735,998,1143,1496,1109,1031,1637,710,1200,1751,682,582,1760,1068,830,1183,1500,1057}'::smallint[])", + "Index Name": "string_encrypted_10000000_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 11237.48 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1453,421,61,2028,895,1596,1574,865,1845,792,587,1018,1735,998,1143,1496,1109,1031,1637,710,1200,1751,682,582,1760,1068,830,1183,1500,1057}'::smallint[])", + "Relation Name": "string_encrypted_10000000", + "Startup Cost": 11237.48, + "Total Cost": 11241.99 + } + ], + "Startup Cost": 11237.48, + "Total Cost": 11241.99 + } + } +] +``` + +
+ +![Query Performance - MATCH/eql_bloom](query_match_eql_bloom_chart.png) + +## eql_cast_firstname + +**Description:** Pattern matching on first name using EQL cast and LIKE + +**SQL Query:** +```sql +SELECT id,value::jsonb FROM {TABLE} WHERE value LIKE $1 LIMIT 10 +``` + +**Parameter:** `Bob` + +**Table: `string_encrypted_{rows}` with encrypted string values. Index: MATCH index for substring searches. Query returns LIMIT 10 results.** + +**Indexes available on the table:** +```sql +CREATE INDEX +string_encrypted_10000_hash_index +ON string_encrypted_10000 using hash ( + eql_v2.hmac_256(value) +); + +CREATE INDEX +string_encrypted_10000_gin_index +ON string_encrypted_10000 USING GIN ( + eql_v2.bloom_filter(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: `string_encrypted_10000_gin_index` +- 100,000: `string_encrypted_100000_gin_index` +- 1,000,000: `string_encrypted_1000000_gin_index` +- 10,000,000: `string_encrypted_10000000_gin_index` + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 2 | 152.35μs | 24.28ms | +| 100,000 | 10 | 634.91μs | 26.58ms | +| 1,000,000 | 10 | 3.77ms | 30.13ms | +| 10,000,000 | 10 | 33.69ms | 58.11ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Bitmap Heap Scan on string_encrypted_10000 + Bitmap Index Scan using string_encrypted_10000_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1033,91,1393,453,1554,461}'::smallint[])", + "Index Name": "string_encrypted_10000_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 56.22 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1033,91,1393,453,1554,461}'::smallint[])", + "Relation Name": "string_encrypted_10000", + "Startup Cost": 56.22, + "Total Cost": 60.73 + } + ], + "Startup Cost": 56.22, + "Total Cost": 60.73 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Bitmap Heap Scan on string_encrypted_100000 + Bitmap Index Scan using string_encrypted_100000_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_100000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{91,461,1393,1033,1554,453}'::smallint[])", + "Index Name": "string_encrypted_100000_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 93.35 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{91,461,1393,1033,1554,453}'::smallint[])", + "Relation Name": "string_encrypted_100000", + "Startup Cost": 93.35, + "Total Cost": 97.86 + } + ], + "Startup Cost": 93.35, + "Total Cost": 97.86 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Bitmap Heap Scan on string_encrypted_1000000 + Bitmap Index Scan using string_encrypted_1000000_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_1000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{91,453,1033,1554,461,1393}'::smallint[])", + "Index Name": "string_encrypted_1000000_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 282.35 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{91,453,1033,1554,461,1393}'::smallint[])", + "Relation Name": "string_encrypted_1000000", + "Startup Cost": 282.35, + "Total Cost": 286.86 + } + ], + "Startup Cost": 282.35, + "Total Cost": 286.86 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Bitmap Heap Scan on string_encrypted_10000000 + Bitmap Index Scan using string_encrypted_10000000_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_10000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1033,91,1554,461,453,1393}'::smallint[])", + "Index Name": "string_encrypted_10000000_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 2249.97 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1033,91,1554,461,453,1393}'::smallint[])", + "Relation Name": "string_encrypted_10000000", + "Startup Cost": 2249.97, + "Total Cost": 2254.48 + } + ], + "Startup Cost": 2249.97, + "Total Cost": 2254.48 + } + } +] +``` + +
+ +![Query Performance - MATCH/eql_cast_firstname](query_match_eql_cast_firstname_chart.png) + +## eql_cast_lastname + +**Description:** Pattern matching on last name using EQL cast and LIKE + +**SQL Query:** +```sql +SELECT id,value::jsonb FROM {TABLE} WHERE value LIKE $1 LIMIT 10 +``` + +**Parameter:** `Johnson` + +**Table: `string_encrypted_{rows}` with encrypted string values. Index: MATCH index for substring searches. Query returns LIMIT 10 results.** + +**Indexes available on the table:** +```sql +CREATE INDEX +string_encrypted_10000_hash_index +ON string_encrypted_10000 using hash ( + eql_v2.hmac_256(value) +); + +CREATE INDEX +string_encrypted_10000_gin_index +ON string_encrypted_10000 USING GIN ( + eql_v2.bloom_filter(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: `string_encrypted_10000_gin_index` +- 100,000: `string_encrypted_100000_gin_index` +- 1,000,000: `string_encrypted_1000000_gin_index` +- 10,000,000: `string_encrypted_10000000_gin_index` + +*⚠️ = Query time exceeds 100ms* + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 437.17μs | 27.30ms | +| 100,000 | 10 | 1.79ms | 28.08ms | +| 1,000,000 | 10 | 14.40ms | 39.25ms | +| 10,000,000 | 10 | ⚠️ 144.81ms | ⚠️ 168.13ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Bitmap Heap Scan on string_encrypted_10000 + Bitmap Index Scan using string_encrypted_10000_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1574,1109,1637,710,61,792,1760,1143,1057,1068,865,1453,1031,1751,587,1200,1596,895,1496,1845,1500,998,830,421,582,2028,1735,682,1183,1018}'::smallint[])", + "Index Name": "string_encrypted_10000_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 264.6 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{1574,1109,1637,710,61,792,1760,1143,1057,1068,865,1453,1031,1751,587,1200,1596,895,1496,1845,1500,998,830,421,582,2028,1735,682,1183,1018}'::smallint[])", + "Relation Name": "string_encrypted_10000", + "Startup Cost": 264.6, + "Total Cost": 269.11 + } + ], + "Startup Cost": 264.6, + "Total Cost": 269.11 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Bitmap Heap Scan on string_encrypted_100000 + Bitmap Index Scan using string_encrypted_100000_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_100000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{895,1637,1183,582,1109,1845,1496,1031,865,682,1500,1760,1068,1200,1574,830,1453,1018,1735,792,1143,998,587,1057,2028,1751,421,710,61,1596}'::smallint[])", + "Index Name": "string_encrypted_100000_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 458.47 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{895,1637,1183,582,1109,1845,1496,1031,865,682,1500,1760,1068,1200,1574,830,1453,1018,1735,792,1143,998,587,1057,2028,1751,421,710,61,1596}'::smallint[])", + "Relation Name": "string_encrypted_100000", + "Startup Cost": 458.48, + "Total Cost": 462.99 + } + ], + "Startup Cost": 458.48, + "Total Cost": 462.99 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Bitmap Heap Scan on string_encrypted_1000000 + Bitmap Index Scan using string_encrypted_1000000_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_1000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{2028,1735,865,1845,1596,1637,1760,1031,792,682,1496,1751,1109,61,582,587,1500,1057,895,1143,998,1183,710,1574,1068,1018,1453,1200,421,830}'::smallint[])", + "Index Name": "string_encrypted_1000000_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 1407.6 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{2028,1735,865,1845,1596,1637,1760,1031,792,682,1496,1751,1109,61,582,587,1500,1057,895,1143,998,1183,710,1574,1068,1018,1453,1200,421,830}'::smallint[])", + "Relation Name": "string_encrypted_1000000", + "Startup Cost": 1407.6, + "Total Cost": 1412.11 + } + ], + "Startup Cost": 1407.6, + "Total Cost": 1412.11 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Bitmap Heap Scan on string_encrypted_10000000 + Bitmap Index Scan using string_encrypted_10000000_gin_index +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "string_encrypted_10000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{830,1500,1143,1031,1574,1109,1068,1453,1845,895,1057,1496,1751,582,61,587,1183,998,2028,1735,1018,792,1760,710,865,1200,1637,421,682,1596}'::smallint[])", + "Index Name": "string_encrypted_10000000_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 11237.48 + } + ], + "Recheck Cond": "((eql_v2.bloom_filter(value))::smallint[] @> '{830,1500,1143,1031,1574,1109,1068,1453,1845,895,1057,1496,1751,582,61,587,1183,998,2028,1735,1018,792,1760,710,865,1200,1637,421,682,1596}'::smallint[])", + "Relation Name": "string_encrypted_10000000", + "Startup Cost": 11237.48, + "Total Cost": 11241.99 + } + ], + "Startup Cost": 11237.48, + "Total Cost": 11241.99 + } + } +] +``` + +
+ +![Query Performance - MATCH/eql_cast_lastname](query_match_eql_cast_lastname_chart.png) + diff --git a/report/v2/ore.md b/report/v2/ore.md new file mode 100644 index 0000000..06167f1 --- /dev/null +++ b/report/v2/ore.md @@ -0,0 +1,1032 @@ +# ORE Queries + +[← Back to overview](./BENCHMARK_REPORT.md) + +Per-tier query performance. Each scenario lists its SQL, the indexes available on the target table, the indexes the planner actually picked per tier, the timing table, and the full EXPLAIN plan in a collapsed block. + +## range_gt_10 + +**Description:** Range query (greater than) returning 10 results + +**SQL Query:** +```sql +SELECT id,value::jsonb FROM {TABLE} WHERE value > $1 LIMIT 10 +``` + +**Parameter:** `5000` + +**Table: `integer_encrypted_{rows}` with Block-ORE-encrypted integer values. Index: functional btree on `eql_v2.ore_block_u64_8_256(value)`. The bare-form `<` / `>` operators inline to `eql_v2.ore_block_u64_8_256(a) op eql_v2.ore_block_u64_8_256(b)` post-2.3, so the index engages without query rewriting. Query: WHERE value > 5000 LIMIT 10.** + +**Indexes available on the table:** +```sql +CREATE INDEX +integer_encrypted_10000_ore_index +ON integer_encrypted_10000 ( + eql_v2.ore_block_u64_8_256(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 629.63μs | 31.20ms | +| 100,000 | 10 | 568.25μs | 25.67ms | +| 1,000,000 | 10 | 699.44μs | 26.64ms | +| 10,000,000 | 10 | 605.03μs | 25.46ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1096, + "Plans": [ + { + "Alias": "integer_encrypted_10000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb2895058ceacf03e52bb407fe49acfa3b16b0ac37b95cd2d7c2de61fe1fe5c0653f7403fbfabc9e15ba1280c66d5cfbe9271bceba052138a29b6b9af48605878bec30891ce20d6c30dc13b435e8b698b06f1f10e88cf6bfc3d374fe394c575c12e87b18bacad46d3397f9ac10b82ec8becf12be4d8c253c2690718699d1e9d9125887e6d2413f2f4fff0e8ce299a3435f7adbe089c5749adda2b589569bcaf8b8c0e589eeae06a9565a4dfbd92d03c3efe15129d6b4f0a9503fd37f84516d96d67e313189e1dbfa5c6c969b299fedb83ad31b7c075888ea9a0e5b8b97d631aeaa16efaf41bf9eb702562c8e57d7f2e2e180d59b1179249bdb33c845146c1a9649cb7058859d3bf96bbefa66227e87acb5ab\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5050, + "Plan Width": 1096, + "Relation Name": "integer_encrypted_10000", + "Startup Cost": 0.0, + "Total Cost": 6580.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.03 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1100, + "Plans": [ + { + "Alias": "integer_encrypted_100000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28cdffed476d8949ad004e8503eee2d1ede277e72680cb4f49336cfc2d27d4d3d87c0d2b188c5667d06c772cd8943097e6bc09e35e82cd7eac79ff5f3601f84c13822ff353bf058a28c334a9152c678ab9f603654b31bbf1a670be0f43714bc2fb662770684b98854b4eee3e4d97b02ea06fd7daf2239bea2e3cbcf9522a5c452bae4b25f21a91080615a53f71d1b59525dd08f87cb9bcd6cad1a6eaad71c123101d4d9483ece39053b5515249f666037d3edaf4197fb129095640f52b1b0e981fa00af3f0ba265e155bccb963fc0afe38b99146b9e7a63813c896bbdbb795e99038271c6047475734c28a135e2aa1b72c282fd257cc7f45412f70e476f63bad5adb65cb1461b84caec0f8bfc07d92acd0\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 49500, + "Plan Width": 1100, + "Relation Name": "integer_encrypted_100000", + "Startup Cost": 0.0, + "Total Cost": 65344.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.2 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1100, + "Plans": [ + { + "Alias": "integer_encrypted_1000000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb282f84fb8bea947267022c54168884f13b299cb13e75fd502a59e9eeeb2841560bc59c69a676482a044359edbc2138c8f381eb13e4b765294ab3eaafa4751639312ead32fde25cb182fbfdcabb32af14a7e3a45dc406285c52e6e3a0ac1ed955d59fb786dd85b6c92608eab5a6f556e3aa9f401ef39d3453e149b01af85327bb8aa02bd78f191f969f1474d04917ec8360c9aa15a7d62181d1f0d29c5b90c6272c8668287f38405b6832c2807a362201945ec2100cdc5d4fda682f40eb0b891c39a3c2accf1d8fd685da9a5853e1c168e6f9c921acbc19ce840aa8f093228183d84c20f72c67758110a35bb1c9d048e04a8c9b476452b8784a4db734f50f0c72d735fd69e8f16f262ce66fe0815c8cdcbb\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 505003, + "Plan Width": 1100, + "Relation Name": "integer_encrypted_1000000", + "Startup Cost": 0.0, + "Total Cost": 652923.06 + } + ], + "Startup Cost": 0.0, + "Total Cost": 12.93 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1100, + "Plans": [ + { + "Alias": "integer_encrypted_10000000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28ab3526a1f71312dd4b4012a56a854f8b6d50e0865458819e6ddb7e5a26c521c2351887d2b69273ee56010754f2e8e30383a63df6b667c659cd59c6e8fc5925653beafc5f1898c4d0f149f230b11ae10083b8316ff49fb1be201bab7464f3695804ce459307906047dd100a885fc13b467ebae0fbecffc31db1f56cf8e177b9ddc24bac3871f14f8475c446c4d0ea2b13d6e687dacf1d6f2647ed35d2e0f009f8ed3d843452ca2df663d840bd0d2dd90a11fadd0b32300a245b4ad2daa679186eea23a0a5fe20f789827344692613214cdc5d901715d26293a64a2ef96d0010dd7136981dc63ff16764bd1c6f5b223970f1ba23dc3855b0e2eea32d484436e2dba077bc5da5537f4fb5d03c23d011184f\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5050158, + "Plan Width": 1100, + "Relation Name": "integer_encrypted_10000000", + "Startup Cost": 0.0, + "Total Cost": 6528775.12 + } + ], + "Startup Cost": 0.0, + "Total Cost": 12.93 + } + } +] +``` + +
+ +![Query Performance - ORE/range_gt_10](query_ore_range_gt_10_chart.png) + +## range_gt_100 + +**Description:** Range query (greater than) returning 100 results + +**SQL Query:** +```sql +SELECT id,value::jsonb FROM {TABLE} WHERE value > $1 LIMIT 100 +``` + +**Parameter:** `5000` + +**Table: `integer_encrypted_{rows}` with Block-ORE-encrypted integer values. Index: functional btree on `eql_v2.ore_block_u64_8_256(value)`. Query: WHERE value > 5000 LIMIT 100.** + +**Indexes available on the table:** +```sql +CREATE INDEX +integer_encrypted_10000_ore_index +ON integer_encrypted_10000 ( + eql_v2.ore_block_u64_8_256(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 100 | 4.08ms | 46.72ms | +| 100,000 | 100 | 4.19ms | 42.46ms | +| 1,000,000 | 100 | 4.11ms | 46.26ms | +| 10,000,000 | 100 | 4.06ms | 45.98ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1096, + "Plans": [ + { + "Alias": "integer_encrypted_10000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28516c2cd5946c69af275e35b4d463d045361a1cf588bd7ce00b458793690af709d02b69d2e6752be608e71d0d74b4c86de79bffbb1a2eedb0d48d31c5e25f35c3d7b0b6d0ebb351be2de001a2e98897471c2de5ccef4c643f000cc2aa4a42b34d9ac46e80fb5e73cdd60cd305f2f65e3a825c3520a9f6700f3b3f332eb1162f56e805f3e43fcc54b611217b120bbf618dc909865ff5ae4724123e3f73465b786fcd127477cf4e0559e500c4fa8e0ff35081ba73c3d5a34a5da3137c37450ddc9fec6050a46b1a3876200fd83a21b7b84f683d2ae6cb0a1e648a227a800e26e7f7071d0a9851bc3c5eca490ef0a51102eaa215147b4f10bef5a9a88475c3fa128476ac2d4061d2f29e48ba5bdcfc772539\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5050, + "Plan Width": 1096, + "Relation Name": "integer_encrypted_10000", + "Startup Cost": 0.0, + "Total Cost": 6580.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 130.3 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1100, + "Plans": [ + { + "Alias": "integer_encrypted_100000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28fa32673493f0be9a0aeb3ba6c3df4f09b3aeab46f298065b776269777c3cf9a42c654c6745db2642d462699cb93ca8b476e2f4662fb7cf9056f5c67c34eb6fd472e5f3a395a4625a56c286821eebcfa6324006b3abdf6f21cd1dcb4708ceb9680f2363fd312604c638f72e3db772996c73df4b980caddfba6941d3a5944928755ff7cae1ba838a7ebd4fabe18f44a243d6f45bb097f77be87c981b3dd3a517ad71f9bbb0ebdf929e8161b5d0c4f7567e6d60ddf06e5516047d814f873fa339e4b4e3b641085e826fbd534cb79e0aadc6b3b96d25533fb166e88205cb32171bad7648bb4e5eb7dcc55b6b73beffa33d5caefe093e86744da6b82947761a9ac38f51439bcdb1f936439295d266b560fe08\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 49500, + "Plan Width": 1100, + "Relation Name": "integer_encrypted_100000", + "Startup Cost": 0.0, + "Total Cost": 65344.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 132.01 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1100, + "Plans": [ + { + "Alias": "integer_encrypted_1000000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28e35161ead6beffd7663345c5318f66d1601b178b8b64bd03b9cb417932b68f4923776a54650ab7182e808668cfaa90543e34e7e4cf6d8dfdb524d45e3bf38f06e99980370109eff79345e4b9389ddb30026d6686c9ec5e1d36452c4b8b48dd5f6c4fe91054ef5518e2ceeac0d04695f32b16b4b5e093386bcacf6e0735402f482eb60618f0fc29f602147257485621aa8ac80a875e6597f48fb66a1895a989ca665ea38d46fccd031aa9230d997a4e6cea51831b3fddbeee566978d81f29c3732d68408cefb521676823a67cf770b733033941594d74afafc37ad96fa7be7d862ff77227be89b16f1f651eadbb2c3c3a5a034a098b9f595c07209177e3c4acae06718f5cbd99d07c4103a7b463d3f6b9\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 505003, + "Plan Width": 1100, + "Relation Name": "integer_encrypted_1000000", + "Startup Cost": 0.0, + "Total Cost": 652923.06 + } + ], + "Startup Cost": 0.0, + "Total Cost": 129.29 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1100, + "Plans": [ + { + "Alias": "integer_encrypted_10000000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) > '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb289ce2631903d6108b8bf2bdf62a911654684dc048f7060858c44bc617b98d87fda06546b08c80283edeb5488db636347b2b0cf949c93dc9e038f247774433cafbcd63bf91d129b31c52a56e4db0361d4f527df7c29e15380b9063b1e04a1e43b74fc095b98b17bb6551448320c938c455cd0ced12447e4c0fc8c05d9bb62593442d628e0386ee98a9abaac940b361b10249c58bbba2726fc2475a423aa5a5e3efe320e3374ba6d247d1864bffd741ae8b3e50734c2e31558d31396840e8d90455d0b2798c225048af2de3201c962b2e8df2edd69d2e172220aedcb05bedfcbe6e3beaa69920c9900f5bec3a2fddf9d589d4e6c6558df08bd9b8f3aecca4566c9b7da26f2dda2bd1eddb0a372119661a3e\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5050158, + "Plan Width": 1100, + "Relation Name": "integer_encrypted_10000000", + "Startup Cost": 0.0, + "Total Cost": 6528775.12 + } + ], + "Startup Cost": 0.0, + "Total Cost": 129.28 + } + } +] +``` + +
+ +![Query Performance - ORE/range_gt_100](query_ore_range_gt_100_chart.png) + +## range_lt_10 + +**Description:** Range query (less than) returning 10 results + +**SQL Query:** +```sql +SELECT id,value::jsonb FROM {TABLE} WHERE value < $1 LIMIT 10 +``` + +**Parameter:** `5000` + +**Table: `integer_encrypted_{rows}` with Block-ORE-encrypted integer values. Index: functional btree on `eql_v2.ore_block_u64_8_256(value)`. Query: WHERE value < 5000 LIMIT 10.** + +**Indexes available on the table:** +```sql +CREATE INDEX +integer_encrypted_10000_ore_index +ON integer_encrypted_10000 ( + eql_v2.ore_block_u64_8_256(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 593.75μs | 28.77ms | +| 100,000 | 10 | 654.88μs | 29.26ms | +| 1,000,000 | 10 | 587.45μs | 26.92ms | +| 10,000,000 | 10 | 765.42μs | 28.62ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1096, + "Plans": [ + { + "Alias": "integer_encrypted_10000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28281514a62219c9e223b1b98519673056b9a5be40434e07d5bb2f217fc5e9d32fbee4b30897d67c09230375ac6ca91c9de55ce861c231520461bad34d8c6b4dc3f153de14b91b711829818e7037c964b2359ea8a038c5822c23bf0d35a0e68635c59c82dc31771fb6dc55614f583c2730b47cc153459a890943b9c4ce5d74e636b1293882943db6023ccdc3460d1a1647dce4a0861af21d65f33cec0528496cd813c2de31ba42d27e125ed3732c01a628229a7a3f7bc91e2f62bb333e92f4f3249478a190c117a45a03c00a1a4ea3b1b9942cd7566ee3052a2abd75b903bdab00476e90b9643e4758d203cd0e86edcf0f9ddab24394d50304f84b884d435ba096b6ed4d201d0a4315a4790152bcfd8743\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4949, + "Plan Width": 1096, + "Relation Name": "integer_encrypted_10000", + "Startup Cost": 0.0, + "Total Cost": 6580.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.3 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1100, + "Plans": [ + { + "Alias": "integer_encrypted_100000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb2818082cdcde08b3ec83a009cc965e2b3feb49c2fd9f35398709b0928121eb28e004ce488d915e1e277d5aaad38670a26d9f03fc6e160ad1aff6b665825d60af3b6b258ff799d72e7a9cc740da7654c2184e3044c78a660f91a093ceb87645f29e93f1b298d14d5a717d4b4aedeed621f2b4b40486787924e2eca5cc8711857806d9b570fcd8cca93af62e401c9af35f2458f83b251587508641cbe02fb3bf90c27a3e4c68ec890dcc2a8eddcfc2bf7999619122104e09064b3c12042914e24ad8fcb74fffc9268c06cc6d7093a545e14ea482fb8d85ac048edb6b882ad41d25c8c6f3e48b6f33df6dd86d3909846307fb8497181666303bfb821890299fdfbba60d9cf8ca0ed7104d78140514cdec9b21\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50499, + "Plan Width": 1100, + "Relation Name": "integer_encrypted_100000", + "Startup Cost": 0.0, + "Total Cost": 65344.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 12.94 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1100, + "Plans": [ + { + "Alias": "integer_encrypted_1000000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb282e91d2b8748554723eec099dc035833f94094f04a27dd8ed5f63bd409a8139d10d2b11e57772a0e591746c4668e8dc002068a91bf70ebdb4209b1692fe59c767f676f24a9fda124826331b1a715518b9f84fa85009b12429e59c9781aaf6bb4362435caaba5dce276cab29415bada9b340e36e96a2377ded7519e8eb30527761902980d7b087bc6336365e238c478989279982e9b7d808305f489af26cf8f8512d2b736935502391c6d2551e50e5c699dd1378be1b8d2ee6b0603658cf9b7ed58b7fc21bec0493cf001ed97b549b9b76dd4157d365f26bbfb019a99d4df555e3f4fc96bc79f254b55353df22614ea788caf528980fda2831cd483fd31f30b291d40f3d8b8dca1b4716a6eaae0c6ff57e\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 495002, + "Plan Width": 1100, + "Relation Name": "integer_encrypted_1000000", + "Startup Cost": 0.0, + "Total Cost": 652923.06 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.19 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1100, + "Plans": [ + { + "Alias": "integer_encrypted_10000000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28f593f1586d1251937b77bd76c4a36fc688c54b1b1760abb18eda2851fccc74552ed80c0a772f803e41a02ec7ab03c4857e53354c7c07aa846e6aa04319816826eba5a69558565a14711bd9dbe930e3ed263b3c6b370ac260c1e12699539c78cdace31999339368554c76fd77a3a1b5a1497ef2fd3d92c730057add2cb55ee475e8fd91eaadb75ed02e7cccbe261730822a2c1afa46b057c79b2201186499e7f11e88644c7bd3616379938706ce2b9d82e8be8a761ce70ec2cfe28e31a4fb50d439755da13c318c2841ac2af4743137f8398a5d9d244be89b6a38777ea4dd01a7048e5733945a991d249e95f2b7d616e763f54923b3e40770d5b7fe6eea162e19c51366bdbcc0bf674f63af3f882e473a\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4950153, + "Plan Width": 1100, + "Relation Name": "integer_encrypted_10000000", + "Startup Cost": 0.0, + "Total Cost": 6528775.12 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.19 + } + } +] +``` + +
+ +![Query Performance - ORE/range_lt_10](query_ore_range_lt_10_chart.png) + +## range_lt_100 + +**Description:** Range query (less than) returning 100 results + +**SQL Query:** +```sql +SELECT id,value::jsonb FROM {TABLE} WHERE value < $1 LIMIT 100 +``` + +**Parameter:** `5000` + +**Table: `integer_encrypted_{rows}` with Block-ORE-encrypted integer values. Index: functional btree on `eql_v2.ore_block_u64_8_256(value)`. Query: WHERE value < 5000 LIMIT 100.** + +**Indexes available on the table:** +```sql +CREATE INDEX +integer_encrypted_10000_ore_index +ON integer_encrypted_10000 ( + eql_v2.ore_block_u64_8_256(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 100,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 1,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ +- 10,000,000: _none — planner picked a sequential / hash-aggregate / sort plan_ + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 100 | 3.95ms | 45.93ms | +| 100,000 | 100 | 3.91ms | 47.31ms | +| 1,000,000 | 100 | 4.07ms | 44.32ms | +| 10,000,000 | 100 | 4.12ms | 46.31ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1096, + "Plans": [ + { + "Alias": "integer_encrypted_10000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb2842b46e630529ee0ad9f9da1dc9679eb9b63125d7c154536158c4bf3612c27decbdc3b89e5e239608510c120ec9fa347dd6e6e9e880ee6e45170a62e35c5f658d698b507dea059565113422ceb693ea2a38a1db6da4e6e1ba71cf3a804e364395be09331d90d897c75286796865ba0088c31dc4ad592ae1c7b577cc0bcb4b1f63cfa7d1946c25be95132827f5763c5237df5077e36fcc28d52dd7047b22f7554736e18d62a83d4a963ff23be234576d0fef6e5952c461d37f234597df886ff57f2db07497a038574bdb9949c48ea54d02c68c438ac86231763b1e7f92dfe39608aa2937b56d8bd076beddff41ee82f7c65fdc1aaa47c91e7c75a09795a50bf0bcaa5e8875702cfba1be4646f82affe75d\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4949, + "Plan Width": 1096, + "Relation Name": "integer_encrypted_10000", + "Startup Cost": 0.0, + "Total Cost": 6580.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 132.96 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1100, + "Plans": [ + { + "Alias": "integer_encrypted_100000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb2890665bb1d27a5a79962d6606881dd9ab6a557fcda289c68cf30f1028fc14e63b6f55a97b9c37995eac10b7122224fb62889debe5c644da1d1e45f75d084b47096442f2b1aac1d0a180d4312b6d817c27d94edcbe1d2903cf91993971e19111ac7c7f7080a68df266b2697699d2e68168492356a64bcbed646de191f4172bc37bd2eb4091a723621e30afd761a205d42bfe3e025ac3240fa6a4480156ececf1f07d67ba3794609a149cf502ada96dc86100fa4c3534837ce8017741778834cb1803236971bb7bcf083e88e7b0f369d6ccc32ea5f15f499b354ea7ada520807d6d687867350ccafe99955b647ebc72b4efb0157e9359419d56532864699db3ab733ae60a3f5ee31ecd52ce5c11b8671942\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50499, + "Plan Width": 1100, + "Relation Name": "integer_encrypted_100000", + "Startup Cost": 0.0, + "Total Cost": 65344.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 129.4 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1100, + "Plans": [ + { + "Alias": "integer_encrypted_1000000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb280f0a220b44bf138b1eeeff29fdf93ea9b1c0992b21396f165eee66f3c630a2f747674e1ec9ac0d28832db9749c921c9fc7ca8d65c423df4a3baa3ff31e48c7f7845f720da4bfb0a30bbf533be3327d1a78135d0fc446ad691c2212fc9f99221c31d2e39bde6b6440b5805915db927fbfa77c599d926f7d2ea09bf8a91abe3143c4882cd81fc268401a57f4be401b94341bc5ec2c143cc54e465c44a1d59a6cba892262c96fd9b5a8f2d5d4b6cd606a8b6623096b570b0d3a8b4813e507f56123ce438d1a4931ad76fbcb17930c20ddc8784c234aea0de7986520080708b50cb91ee2bc3970bc071195854660b3d374b85dcc3e2f3085f0d5d77a8d2e3df905ca5e9bf6aff650c799ee2fa7f67a5883cc\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 495002, + "Plan Width": 1100, + "Relation Name": "integer_encrypted_1000000", + "Startup Cost": 0.0, + "Total Cost": 652923.06 + } + ], + "Startup Cost": 0.0, + "Total Cost": 131.9 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Seq Scan on integer_encrypted_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1100, + "Plans": [ + { + "Alias": "integer_encrypted_10000000", + "Async Capable": false, + "Filter": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb288760bfdc5090d4008746ffbbc9564c0557b9a0e0f6b3e8e756c45d0b080540b9871bbab03a4d65bc35ccdb62515535cfdcc6e8eaed2cf489c23a23985916b1c73381a4dd970edaac9111b97e40cc5de333d40f0db178d987d6b1343e6c2464e5ca2f06ec4203ca875b7ec69be9d25822bd2d9d9c9964afabf74d9c6e2ade4d6a5dac18936c675fd79c54af9570f7efbb01d85100a6f2970c956d2d15de7c7a617e54347296aca56c0b58a1154d8a20c77f5da0f2a28b473e2d7d3437593d1d787ee78884647dc976123b8e1c728227dd1fafd530c5422a758660d30785a5b19f4f35be342c8ade262968e31eb07fb05fea210d5e3baa46c251be7e8c75e42c788ae4e3d0a784e7f0161b2016c16cdee0\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4950153, + "Plan Width": 1100, + "Relation Name": "integer_encrypted_10000000", + "Startup Cost": 0.0, + "Total Cost": 6528775.12 + } + ], + "Startup Cost": 0.0, + "Total Cost": 131.89 + } + } +] +``` + +
+ +![Query Performance - ORE/range_lt_100](query_ore_range_lt_100_chart.png) + +## range_lt_ordered_10 + +**Description:** Unknown query + +**** + +**Indexes available on the table:** +```sql +CREATE INDEX +integer_encrypted_10000_ore_index +ON integer_encrypted_10000 ( + eql_v2.ore_block_u64_8_256(value) +); +``` + +**Indexes used by the planner (per data set size):** + +- 10,000: `integer_encrypted_10000_ore_index` +- 100,000: `integer_encrypted_100000_ore_index` +- 1,000,000: `integer_encrypted_1000000_ore_index` +- 10,000,000: `integer_encrypted_10000000_ore_index` + +| Data Set Size | Rows Returned | Query Time (no decrypt) | Query Time (with decrypt) | +|---------------|---------------|-------------------------|---------------------------| +| 10,000 | 10 | 477.00μs | 28.85ms | +| 100,000 | 10 | 508.19μs | 28.80ms | +| 1,000,000 | 10 | 513.33μs | 27.10ms | +| 10,000,000 | 10 | 519.51μs | 26.54ms | + +_Rows Returned is the actual count from a one-shot pre-bench execution. For LIMIT-bounded queries it matches the LIMIT (or is lower when the table doesn't have enough matching rows); for aggregates wrapped in `count(*)` it's 1._ + +
+EXPLAIN plans (per data set size) + +**10,000 rows** + +``` +Limit + Index Scan using integer_encrypted_10000_ore_index on integer_encrypted_10000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1128, + "Plans": [ + { + "Alias": "integer_encrypted_10000", + "Async Capable": false, + "Index Cond": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb280e44626ed9555695a2cb4526032945fc0d94a21cfafd74507cf7f504d833e4819e5d2559755ed1dd33bb71349ef14cdaa984cdf81c1f9b45f9760429854a86d97e7b52eae8ce7e76b219a1ceefa8f145e7851dea9d92bca84caed4fc577f0b3248e8ffd00c6619cdbe25fd2a49dd3a81b514a128eac4d6458804c8e0c22807f7fa4513ef1ad9e4e716dc2534ba73178d710434d7f5d907116b7fc5816dc094e3ee443a5f106fedcbe7ffe37144ef757ca1a0efacac1de17b6ac06e4117df56d4564636004948f8d680a8573dfef9203bd349d89894380eff94f63759eb0aa34f3c78e8638327bfc60a02da53257846f5028e714cac8febfeb0ca58d5eb1f5ef4a52a981c694138d1fe0ef1aecf582290\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Index Name": "integer_encrypted_10000_ore_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4949, + "Plan Width": 1128, + "Relation Name": "integer_encrypted_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.54, + "Total Cost": 8796.38 + } + ], + "Startup Cost": 0.54, + "Total Cost": 18.31 + } + } +] +``` + +**100,000 rows** + +``` +Limit + Index Scan using integer_encrypted_100000_ore_index on integer_encrypted_100000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1132, + "Plans": [ + { + "Alias": "integer_encrypted_100000", + "Async Capable": false, + "Index Cond": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28a04e1538aef13d7dd0274a9106e45bb7e18744c1d268a8ae635ab442f5b76e9b9e10d695c7879972bf817d8a33a9fab2cf79b718dec6b47366f1105c61315524ccf91773e719f53f72a98fe07d2476e14c4752c0a2f105826c66db0a731df6a563ba7f884a4cd390f816b7262b80858ef95cf204af0b7fd73d221e3c665bd0e4fdc8dd741f97e9ff2781272426a781392d476744643d2388572fae7e50ca46b5d6d67b3e56d8ff13375add7d0696a818d5c802719e46c3ca40965aabdefb7e7e22d68cc57ca67e4e7707cc4ccbcd4e333d71bdfd77a6c02a7a18852cac31842590781ca501d08b6f524a18b0f70f60bfba0c3c895a617e603375c8dbc2d0a1611d2fccd785f508e78172c74d34bc204f\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Index Name": "integer_encrypted_100000_ore_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50499, + "Plan Width": 1132, + "Relation Name": "integer_encrypted_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.67, + "Total Cost": 86629.25 + } + ], + "Startup Cost": 0.67, + "Total Cost": 17.82 + } + } +] +``` + +**1,000,000 rows** + +``` +Limit + Index Scan using integer_encrypted_1000000_ore_index on integer_encrypted_1000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1132, + "Plans": [ + { + "Alias": "integer_encrypted_1000000", + "Async Capable": false, + "Index Cond": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb28c42a974dd413be8197f39a39743b9753fb03ac7a0090988ceed596fc5f2eba8b3a4abd0bfc406e9574de6dfa828633cba8a23a99e5e94c4b769193fd0650114e95a993e451581068267bbb24ce7a639c28974d095366345a81fbe99d57aa9bd954e3e3ffc3c7ee1f18d58cad41b6b32fbec55da6048406616f338a39631e2e84690816e56858ac0d7e517c256131aeb42295fec3a55af4071c5f2dfa0e7ceed54cd4a61153f53806d6e2abaf9f5d36a2c80237b1d7e5baf94dbbb9ba979a269609e5f053f738bbcbc89fbca1a83dc642ef6a578ae5a6d419780fc64837551b1659f91170b8922aa92f8f51d970d45172736424fa44542400d359bfa102f701ad05b10414e6eca20bda1f2964ca7f1322\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Index Name": "integer_encrypted_1000000_ore_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 495002, + "Plan Width": 1132, + "Relation Name": "integer_encrypted_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.8, + "Total Cost": 858388.62 + } + ], + "Startup Cost": 0.8, + "Total Cost": 18.14 + } + } +] +``` + +**10,000,000 rows** + +``` +Limit + Index Scan using integer_encrypted_10000000_ore_index on integer_encrypted_10000000 +``` + +Full `EXPLAIN (FORMAT JSON)`: + +```json +[ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1132, + "Plans": [ + { + "Alias": "integer_encrypted_10000000", + "Async Capable": false, + "Index Cond": "(eql_v2.ore_block_u64_8_256(value) < '(\"{\"\"(\\\\\"\"\\\\\\\\\\\\\\\\x4a4a4a4a7b75d35a800cfa2ff43dcd1b62771a15e33d22e69fda6d34f8e7f8be158e580893b02f753ecf7644fb8c1aba4adf0b01dd621fb107b51a023311e9484b76a975afea7fd7f7d3e6c4a96effd0ce52df7af438bca65a7cbad28e493fef601c3bf913156337fff25712e92fcecde5fdf2c4c33b0dcf6407e8b578be07e00aad33c3a870cb280c255538e575a2753d81ac25925e6e969bb0185a5dc30563df8af424efb304dac7cabc859d0694466c688bf93c2a2442b293763a5ad34a2d6536df4985eb7f0db964c73be7605c18917aec9b6cc58c756c6bfa3c147164f40778499953e816ffd650afae1d4687b519c846d8ce849f2c40d787edb645b20459ad945b1aa86183198c4ab4ebe63c0c0bc89979cf088e025ab91d061f1dce453c8358034893ad2fbe6422dfc34d1b590abe1d6ac9aa223505cc8dd058eb4a4d672e53363c7cfda6d15aa600642077855f590e0df12e0f2ef1cf5c49e56a88affc372b8cfcf5f6a8b866763620d68333ffb15668e72fca5df89a3410446dcfc39a0194d9584518d484a816f719b684bea68e4f6aa80eaed5\\\\\"\")\"\"}\")'::eql_v2.ore_block_u64_8_256)", + "Index Name": "integer_encrypted_10000000_ore_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4950153, + "Plan Width": 1132, + "Relation Name": "integer_encrypted_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.94, + "Total Cost": 8581229.33 + } + ], + "Startup Cost": 0.94, + "Total Cost": 18.27 + } + } +] +``` + +
+ +![Query Performance - ORE/range_lt_ordered_10](query_ore_range_lt_ordered_10_chart.png) + diff --git a/report/v2/query_combo_bloom_ore_order_limit_chart.png b/report/v2/query_combo_bloom_ore_order_limit_chart.png new file mode 100644 index 0000000..369bdfe Binary files /dev/null and b/report/v2/query_combo_bloom_ore_order_limit_chart.png differ diff --git a/report/v2/query_combo_filtered_group_by_chart.png b/report/v2/query_combo_filtered_group_by_chart.png new file mode 100644 index 0000000..5febff5 Binary files /dev/null and b/report/v2/query_combo_filtered_group_by_chart.png differ diff --git a/report/v2/query_combo_top_n_filtered_group_by_chart.png b/report/v2/query_combo_top_n_filtered_group_by_chart.png new file mode 100644 index 0000000..d7288fc Binary files /dev/null and b/report/v2/query_combo_top_n_filtered_group_by_chart.png differ diff --git a/report/v2/query_exact_eql_cast_chart.png b/report/v2/query_exact_eql_cast_chart.png new file mode 100644 index 0000000..6df2150 Binary files /dev/null and b/report/v2/query_exact_eql_cast_chart.png differ diff --git a/report/v2/query_exact_eql_hash_chart.png b/report/v2/query_exact_eql_hash_chart.png new file mode 100644 index 0000000..635d649 Binary files /dev/null and b/report/v2/query_exact_eql_hash_chart.png differ diff --git a/report/v2/query_group_by_low_cardinality_groups_encrypted_chart.png b/report/v2/query_group_by_low_cardinality_groups_encrypted_chart.png new file mode 100644 index 0000000..15216fa Binary files /dev/null and b/report/v2/query_group_by_low_cardinality_groups_encrypted_chart.png differ diff --git a/report/v2/query_group_by_low_cardinality_groups_plaintext_chart.png b/report/v2/query_group_by_low_cardinality_groups_plaintext_chart.png new file mode 100644 index 0000000..ee13ed5 Binary files /dev/null and b/report/v2/query_group_by_low_cardinality_groups_plaintext_chart.png differ diff --git a/report/v2/query_group_by_top_n_groups_encrypted_chart.png b/report/v2/query_group_by_top_n_groups_encrypted_chart.png new file mode 100644 index 0000000..b824c1b Binary files /dev/null and b/report/v2/query_group_by_top_n_groups_encrypted_chart.png differ diff --git a/report/v2/query_group_by_top_n_groups_plaintext_chart.png b/report/v2/query_group_by_top_n_groups_plaintext_chart.png new file mode 100644 index 0000000..00d306c Binary files /dev/null and b/report/v2/query_group_by_top_n_groups_plaintext_chart.png differ diff --git a/report/query_json_contains_chart.png b/report/v2/query_json_contains_chart.png similarity index 100% rename from report/query_json_contains_chart.png rename to report/v2/query_json_contains_chart.png diff --git a/report/v2/query_json_contains_functional_chart.png b/report/v2/query_json_contains_functional_chart.png new file mode 100644 index 0000000..10a859a Binary files /dev/null and b/report/v2/query_json_contains_functional_chart.png differ diff --git a/report/v2/query_json_field_eq_bare_chart.png b/report/v2/query_json_field_eq_bare_chart.png new file mode 100644 index 0000000..3aff0c5 Binary files /dev/null and b/report/v2/query_json_field_eq_bare_chart.png differ diff --git a/report/query_json_field_eq_chart.png b/report/v2/query_json_field_eq_chart.png similarity index 100% rename from report/query_json_field_eq_chart.png rename to report/v2/query_json_field_eq_chart.png diff --git a/report/v2/query_json_field_eq_extractor_chart.png b/report/v2/query_json_field_eq_extractor_chart.png new file mode 100644 index 0000000..8be1467 Binary files /dev/null and b/report/v2/query_json_field_eq_extractor_chart.png differ diff --git a/report/v2/query_json_field_eq_functional_chart.png b/report/v2/query_json_field_eq_functional_chart.png new file mode 100644 index 0000000..a72e520 Binary files /dev/null and b/report/v2/query_json_field_eq_functional_chart.png differ diff --git a/report/query_json_field_order_chart.png b/report/v2/query_json_field_order_chart.png similarity index 100% rename from report/query_json_field_order_chart.png rename to report/v2/query_json_field_order_chart.png diff --git a/report/v2/query_json_field_order_functional_chart.png b/report/v2/query_json_field_order_functional_chart.png new file mode 100644 index 0000000..7938e52 Binary files /dev/null and b/report/v2/query_json_field_order_functional_chart.png differ diff --git a/report/v2/query_match_eql_bloom_chart.png b/report/v2/query_match_eql_bloom_chart.png new file mode 100644 index 0000000..ea33ea1 Binary files /dev/null and b/report/v2/query_match_eql_bloom_chart.png differ diff --git a/report/v2/query_match_eql_cast_firstname_chart.png b/report/v2/query_match_eql_cast_firstname_chart.png new file mode 100644 index 0000000..83e6a29 Binary files /dev/null and b/report/v2/query_match_eql_cast_firstname_chart.png differ diff --git a/report/v2/query_match_eql_cast_lastname_chart.png b/report/v2/query_match_eql_cast_lastname_chart.png new file mode 100644 index 0000000..5805815 Binary files /dev/null and b/report/v2/query_match_eql_cast_lastname_chart.png differ diff --git a/report/v2/query_ore_range_gt_100_chart.png b/report/v2/query_ore_range_gt_100_chart.png new file mode 100644 index 0000000..26b1922 Binary files /dev/null and b/report/v2/query_ore_range_gt_100_chart.png differ diff --git a/report/v2/query_ore_range_gt_10_chart.png b/report/v2/query_ore_range_gt_10_chart.png new file mode 100644 index 0000000..978e6fd Binary files /dev/null and b/report/v2/query_ore_range_gt_10_chart.png differ diff --git a/report/query_ore_range_highly_selective_gt_10_chart.png b/report/v2/query_ore_range_highly_selective_gt_10_chart.png similarity index 100% rename from report/query_ore_range_highly_selective_gt_10_chart.png rename to report/v2/query_ore_range_highly_selective_gt_10_chart.png diff --git a/report/query_ore_range_highly_selective_gt_count_chart.png b/report/v2/query_ore_range_highly_selective_gt_count_chart.png similarity index 100% rename from report/query_ore_range_highly_selective_gt_count_chart.png rename to report/v2/query_ore_range_highly_selective_gt_count_chart.png diff --git a/report/v2/query_ore_range_lt_100_chart.png b/report/v2/query_ore_range_lt_100_chart.png new file mode 100644 index 0000000..79da405 Binary files /dev/null and b/report/v2/query_ore_range_lt_100_chart.png differ diff --git a/report/v2/query_ore_range_lt_10_chart.png b/report/v2/query_ore_range_lt_10_chart.png new file mode 100644 index 0000000..d1f4246 Binary files /dev/null and b/report/v2/query_ore_range_lt_10_chart.png differ diff --git a/report/query_ore_range_lt_hybrid_ordered_10_chart.png b/report/v2/query_ore_range_lt_hybrid_ordered_10_chart.png similarity index 100% rename from report/query_ore_range_lt_hybrid_ordered_10_chart.png rename to report/v2/query_ore_range_lt_hybrid_ordered_10_chart.png diff --git a/report/query_ore_range_lt_natural_ordered_10_chart.png b/report/v2/query_ore_range_lt_natural_ordered_10_chart.png similarity index 100% rename from report/query_ore_range_lt_natural_ordered_10_chart.png rename to report/v2/query_ore_range_lt_natural_ordered_10_chart.png diff --git a/report/v2/query_ore_range_lt_ordered_10_chart.png b/report/v2/query_ore_range_lt_ordered_10_chart.png new file mode 100644 index 0000000..e23d52c Binary files /dev/null and b/report/v2/query_ore_range_lt_ordered_10_chart.png differ diff --git a/report/query_ore_range_selective_gt_100_chart.png b/report/v2/query_ore_range_selective_gt_100_chart.png similarity index 100% rename from report/query_ore_range_selective_gt_100_chart.png rename to report/v2/query_ore_range_selective_gt_100_chart.png diff --git a/report/query_ore_range_selective_gt_count_chart.png b/report/v2/query_ore_range_selective_gt_count_chart.png similarity index 100% rename from report/query_ore_range_selective_gt_count_chart.png rename to report/v2/query_ore_range_selective_gt_count_chart.png diff --git a/report/v3/ore_vs_ope_10000.png b/report/v3/ore_vs_ope_10000.png new file mode 100644 index 0000000..eccf806 Binary files /dev/null and b/report/v3/ore_vs_ope_10000.png differ diff --git a/report/v3/ore_vs_ope_10000.svg b/report/v3/ore_vs_ope_10000.svg new file mode 100644 index 0000000..51c0bf5 --- /dev/null +++ b/report/v3/ore_vs_ope_10000.svg @@ -0,0 +1,1538 @@ + + + + + + + + 2026-07-09T10:39:42.083949 + image/svg+xml + + + Matplotlib v3.10.8, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/report/v3/ore_vs_ope_100000.png b/report/v3/ore_vs_ope_100000.png new file mode 100644 index 0000000..ddd0297 Binary files /dev/null and b/report/v3/ore_vs_ope_100000.png differ diff --git a/report/v3/ore_vs_ope_100000.svg b/report/v3/ore_vs_ope_100000.svg new file mode 100644 index 0000000..068e6d2 --- /dev/null +++ b/report/v3/ore_vs_ope_100000.svg @@ -0,0 +1,1552 @@ + + + + + + + + 2026-07-09T10:39:42.473909 + image/svg+xml + + + Matplotlib v3.10.8, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/report/v3/ore_vs_ope_1000000.png b/report/v3/ore_vs_ope_1000000.png new file mode 100644 index 0000000..8c8feaf Binary files /dev/null and b/report/v3/ore_vs_ope_1000000.png differ diff --git a/report/v3/ore_vs_ope_1000000.svg b/report/v3/ore_vs_ope_1000000.svg new file mode 100644 index 0000000..55ccfc3 --- /dev/null +++ b/report/v3/ore_vs_ope_1000000.svg @@ -0,0 +1,1553 @@ + + + + + + + + 2026-07-09T10:39:42.877463 + image/svg+xml + + + Matplotlib v3.10.8, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/report/v3/ore_vs_ope_10000000.png b/report/v3/ore_vs_ope_10000000.png new file mode 100644 index 0000000..a0a9689 Binary files /dev/null and b/report/v3/ore_vs_ope_10000000.png differ diff --git a/report/v3/ore_vs_ope_10000000.svg b/report/v3/ore_vs_ope_10000000.svg new file mode 100644 index 0000000..e144a81 --- /dev/null +++ b/report/v3/ore_vs_ope_10000000.svg @@ -0,0 +1,1534 @@ + + + + + + + + 2026-07-09T10:39:43.205507 + image/svg+xml + + + Matplotlib v3.10.8, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/report/v3/overhead_vs_plaintext_10000.png b/report/v3/overhead_vs_plaintext_10000.png new file mode 100644 index 0000000..b37dd59 Binary files /dev/null and b/report/v3/overhead_vs_plaintext_10000.png differ diff --git a/report/v3/overhead_vs_plaintext_10000.svg b/report/v3/overhead_vs_plaintext_10000.svg new file mode 100644 index 0000000..096b261 --- /dev/null +++ b/report/v3/overhead_vs_plaintext_10000.svg @@ -0,0 +1,2216 @@ + + + + + + + + 2026-07-09T10:39:42.004551 + image/svg+xml + + + Matplotlib v3.10.8, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/report/v3/overhead_vs_plaintext_100000.png b/report/v3/overhead_vs_plaintext_100000.png new file mode 100644 index 0000000..c589368 Binary files /dev/null and b/report/v3/overhead_vs_plaintext_100000.png differ diff --git a/report/v3/overhead_vs_plaintext_100000.svg b/report/v3/overhead_vs_plaintext_100000.svg new file mode 100644 index 0000000..0f3ebdd --- /dev/null +++ b/report/v3/overhead_vs_plaintext_100000.svg @@ -0,0 +1,2227 @@ + + + + + + + + 2026-07-09T10:39:42.388930 + image/svg+xml + + + Matplotlib v3.10.8, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/report/v3/overhead_vs_plaintext_1000000.png b/report/v3/overhead_vs_plaintext_1000000.png new file mode 100644 index 0000000..a9223ef Binary files /dev/null and b/report/v3/overhead_vs_plaintext_1000000.png differ diff --git a/report/v3/overhead_vs_plaintext_1000000.svg b/report/v3/overhead_vs_plaintext_1000000.svg new file mode 100644 index 0000000..9a3b00b --- /dev/null +++ b/report/v3/overhead_vs_plaintext_1000000.svg @@ -0,0 +1,2259 @@ + + + + + + + + 2026-07-09T10:39:42.791330 + image/svg+xml + + + Matplotlib v3.10.8, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/report/v3/overhead_vs_plaintext_10000000.png b/report/v3/overhead_vs_plaintext_10000000.png new file mode 100644 index 0000000..47e2adb Binary files /dev/null and b/report/v3/overhead_vs_plaintext_10000000.png differ diff --git a/report/v3/overhead_vs_plaintext_10000000.svg b/report/v3/overhead_vs_plaintext_10000000.svg new file mode 100644 index 0000000..780ed6f --- /dev/null +++ b/report/v3/overhead_vs_plaintext_10000000.svg @@ -0,0 +1,2178 @@ + + + + + + + + 2026-07-09T10:39:43.128020 + image/svg+xml + + + Matplotlib v3.10.8, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/report/v3/perf-latency-dark.svg b/report/v3/perf-latency-dark.svg new file mode 100644 index 0000000..8bc3bb3 --- /dev/null +++ b/report/v3/perf-latency-dark.svg @@ -0,0 +1,40 @@ + + +Latency stays flat from 10k → 10M rows. +Median encrypted query latency · EQL v3 · PostgreSQL 17 + +0 + +0.2 + +0.4 + +0.6 +latency (ms) +10k +100k +1M +10M +rows (log scale) + +plaintext Postgres + + + + + +Equality (0.13 ms) + + + + + +JSON field equality (0.11 ms) + + + + + +Range + ORDER BY (0.53 ms) +github.com/cipherstash/benches + \ No newline at end of file diff --git a/report/v3/perf-latency-light.svg b/report/v3/perf-latency-light.svg new file mode 100644 index 0000000..d18dcf3 --- /dev/null +++ b/report/v3/perf-latency-light.svg @@ -0,0 +1,40 @@ + + +Latency stays flat from 10k → 10M rows. +Median encrypted query latency · EQL v3 · PostgreSQL 17 + +0 + +0.2 + +0.4 + +0.6 +latency (ms) +10k +100k +1M +10M +rows (log scale) + +plaintext Postgres + + + + + +Equality (0.13 ms) + + + + + +JSON field equality (0.11 ms) + + + + + +Range + ORDER BY (0.53 ms) +github.com/cipherstash/benches + \ No newline at end of file diff --git a/report/v3/v3_vs_v2_10000.png b/report/v3/v3_vs_v2_10000.png new file mode 100644 index 0000000..cbef794 Binary files /dev/null and b/report/v3/v3_vs_v2_10000.png differ diff --git a/report/v3/v3_vs_v2_10000.svg b/report/v3/v3_vs_v2_10000.svg new file mode 100644 index 0000000..893cfb1 --- /dev/null +++ b/report/v3/v3_vs_v2_10000.svg @@ -0,0 +1,3253 @@ + + + + + + + + 2026-07-09T10:39:41.872289 + image/svg+xml + + + Matplotlib v3.10.8, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/report/v3/v3_vs_v2_100000.png b/report/v3/v3_vs_v2_100000.png new file mode 100644 index 0000000..372322b Binary files /dev/null and b/report/v3/v3_vs_v2_100000.png differ diff --git a/report/v3/v3_vs_v2_100000.svg b/report/v3/v3_vs_v2_100000.svg new file mode 100644 index 0000000..f1104b0 --- /dev/null +++ b/report/v3/v3_vs_v2_100000.svg @@ -0,0 +1,3261 @@ + + + + + + + + 2026-07-09T10:39:42.262854 + image/svg+xml + + + Matplotlib v3.10.8, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/report/v3/v3_vs_v2_1000000.png b/report/v3/v3_vs_v2_1000000.png new file mode 100644 index 0000000..216819a Binary files /dev/null and b/report/v3/v3_vs_v2_1000000.png differ diff --git a/report/v3/v3_vs_v2_1000000.svg b/report/v3/v3_vs_v2_1000000.svg new file mode 100644 index 0000000..da416d9 --- /dev/null +++ b/report/v3/v3_vs_v2_1000000.svg @@ -0,0 +1,3185 @@ + + + + + + + + 2026-07-09T10:39:42.663939 + image/svg+xml + + + Matplotlib v3.10.8, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/report/v3/v3_vs_v2_10000000.png b/report/v3/v3_vs_v2_10000000.png new file mode 100644 index 0000000..352f51a Binary files /dev/null and b/report/v3/v3_vs_v2_10000000.png differ diff --git a/report/v3/v3_vs_v2_10000000.svg b/report/v3/v3_vs_v2_10000000.svg new file mode 100644 index 0000000..4133b45 --- /dev/null +++ b/report/v3/v3_vs_v2_10000000.svg @@ -0,0 +1,2677 @@ + + + + + + + + 2026-07-09T10:39:43.017225 + image/svg+xml + + + Matplotlib v3.10.8, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/report_benchmarks.py b/report_benchmarks.py index 1e8c543..db9b124 100755 --- a/report_benchmarks.py +++ b/report_benchmarks.py @@ -70,10 +70,17 @@ class ScenarioMetadata: class BenchmarkReporter: - def __init__(self, results_dir: Path, output_file: Path, sql_dir: Optional[Path] = None): + def __init__(self, results_dir: Path, output_file: Path, sql_dir: Optional[Path] = None, + v3: bool = False): self.results_dir = results_dir self.output_file = output_file self.sql_dir = sql_dir or Path("sql") + # EQL v3 mode: results live in the v3/ subdirectories (the committed + # v2 baseline files stay untouched in the parent dirs), and the v3 + # ingest suite has its own bench inventory / filename suffix. + self.v3 = v3 + self.query_dir = results_dir / "query" / "v3" if v3 else results_dir / "query" + self.ingest_dir = results_dir / "ingest" / "v3" if v3 else results_dir / "ingest" self.ingest_results: List[IngestResult] = [] self.query_results: List[QueryResult] = [] # Keyed by (query_type, query_name, row_count) so a scenario can @@ -81,12 +88,34 @@ def __init__(self, results_dir: Path, output_file: Path, sql_dir: Optional[Path] self.metadata: Dict[Tuple[str, str, int], ScenarioMetadata] = {} self.index_cache: Dict[str, str] = {} # Cache for index SQL + # EQL v3 mode: ingest benches are named by the domain type they write, + # which is what "how does each type perform for ingest" actually means. + V3_BENCH_DOMAIN = { + "int": "integer_ord", + "int_ope": "integer_ord_ope", + "string": "text_search", + "category": "text_eq", + "ste_vec_small": "json", + } + + def _bench_label(self, bench_type: str) -> str: + if self.v3: + # alpha.3 moved the per-domain types eql_v3.* -> public.* + return f"public.{self.V3_BENCH_DOMAIN.get(bench_type, bench_type)}" + return bench_type.replace('_', ' ').title() + def load_ingest_results(self): """Load ingest benchmark results""" - ingest_dir = self.results_dir / "ingest" - - for bench_type in ["int", "json_small", "json_large", "string", "ste_vec_small", "ste_vec_large"]: - file_path = ingest_dir / f"encrypt_{bench_type}_combined.json" + ingest_dir = self.ingest_dir + if self.v3: + bench_types = ["int", "int_ope", "string", "category", "ste_vec_small"] + suffix = "_v3" + else: + bench_types = ["int", "json_small", "json_large", "string", "ste_vec_small", "ste_vec_large"] + suffix = "" + + for bench_type in bench_types: + file_path = ingest_dir / f"encrypt_{bench_type}{suffix}_combined.json" if not file_path.exists(): print(f"Warning: {file_path} not found, skipping", file=sys.stderr) @@ -106,7 +135,7 @@ def load_ingest_results(self): def load_query_results(self): """Load query benchmark results from criterion JSON output""" - query_dir = self.results_dir / "query" + query_dir = self.query_dir for json_file in query_dir.glob("*.json"): # Parse filename: {query_type}_rows_{count}.json @@ -166,7 +195,7 @@ def load_query_results(self): def load_query_metadata(self): """Load `*_metadata_*.json` sidecars written by each bench at startup.""" - query_dir = self.results_dir / "query" + query_dir = self.query_dir meta_pattern = re.compile(r'^(.+)_metadata_(\d+)$') for json_file in query_dir.glob("*_metadata_*.json"): m = meta_pattern.match(json_file.stem) @@ -758,10 +787,13 @@ def generate_report(self): self._write_header(f, scenario_pages) self._write_ingest_section(f) self._write_query_overview(f, scenario_pages) + if self.v3: + self._write_v2_comparison(f) + self._write_plaintext_comparison(f) self._write_footer(f) def _write_header(self, f, scenario_pages: Dict[str, str]): - f.write("# Benchmark Report\n\n") + f.write(f"# Benchmark Report{' (EQL v3)' if self.v3 else ''}\n\n") f.write("This report summarises the performance benchmarks for encrypted database operations. " "Per-query-type detail lives on its own page — click through from the " "Query Performance section below.\n\n") @@ -771,13 +803,17 @@ def _write_header(self, f, scenario_pages: Dict[str, str]): # Add subsections for each ingest type ingest_types = sorted(set(r.bench_type for r in self.ingest_results)) for it in ingest_types: - title = it.replace('_', ' ').title() - anchor = it.replace('_', '-') + title = self._bench_label(it) + # GitHub-style anchor: lowercase, drop dots, spaces -> hyphens. + anchor = title.lower().replace('.', '').replace(' ', '-') f.write(f" - [{title}](#{anchor})\n") f.write("2. [Query Performance](#query-performance)\n") for qt in sorted(scenario_pages.keys()): f.write(f" - [{qt} Queries]({scenario_pages[qt]})\n") + if self.v3: + f.write("3. [Comparison vs EQL 2.3](#comparison-vs-eql-23)\n") + f.write("4. [Comparison vs plaintext PostgreSQL](#comparison-vs-plaintext-postgresql)\n") f.write("\n---\n\n") @@ -800,7 +836,7 @@ def _write_ingest_section(self, f): # Sort by num_records results.sort(key=lambda x: x.num_records) - f.write(f"### {bench_type.replace('_', ' ').title()}\n\n") + f.write(f"### {self._bench_label(bench_type)}\n\n") # Add descriptions for each type descriptions = { @@ -847,7 +883,7 @@ def _create_ingest_throughput_chart(self, results: List[IngestResult], bench_typ ax.bar(range(len(records)), throughput, color='steelblue') ax.set_xlabel('Number of Records') ax.set_ylabel('Throughput (records/sec)') - ax.set_title(f'Ingest Throughput - {bench_type.replace("_", " ").title()}') + ax.set_title(f'Ingest Throughput - {self._bench_label(bench_type)}') ax.set_xticks(range(len(records))) ax.set_xticklabels([f"{r:,}" for r in records]) ax.grid(axis='y', alpha=0.3) @@ -872,7 +908,7 @@ def _create_ingest_time_chart(self, results: List[IngestResult], bench_type: str ax.bar(range(len(records)), times, color='coral') ax.set_xlabel('Number of Records') ax.set_ylabel('Total Time (seconds)') - ax.set_title(f'Ingest Total Time - {bench_type.replace("_", " ").title()}') + ax.set_title(f'Ingest Total Time - {self._bench_label(bench_type)}') ax.set_xticks(range(len(records))) ax.set_xticklabels([f"{r:,}" for r in records]) ax.grid(axis='y', alpha=0.3) @@ -929,7 +965,7 @@ def _create_comparison_throughput_chart(self, comparison_data: Dict[str, IngestR # Sort by throughput descending (highest on left) sorted_items = sorted(comparison_data.items(), key=lambda x: x[1].throughput, reverse=True) bench_types = [item[0] for item in sorted_items] - labels = [bt.replace('_', ' ').title() for bt in bench_types] + labels = [self._bench_label(bt) for bt in bench_types] throughputs = [comparison_data[bt].throughput for bt in bench_types] # Use different colors for each bar @@ -961,7 +997,7 @@ def _create_comparison_time_chart(self, comparison_data: Dict[str, IngestResult] # Sort by throughput descending (highest on left) to match throughput chart order sorted_items = sorted(comparison_data.items(), key=lambda x: x[1].throughput, reverse=True) bench_types = [item[0] for item in sorted_items] - labels = [bt.replace('_', ' ').title() for bt in bench_types] + labels = [self._bench_label(bt) for bt in bench_types] times = [comparison_data[bt].total_time for bt in bench_types] # Use different colors for each bar @@ -972,7 +1008,7 @@ def _create_comparison_time_chart(self, comparison_data: Dict[str, IngestResult] ax.set_ylabel('Total Time (seconds)', fontsize=12) title = f'Total Ingest Time Comparison at {row_count:,} Records' if exclude_label: - title += f' (excluding {exclude_label.replace("_", " ").title()})' + title += f' (excluding {self._bench_label(exclude_label)})' ax.set_title(title, fontsize=14, fontweight='bold') ax.set_xticks(range(len(bench_types))) ax.set_xticklabels(labels, rotation=45, ha='right') @@ -1248,6 +1284,76 @@ def _create_query_chart(self, results: List[QueryResult], query_type: str, plt.savefig(output_path, dpi=100, bbox_inches='tight') plt.close() + def _write_v2_comparison(self, f): + """v3-vs-v2 summary: flagged deltas + charts, from the committed v2 + baseline. Full 115-pair table + methodology in V3_COMPARISON.md.""" + import report_v3_compare as cmp + + v2q = cmp.load_criterion_dir(cmp.V2_QUERY_DIR) + v3q = cmp.load_criterion_dir(cmp.V3_QUERY_DIR) + rows = cmp.build_regression_rows(v2q, v3q, 10.0) + + f.write("## Comparison vs EQL 2.3\n\n") + n_reg = sum(1 for r in rows if r["flag"] == "REGRESSION") + n_imp = sum(1 for r in rows if r["flag"] == "improvement") + n_sem = sum(1 for r in rows if r["flag"] == "semantics changed") + f.write(f"{len(rows)} comparable scenario/tier pairs against the committed " + f"EQL 2.3 baseline: **{n_reg} regressions**, **{n_imp} improvements** " + f"(beyond ±10%), {n_sem} pairs whose SQL semantics changed between " + "versions (annotated, not flagged). Full table, methodology, and " + "index-engagement audit: [V3_COMPARISON.md](V3_COMPARISON.md).\n\n") + + flagged = [r for r in rows if r["flag"] in ("REGRESSION", "improvement")] + if flagged: + f.write("| Scenario | Tier | v2 median | v3 median | Δ | |\n") + f.write("|-|-|-|-|-|-|\n") + for r in sorted(flagged, key=lambda r: -r["delta_pct"]): + mark = "🔴" if r["flag"] == "REGRESSION" else "🟢" + f.write(f"| {cmp.scenario_prefix(r['id'])} | {cmp.tier_of(r['id'])} " + f"| {cmp.fmt_ns(r['v2_ns'])} | {cmp.fmt_ns(r['v3_ns'])} " + f"| {r['delta_pct']:+.1f}% | {mark} |\n") + f.write("\n") + + for tier in sorted({cmp.tier_of(cid) for cid in v3q}, key=int): + chart = Path("report/v3") / f"v3_vs_v2_{tier}.png" + if chart.exists(): + f.write(f"![v3 vs v2 at {int(tier):,} rows](v3/v3_vs_v2_{tier}.png)\n\n") + + def _write_plaintext_comparison(self, f): + """Encrypted-vs-plaintext ratios for the headline scenarios, from the + PLAINTEXT bench family (same query shapes, btree/GIN-indexed + plaintext tables).""" + import report_v3_compare as cmp + + v3q = cmp.load_criterion_dir(cmp.V3_QUERY_DIR) + tiers = sorted({cmp.tier_of(cid) for cid in v3q if cid.startswith("PLAINTEXT/")}, + key=int) + + f.write("## Comparison vs plaintext PostgreSQL\n\n") + f.write("The same query shapes against plaintext tables with equivalent " + "indexes (see `benches/plaintext_v3.rs`). Ratios are encrypted ÷ " + "plaintext median; the JSON plaintext baseline is an unindexed " + "`->` filter, hence ratios below 1.\n\n") + f.write("| Scenario | " + " | ".join(f"{int(t):,} rows" for t in tiers) + " |\n") + f.write("|-" * (len(tiers) + 1) + "|\n") + for enc_prefix, plain in cmp.PLAINTEXT_MAP.items(): + cells = [] + for t in tiers: + enc = v3q.get(f"{enc_prefix}/{t}") + if plain.startswith("@"): + pt = v3q.get(f"{plain[1:]}/{t}") + else: + pt = v3q.get(f"PLAINTEXT/plaintext/{plain}/{t}") + cells.append(f"{cmp.fmt_ns(enc)} ({enc / pt:.1f}×)" if enc and pt else "—") + f.write(f"| {enc_prefix} | " + " | ".join(cells) + " |\n") + f.write("\n") + + for t in tiers: + chart = Path("report/v3") / f"overhead_vs_plaintext_{t}.png" + if chart.exists(): + f.write(f"![encrypted vs plaintext at {int(t):,} rows]" + f"(v3/overhead_vs_plaintext_{t}.png)\n\n") + def _write_footer(self, f): f.write("\n---\n\n") f.write("*Report generated by `report_benchmarks.py`*\n") @@ -1259,10 +1365,19 @@ def main(): help="Directory containing benchmark results (default: results)") parser.add_argument("--sql-dir", type=Path, default=Path("sql"), help="Directory containing SQL schema and index files (default: sql)") - parser.add_argument("--output", "-o", type=Path, default=Path("report/BENCHMARK_REPORT.md"), - help="Output file path (default: report/BENCHMARK_REPORT.md)") - + parser.add_argument("--output", "-o", type=Path, default=None, + help="Output file path (default: report/BENCHMARK_REPORT.md, " + "or report/v2/BENCHMARK_REPORT.md with --v2)") + parser.add_argument("--v2", action="store_true", + help="rebuild the archived EQL 2.3 report from the committed v2 " + "baseline results into report/v2/ (default builds the main " + "EQL v3 report from results/{query,ingest}/v3/)") + args = parser.parse_args() + args.v3 = not args.v2 + if args.output is None: + args.output = Path("report/v2/BENCHMARK_REPORT.md") if args.v2 \ + else Path("report/BENCHMARK_REPORT.md") if not args.results_dir.exists(): print(f"Error: Results directory '{args.results_dir}' does not exist", file=sys.stderr) @@ -1271,7 +1386,7 @@ def main(): # Create output directory if it doesn't exist args.output.parent.mkdir(parents=True, exist_ok=True) - reporter = BenchmarkReporter(args.results_dir, args.output, args.sql_dir) + reporter = BenchmarkReporter(args.results_dir, args.output, args.sql_dir, v3=args.v3) print("Loading ingest results...") reporter.load_ingest_results() diff --git a/report_flat_latency.py b/report_flat_latency.py new file mode 100644 index 0000000..f4b9b1a --- /dev/null +++ b/report_flat_latency.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python3 +"""CIP-3361: the cipherstash/stack README "flat latency" chart. + +Generates a theme-aware light/dark SVG pair showing median encrypted-query +latency vs table size — three flat lines near the floor plus a subtle +plaintext-baseline band. Palette matches the stack README architecture +diagrams (lime + orange accents, warm ink/surfaces). + +Data source: EQL v3 criterion results in results/query/v3/. Tiers are +auto-detected (the callout adapts: "10k → 1M" vs "10k → 10M" once the 10M +tier lands). Series: + + Equality EXACT/exact/eql_cast orange, circle + JSON field equality JSON/json/field_eq/functional lime, square + Range + ORDER BY ORE/ore/range_lt_ordered_10 ink, triangle, dashed + +Accessibility notes (brand palette is fixed; the validator flags the +lime↔orange pair in the CVD floor band and the ink line reads gray): every +series carries a DISTINCT marker shape and a direct end-of-line label, and +the ink line is dashed — identity never rides on hue alone. The plaintext +band is a fill with its own label. + +Usage: + python3 report_flat_latency.py [--out-dir report/v3] + +Outputs perf-latency-light.svg / perf-latency-dark.svg. Copy into +cipherstash/stack docs/images/ as perf-latency-{light,dark}.svg with the + embed per docs/plans/readme-visual-assets.md (Asset 3). + +Alt text (from the spec): + Line chart of median encrypted-query latency versus table size. + Equality, range, and JSON queries hold steady at well under one + millisecond as row counts grow from ten thousand to ten million. +""" + +import argparse +import json +import math +import sys +from pathlib import Path + +V3_DIR = Path(__file__).parent / "results" / "query" / "v3" + +SERIES = [ + # (label, criterion id prefix, color role, marker, dashed) + ("Equality", "EXACT/exact/eql_cast", "accent2", "circle", False), + ("JSON field equality", "JSON/json/field_eq/functional", "accent1", "square", False), + ("Range + ORDER BY", "ORE/ore/range_lt_ordered_10", "ink", "triangle", True), +] + +# Band = the two btree-indexed plaintext baselines (both flat ~0.1 ms). The +# json plaintext baseline is deliberately excluded: it is an unindexed +# LIMIT-scan whose growth with table size is an artifact of the baseline +# shape, not a fair "native Postgres" reference for this chart. +PLAINTEXT_PREFIXES = [ + "PLAINTEXT/plaintext/exact_eq", + "PLAINTEXT/plaintext/range_lt_ordered_10", +] + +THEMES = { + "light": { + "surface": "#f4f3ec", + "ink": "#060606", + "muted": "#6b6a63", + "grid": "#e2e0d3", + "accent1": "#5f7404", # lime/olive + "accent2": "#cc3d00", # orange + "band": "#e2e0d3", + }, + "dark": { + "surface": "#0d0d0d", + "ink": "#eae8dd", + "muted": "#8f8e85", + "grid": "#242420", + "accent1": "#c8f031", + "accent2": "#ff5b1f", + "band": "#1c1c18", + }, +} + +TIER_LABELS = {10_000: "10k", 100_000: "100k", 1_000_000: "1M", 10_000_000: "10M"} + + +def load_medians(): + """{criterion_id: median_ms} across every v3 result file.""" + out = {} + for f in sorted(V3_DIR.glob("*_rows_*.json")): + for line in f.read_text().splitlines(): + if '"benchmark-complete"' not in line: + continue + try: + d = json.loads(line) + except json.JSONDecodeError: + continue + m = d.get("median", {}).get("estimate") + if m is not None: + out[d["id"]] = m / 1e6 + return out + + +def collect(medians): + """Return (tiers, series_points, band) where series_points[label] and + band are {tier: ms}. Tiers = those present in EVERY line series.""" + tiers = None + series_points = {} + for label, prefix, *_ in SERIES: + pts = {} + for t in TIER_LABELS: + v = medians.get(f"{prefix}/{t}") + if v is not None: + pts[t] = v + series_points[label] = pts + tiers = set(pts) if tiers is None else tiers & set(pts) + tiers = sorted(tiers or []) + + band = {} + for t in tiers: + vals = [medians[f"{p}/{t}"] for p in PLAINTEXT_PREFIXES if f"{p}/{t}" in medians] + if vals: + band[t] = (min(vals), max(vals)) + return tiers, series_points, band + + +def marker_svg(shape, x, y, color, surface): + """Distinct marker per series (CVD relief), with a surface ring.""" + ring = f'stroke="{surface}" stroke-width="2"' + if shape == "circle": + return f'' + if shape == "square": + return (f'') + # triangle + return (f'') + + +def render(theme_name, tiers, series_points, band, out_path): + c = THEMES[theme_name] + W, H = 760, 420 + ML, MR, MT, MB = 64, 226, 76, 52 + plot_w, plot_h = W - ML - MR, H - MT - MB + + xs = {t: ML + plot_w * i / (len(tiers) - 1) for i, t in enumerate(tiers)} + + y_max = max(v for pts in series_points.values() for v in pts.values()) + if band: + y_max = max(y_max, max(hi for _, hi in band.values())) + y_max *= 1.35 + + def Y(v): + return MT + plot_h * (1 - v / y_max) + + top_label = TIER_LABELS[tiers[-1]] + parts = [ + f'', + f'', + # Callout (the headline claim) + f'' + f'Latency stays flat from 10k → {top_label} rows.', + f'' + f'Median encrypted query latency · EQL v3 · PostgreSQL 17', + ] + + # y gridlines + labels (recessive) + step = 0.2 if y_max <= 1.2 else 0.5 + v = 0.0 + while v <= y_max + 1e-9: + y = Y(v) + parts.append(f'') + parts.append(f'{v:g}') + v += step + parts.append(f'latency (ms)') + + # x labels + for t in tiers: + parts.append(f'{TIER_LABELS[t]}') + parts.append(f'rows (log scale)') + + # plaintext band + if band: + top_pts = " ".join(f'{xs[t]:.1f},{Y(band[t][1]):.1f}' for t in tiers) + bot_pts = " ".join(f'{xs[t]:.1f},{Y(band[t][0]):.1f}' for t in reversed(tiers)) + parts.append(f'') + # Label the band at its left edge, BELOW the band — above it sits the + # equality line, and the right edge is where the series' direct + # labels stack. + t_first = tiers[0] + parts.append(f'plaintext Postgres') + + # series lines + markers + direct labels + label_ys = [] + for label, _, role, marker, dashed in SERIES: + pts = series_points[label] + color = c[role] + dash = ' stroke-dasharray="7 5"' if dashed else "" + path = " ".join(f'{xs[t]:.1f},{Y(pts[t]):.1f}' for t in tiers) + parts.append(f'') + for t in tiers: + parts.append(marker_svg(marker, xs[t], Y(pts[t]), color, c["surface"])) + # direct label, collision-nudged + t_last = tiers[-1] + ly = Y(pts[t_last]) + 4 + while any(abs(ly - prev) < 16 for prev in label_ys): + ly += 16 + label_ys.append(ly) + parts.append(f'{label} ' + f'({pts[t_last]:.2f} ms)') + + # attribution caption + parts.append(f'github.com/cipherstash/benches') + parts.append("") + + out_path.write_text("\n".join(parts)) + print(f"chart: {out_path}") + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--out-dir", type=Path, default=Path("report/v3")) + args = ap.parse_args() + + medians = load_medians() + if not medians: + sys.exit("no v3 results under results/query/v3/") + tiers, series_points, band = collect(medians) + if len(tiers) < 2: + sys.exit(f"need >= 2 complete tiers across all series, found {tiers}") + + args.out_dir.mkdir(parents=True, exist_ok=True) + for theme in THEMES: + render(theme, tiers, series_points, band, + args.out_dir / f"perf-latency-{theme}.svg") + + +if __name__ == "__main__": + main() diff --git a/report_ingest.py b/report_ingest.py index 98c53fe..b40e17c 100644 --- a/report_ingest.py +++ b/report_ingest.py @@ -54,16 +54,20 @@ def format_age(mtime: float, now: float) -> str: return f"{delta // (86400 * 7)}w ago" -def collect_ingest(results_dir, prefix): +def collect_ingest(results_dir, prefix, v3=False): """Walk `results_dir/ingest/*_combined.json` and flatten the inner results. + With `v3=True`, scans `results_dir/ingest/v3/` instead — the EQL v3 + ingest results live in a subdirectory so the committed v2 baseline files + stay untouched (see report_v3_compare.py). + Returns a list of `(throughput, records, total_time, mtime, bench)` tuples — unsorted. Bench name (the filename minus `_combined`) is filtered by `prefix` (str.startswith) when given. """ - ingest_dir = results_dir / "ingest" + ingest_dir = results_dir / "ingest" / "v3" if v3 else results_dir / "ingest" if not ingest_dir.is_dir(): - sys.exit(f"no `ingest/` subdirectory under {results_dir}") + sys.exit(f"no `{ingest_dir}` directory") rows = [] @@ -99,23 +103,26 @@ def main(): formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument("--results-dir", type=Path, default=Path("results"), help="benchmark results root (default ./results)") + parser.add_argument("--v3", action="store_true", + help="scan the EQL v3 results (results/ingest/v3/) instead of the v2 baseline") parser.add_argument("prefix", nargs="?", default=None, help="if given, only include benches whose name starts with this prefix " "(e.g. 'encrypt_int', 'encrypt_json')") args = parser.parse_args() - rows = collect_ingest(args.results_dir, args.prefix) + rows = collect_ingest(args.results_dir, args.prefix, v3=args.v3) # Highest throughput first. rows.sort(key=lambda r: r[0], reverse=True) prefix_note = f" matching prefix '{args.prefix}'" if args.prefix else "" + scanned = f"{args.results_dir}/ingest/v3" if args.v3 else f"{args.results_dir}/ingest" if not rows: - print(f"No ingest results found under {args.results_dir}/ingest{prefix_note}.") + print(f"No ingest results found under {scanned}{prefix_note}.") return print(f"All {len(rows)} ingest scenarios{prefix_note} " - f"(scanned {args.results_dir}/ingest), highest throughput first:") + f"(scanned {scanned}), highest throughput first:") print() now = time.time() diff --git a/report_v3_compare.py b/report_v3_compare.py new file mode 100644 index 0000000..7511cd3 --- /dev/null +++ b/report_v3_compare.py @@ -0,0 +1,624 @@ +#!/usr/bin/env python3 +"""EQL v3 vs v2 comparison report + docs/marketing charts. + +Joins criterion query results and hyperfine ingest results across the two +result trees: + + v2 (committed baseline): results/query/*_rows_*.json + results/ingest/*_combined.json + v3 (this branch's runs): results/query/v3/*_rows_*.json + results/ingest/v3/*_combined.json + +and emits: + + report/V3_COMPARISON.md regression tables + index-engagement audit + report/v3/*.png|.svg charts (v3-vs-v2, encrypted-vs-plaintext + overhead, ORE-vs-OPE) + +Usage: + python3 report_v3_compare.py [--threshold 10] + +`--threshold` is the regression flag threshold in percent (v3 slower than v2 +by more than this on a comparable scenario ⇒ REGRESSION). + +Scenario ids are shared between versions by construction (the v3 benches +reuse the v2 criterion ids), so the join key is the full criterion id, +e.g. ``EXACT/exact/eql_cast/10000``. Scenarios whose SQL semantics changed +between versions are annotated from SEMANTICS_CHANGED rather than flagged. +""" + +import argparse +import json +import re +import sys +from pathlib import Path + +ROOT = Path(__file__).parent +V2_QUERY_DIR = ROOT / "results" / "query" +V3_QUERY_DIR = ROOT / "results" / "query" / "v3" +V2_INGEST_DIR = ROOT / "results" / "ingest" +V3_INGEST_DIR = ROOT / "results" / "ingest" / "v3" +REPORT_DIR = ROOT / "report" +CHART_DIR = REPORT_DIR / "v3" + +# Scenario-id prefixes whose v2/v3 SQL differs in meaning, with the note the +# report shows instead of a bare REGRESSION flag. +SEMANTICS_CHANGED = { + "MATCH/match/eql_cast_firstname": "v2 LIKE → v3 @> (no LIKE operator in v3; same bloom semantics)", + "MATCH/match/eql_cast_lastname": "v2 LIKE → v3 @> (no LIKE operator in v3; same bloom semantics)", + "MATCH/match_decrypt/eql_cast_firstname": "v2 LIKE → v3 @>", + "MATCH/match_decrypt/eql_cast_lastname": "v2 LIKE → v3 @>", + "EXACT/exact/eql_hash": "index type changed: v2 hash → v3 btree on eq_term", + "EXACT/exact_decrypt/eql_hash": "index type changed: v2 hash → v3 btree on eq_term", + "COMBO/combo/bloom_ore_order_limit": "v2 LIKE → v3 @>", + "COMBO/combo/filtered_group_by": "v2 LIKE → v3 @>", + "COMBO/combo/top_n_filtered_group_by": "v2 LIKE → v3 @>", + # DIAGNOSED bench artifact, not a v3 defect: the sampled needle matches + # EVERY row (selector-lookup hm — the only hm-bearing sv entry in the + # 2.3+ wire format). v3 extractor now runs eql_v3.jsonb_contains (the + # jsonb_array GIN recipe, single-entry needle), replacing v2's typed + # stevec_query GIN. sqlx's prepared statements flip to a generic plan + # after 5 executions; on the every-row needle the plan is unstable — + # sometimes an early-stop seq scan (~0.6ms), sometimes a full-posting-list + # GIN bitmap before LIMIT (tens of ms), which is why the number swings + # non-monotonically across tiers (e.g. 72ms @1M vs 0.6ms @10M). With a + # realistic selective needle the GIN bitmap is small and the plan is + # optimal. + "JSON/json/field_eq/extractor": "v2 stevec_query GIN → v3 jsonb_contains; every-row-needle plan instability (see notes)", +} + +# Extra context notes keyed the same way (shown alongside numbers). +NOTES = { + "EXACT/exact/eql_cast": "v3 string rows are wider (text_search adds an ORE term v2 didn't carry)", + "MATCH/match/eql_bloom": "v3 GIN uses native array_ops on the bloom term (no shipped opclass)", + # The sampled field_eq needle is the selector-lookup entry's hm (the only + # hm-bearing sv entry in the 2.3+ wire format) — it matches EVERY row, in + # v2 and v3 alike, so these scenarios measure "fetch first 10 of + # everything", not selective equality. Plans are identical across + # versions (extractor: seq scan in both; bare/functional: btree in + # both) — deltas isolate per-row extractor cost. + "JSON/json/field_eq/bare": "same btree plan as v2 (needle matches every row in both versions)", + "JSON/json/field_eq/functional": "same btree plan as v2 (needle matches every row in both versions)", + # v3 now runs eql_v3.jsonb_contains → jsonb_array(value) @> jsonb_array(needle), + # the SAME recipe/GIN as v2 (no longer semantics-changed). The 10M delta + # reflects GIN posting-list growth over the public.json domain vs the v2 + # composite, not a recipe change. + "JSON/json/contains/functional": "same jsonb_array GIN recipe as v2; 10M delta is posting-list/data-shape", + # Same-day v2 re-measurement (2026-07-04) adjudicated the 10M flags vs + # the May-measured baseline: cross-session drift is ±8-19% at these + # scales. v3 vs SAME-DAY v2: eql_cast -3.3%, top_n GROUP BY -0.7%, + # low-cardinality GROUP BY +6.4% — parity within threshold. + "EXACT/exact/eql_cast": "10M flag adjudicated as baseline drift: v3 is 3.3% FASTER than same-day v2", + "GROUP_BY/group_by/low_cardinality_groups_encrypted": "10M flag adjudicated as baseline drift: +6.4% vs same-day v2", + "GROUP_BY/group_by/top_n_groups_encrypted": "10M flag adjudicated as baseline drift: parity (-0.7%) vs same-day v2", +} + +# Notes for the ingest comparison, keyed by v3 bench name. +INGEST_NOTES = { + "encrypt_string_v3": ( + "NOT a conversion regression: v3's only eq+match text domain " + "(text_search) also REQUIRES the ORE term, so the config adds " + "Index::new_ore() that v2's unique+match didn't carry — string " + "ingest is capped at ORE-generation speed. A v3 hm+bf-only domain " + "would restore v2 throughput." + ), + "encrypt_int_ope_v3": ( + "real CLLW-OPE op terms (cipherstash-client 0.38.1, Index::new_ope)" + ), +} + +# v3 scenarios whose plan MUST show an index; empty indexes_used ⇒ audit FAIL. +# (Non-selective ORE/OPE range scans may legitimately seq-scan at scale, so +# only the ordered/eq/json/match shapes are gated.) +EXPECTED_INDEX_PATTERNS = [ + r"^EXACT/exact/", + r"^ORE/ore/range_lt_ordered_10/", + r"^OPE/ope/range_lt_ordered_10/", + r"^MATCH/match/(?!.*_noindex)", + # field_eq/extractor is exempt: its needle matches every row (selector- + # lookup hm), so a seq scan is the CORRECT plan — v2 planned it the same + # way. Gated scenarios are the selective/ordered JSON shapes. + r"^JSON/json/(contains|field_order)/", + r"^JSON/json/field_eq/(bare|functional)/", + r"^SMOKE_V3/smoke/.*/range_gt_ordered_10/", +] + +# Encrypted ↔ plaintext scenario mapping for the overhead chart/table. +# encrypted id prefix -> plaintext scenario name +PLAINTEXT_MAP = { + "EXACT/exact/eql_cast": "exact_eq", + "ORE/ore/range_gt_10": "range_gt_10", + "ORE/ore/range_lt_ordered_10": "range_lt_ordered_10", + "OPE/ope/range_gt_10": "range_gt_10", + "OPE/ope/range_lt_ordered_10": "range_lt_ordered_10", + "JSON/json/contains/functional": "json_contains", + "JSON/json/field_eq/bare": "json_field_eq", + "GROUP_BY/group_by/low_cardinality_groups_encrypted": "@GROUP_BY/group_by/low_cardinality_groups_plaintext", + "GROUP_BY/group_by/top_n_groups_encrypted": "@GROUP_BY/group_by/top_n_groups_plaintext", +} + +# Chart colors — validated 3-slot categorical palette (dataviz skill, +# reference palette slots 1-3; light surface). Aqua/yellow sit below 3:1 on +# the surface, so every bar carries a direct value label. +COLOR_V2 = "#2a78d6" # blue — EQL v2 baseline +COLOR_V3 = "#1baf7a" # aqua — EQL v3 +COLOR_PLAIN = "#a8a69e" # neutral — plaintext baseline (identity is + # 'no encryption', gray keeps it recessive) +COLOR_ORE = "#2a78d6" # blue — ORE path +COLOR_OPE = "#1baf7a" # aqua — OPE path +SURFACE = "#fcfcfb" +TEXT_PRIMARY = "#0b0b0b" +TEXT_SECONDARY = "#52514e" +GRID = "#e4e2dc" + + +def load_criterion_dir(path: Path) -> dict: + """{criterion_id: median_ns} across every *_rows_*.json in `path`.""" + out = {} + for f in sorted(path.glob("*_rows_*.json")): + for line in f.read_text().splitlines(): + line = line.strip() + if not line: + continue + try: + data = json.loads(line) + except json.JSONDecodeError: + continue + if data.get("reason") != "benchmark-complete": + continue + median = data.get("median", {}).get("estimate") + if median is not None: + out[data["id"]] = median + return out + + +def load_metadata_dir(path: Path) -> dict: + """{scenario_id: {query, indexes_used, rows_returned}}.""" + out = {} + for f in sorted(path.glob("*_metadata_*.json")): + data = json.loads(f.read_text()) + for s in data.get("scenarios", []): + out[s["id"]] = { + "query": s.get("query", ""), + "indexes_used": s.get("indexes_used", []), + "rows_returned": s.get("rows_returned", 0), + } + return out + + +def load_ingest_dir(path: Path) -> dict: + """{bench_name: {num_records: throughput_rps}}.""" + out = {} + for f in sorted(path.glob("*_combined.json")): + data = json.loads(f.read_text()) + name = f.name.replace("_combined.json", "") + out[name] = { + r["num_records"]: r["throughput_records_per_second"] + for r in data.get("results", []) + } + return out + + +def scenario_prefix(cid: str) -> str: + """Strip the trailing tier segment from a criterion id.""" + return cid.rsplit("/", 1)[0] + + +def tier_of(cid: str) -> str: + return cid.rsplit("/", 1)[1] + + +def fmt_ns(ns: float) -> str: + if ns >= 1e9: + return f"{ns / 1e9:.2f} s" + if ns >= 1e6: + return f"{ns / 1e6:.2f} ms" + if ns >= 1e3: + return f"{ns / 1e3:.1f} µs" + return f"{ns:.0f} ns" + + +def semantics_note(cid: str): + return SEMANTICS_CHANGED.get(scenario_prefix(cid)) + + +def build_regression_rows(v2: dict, v3: dict, threshold: float): + rows = [] + for cid in sorted(set(v2) & set(v3)): + d = (v3[cid] - v2[cid]) / v2[cid] * 100.0 + note = semantics_note(cid) + flag = "" + if note: + flag = "semantics changed" + elif "_decrypt/" in cid: + # Decrypt variants are dominated by ZeroKMS round-trips (~25 ms) + # — cross-run network variance alone exceeds any sane threshold, + # and the v2 baseline was measured under a different client + # version. Informational only; never flagged. + flag = "" + elif d > threshold: + flag = "REGRESSION" + elif d < -threshold: + flag = "improvement" + rows.append( + { + "id": cid, + "v2_ns": v2[cid], + "v3_ns": v3[cid], + "delta_pct": d, + "flag": flag, + "note": note or NOTES.get(scenario_prefix(cid), ""), + } + ) + return rows + + +# --- Charts --------------------------------------------------------------- + + +def _style_axes(ax): + ax.set_facecolor(SURFACE) + for spine in ("top", "right", "left"): + ax.spines[spine].set_visible(False) + ax.spines["bottom"].set_color(GRID) + ax.tick_params(colors=TEXT_SECONDARY, labelsize=9) + ax.xaxis.grid(True, color=GRID, linewidth=0.6) + ax.set_axisbelow(True) + + +def _save(fig, name: str): + CHART_DIR.mkdir(parents=True, exist_ok=True) + for ext in ("png", "svg"): + fig.savefig(CHART_DIR / f"{name}.{ext}", dpi=150, bbox_inches="tight", + facecolor=SURFACE) + print(f"chart: report/v3/{name}.png (+.svg)") + + +def grouped_hbar(pairs, series_names, series_colors, title, name, unit="ms"): + """Horizontal grouped bars. pairs = [(label, [val_per_series…]), …].""" + import matplotlib + matplotlib.use("Agg") + import matplotlib.pyplot as plt + import numpy as np + + n_series = len(series_names) + height = max(2.2, 0.42 * len(pairs) * n_series + 1.2) + fig, ax = plt.subplots(figsize=(9, height)) + fig.patch.set_facecolor(SURFACE) + _style_axes(ax) + + y = np.arange(len(pairs)) + bar_h = 0.78 / n_series + for i, (sname, color) in enumerate(zip(series_names, series_colors)): + vals = [p[1][i] for p in pairs] + offs = y + (i - (n_series - 1) / 2) * (bar_h + 0.04) + bars = ax.barh(offs, vals, height=bar_h, color=color, label=sname, + zorder=3) + # Direct value labels (relief for below-3:1 palette slots). + for b, v in zip(bars, vals): + if v is None: + continue + ax.text(b.get_width() * 1.01, b.get_y() + b.get_height() / 2, + f"{v:,.2f}" if v < 100 else f"{v:,.0f}", + va="center", ha="left", fontsize=8, color=TEXT_PRIMARY) + + ax.set_yticks(y) + ax.set_yticklabels([p[0] for p in pairs], fontsize=9, color=TEXT_PRIMARY) + ax.invert_yaxis() + ax.set_xlabel(f"median latency ({unit}) — lower is better", + fontsize=9, color=TEXT_SECONDARY) + # Title on its own band, legend in the gap beneath it — neither can + # collide with the other or with long bars. + ax.set_title(title, fontsize=11, color=TEXT_PRIMARY, loc="left", pad=34) + ax.legend(frameon=False, fontsize=9, labelcolor=TEXT_PRIMARY, + loc="lower right", bbox_to_anchor=(1.0, 1.0), ncol=2) + _save(fig, name) + plt.close(fig) + + +def chart_v3_vs_v2(rows, tier: str): + pairs = [] + for r in rows: + if tier_of(r["id"]) != tier or "_decrypt/" in r["id"]: + continue + label = scenario_prefix(r["id"]) + pairs.append((label, [r["v2_ns"] / 1e6, r["v3_ns"] / 1e6])) + if not pairs: + return + grouped_hbar(pairs, ["EQL v2.3", "EQL v3"], [COLOR_V2, COLOR_V3], + f"EQL v3 vs v2.3 — query medians at {int(tier):,} rows", + f"v3_vs_v2_{tier}") + + +def chart_plaintext_overhead(v3: dict, tier: str): + pairs = [] + for enc_prefix, plain in PLAINTEXT_MAP.items(): + enc_id = f"{enc_prefix}/{tier}" + if plain.startswith("@"): + plain_id = f"{plain[1:]}/{tier}" + else: + plain_id = f"PLAINTEXT/plaintext/{plain}/{tier}" + if enc_id in v3 and plain_id in v3: + pairs.append( + (enc_prefix, [v3[plain_id] / 1e6, v3[enc_id] / 1e6]) + ) + if not pairs: + return + grouped_hbar(pairs, ["plaintext Postgres", "EQL v3 encrypted"], + [COLOR_PLAIN, COLOR_V3], + f"Encrypted vs plaintext — same query shape, {int(tier):,} rows", + f"overhead_vs_plaintext_{tier}") + + +def chart_ore_vs_ope(v3: dict, tier: str): + pairs = [] + for cid in sorted(v3): + m = re.match(r"^ORE/ore/([^/]+)/" + re.escape(tier) + "$", cid) + if not m: + continue + ope_id = f"OPE/ope/{m.group(1)}/{tier}" + if ope_id in v3: + pairs.append((m.group(1), [v3[cid] / 1e6, v3[ope_id] / 1e6])) + if not pairs: + return + grouped_hbar(pairs, ["ORE (block, custom opclass)", "OPE (CLLW, native btree)"], + [COLOR_ORE, COLOR_OPE], + f"v3 ordering paths: ORE vs OPE at {int(tier):,} rows", + f"ore_vs_ope_{tier}") + + +# --- Report --------------------------------------------------------------- + + +def write_report(rows, v3_query, v3_meta, v2_ingest, v3_ingest, + threshold: float, tiers: list): + REPORT_DIR.mkdir(exist_ok=True) + out = REPORT_DIR / "V3_COMPARISON.md" + lines = [] + w = lines.append + + w("# EQL v3 vs v2.3 — Benchmark Comparison") + w("") + w("Auto-generated by `report_v3_compare.py` (`mise run report:v3-compare`).") + w("") + w(f"Regression threshold: v3 slower by more than **{threshold:.0f}%** on a " + "semantics-equivalent scenario.") + w("") + w("Methodology notes:") + w("") + w("- EQL v3 is installed from the pinned release bundle " + "**eql-3.0.0-alpha.3** (`mise run setup-db-v3`). alpha.3 places the " + "per-domain types in `public.*` (`public.text_search`, " + "`public.integer_ord`, `public.json`, …); the raw-jsonb SEM extractors " + "live in `eql_v3_internal`, and the benches call only the public " + "`eql_v3.*` wrappers.") + w("- **Re-baseline status:** the **JSON** tiers (10k–10M) were re-ingested " + "and re-run against alpha.3. The **non-JSON** v3 scenarios below are " + "still the pre-release alpha.2-equivalent measurements and are pending a " + "full alpha.3 re-baseline — treat their absolute numbers accordingly.") + w("- v3 payloads are produced by `eql-bindings::from_v2` over the pinned " + "cipherstash-client's v2.3 output (the supported migration path); " + "conversion cost is inside the measured ingest path.") + w("- The JSON bench queries the encrypted document through the named EQL " + "JSON functions — `eql_v3.jsonb_contains` (GIN over " + "`eql_v3.jsonb_array(value)`) for containment and " + "`eql_v3.jsonb_path_query_first(value, selector)` feeding " + "`eql_v3.eq_term` / `eql_v3.ore_cllw` for field equality/ordering — not " + "raw `jsonb` `@>` / `->`.") + w("- v3 query parameters are stored-shape payloads (no v3 scalar query " + "wire shape exists); server-side timings are unaffected.") + w("- The v3 string column (`text_search`) carries an ORE term v2's " + "unique+match config did not — v3 string rows are wider.") + w("- OPE ciphertexts are real CLLW-OPE terms emitted by " + "cipherstash-client 0.38.1 (Index::new_ope); ordering parity against " + "decrypted plaintext is asserted at bench startup.") + w("- v2 numbers are the committed baseline results (`results/query/`, " + "`results/ingest/`); v3 numbers come from `results/query/v3/`, " + "`results/ingest/v3/`. The baseline was measured in May; same-day v2 " + "re-measurement (2026-07-04) shows ±8-19% cross-session drift at the " + "10M tier, so 10M flags were re-adjudicated against same-day v2 — " + "see the per-row notes.") + w("") + + # Regression table + w("## Query scenarios: v3 vs v2") + w("") + if rows: + n_reg = sum(1 for r in rows if r["flag"] == "REGRESSION") + n_imp = sum(1 for r in rows if r["flag"] == "improvement") + w(f"{len(rows)} comparable scenario/tier pairs — " + f"**{n_reg} regressions**, {n_imp} improvements beyond ±{threshold:.0f}%.") + w("") + w("| Scenario | Tier | v2 median | v3 median | Δ | Flag | Note |") + w("|---|---|---|---|---|---|---|") + for r in sorted(rows, key=lambda r: -r["delta_pct"]): + flag = {"REGRESSION": "🔴 REGRESSION", + "improvement": "🟢 improvement", + "semantics changed": "⚠️ semantics changed"}.get(r["flag"], "") + w(f"| {scenario_prefix(r['id'])} | {tier_of(r['id'])} " + f"| {fmt_ns(r['v2_ns'])} | {fmt_ns(r['v3_ns'])} " + f"| {r['delta_pct']:+.1f}% | {flag} | {r['note']} |") + else: + w("_No overlapping scenario ids between v2 and v3 result sets yet._") + w("") + + # v3-only scenarios: any v3 scenario whose prefix never matched a v2 + # counterpart (mirrors print_cli_table). Prefix-based so all tiers of a + # v3-only scenario are listed; excludes the ZeroKMS-dominated _decrypt + # variants. Picks up new v3-only scenarios (e.g. JSON field_gt) + # automatically instead of a hardcoded prefix allowlist. + matched_prefixes = {scenario_prefix(r["id"]) for r in rows} + v3_only = sorted( + cid for cid in v3_query + if scenario_prefix(cid) not in matched_prefixes + and "_decrypt" not in cid + ) + if v3_only: + w("## v3-only scenarios (no v2 counterpart)") + w("") + w("| Scenario | Median |") + w("|---|---|") + for cid in v3_only: + w(f"| {cid} | {fmt_ns(v3_query[cid])} |") + w("") + + # Index engagement audit + w("## Index engagement audit (v3 plans)") + w("") + w("Scenarios matching an expected-index rule must show a non-empty " + "`indexes_used` in their EXPLAIN capture.") + w("") + w("| Scenario | Indexes used | Rows | Status |") + w("|---|---|---|---|") + failures = 0 + for cid in sorted(v3_meta): + meta = v3_meta[cid] + expected = any(re.search(p, cid) for p in EXPECTED_INDEX_PATTERNS) + idx = ", ".join(meta["indexes_used"]) or "—" + if expected and not meta["indexes_used"]: + status = "❌ expected index, none used" + failures += 1 + elif expected: + status = "✅" + else: + status = "" + w(f"| {cid} | {idx} | {meta['rows_returned']} | {status} |") + w("") + if failures: + w(f"**{failures} scenario(s) failed the index-engagement gate.**") + w("") + + # Ingest comparison + w("## Ingest throughput: v3 vs v2") + w("") + matched = False + w("| Bench | Records | v2 rec/s | v3 rec/s | Δ | Note |") + w("|---|---|---|---|---|---|") + for v3_name, v3_res in sorted(v3_ingest.items()): + v2_name = v3_name.replace("_v3", "") + v2_res = v2_ingest.get(v2_name, {}) + note = INGEST_NOTES.get(v3_name, "") + for n, v3_rps in sorted(v3_res.items()): + v2_rps = v2_res.get(n) + if v2_rps: + matched = True + d = (v3_rps - v2_rps) / v2_rps * 100.0 + w(f"| {v3_name} | {n:,} | {v2_rps:,.0f} | {v3_rps:,.0f} | {d:+.1f}% | {note} |") + else: + w(f"| {v3_name} | {n:,} | — | {v3_rps:,.0f} | | {note} |") + note = "" + if not matched: + w("") + w("_No matching v2 ingest baselines for the v3 benches run so far._") + w("") + + # Index build times + build_log = V2_INGEST_DIR / "index_build_times.jsonl" + if build_log.exists(): + w("## Index build times") + w("") + w("| Table | Build seconds | Recorded |") + w("|---|---|---|") + for line in build_log.read_text().splitlines(): + try: + e = json.loads(line) + w(f"| {e['table']} | {e['build_seconds']} | {e['recorded_at']} |") + except (json.JSONDecodeError, KeyError): + continue + w("") + + w("## Charts") + w("") + for tier in tiers: + for base in (f"v3_vs_v2_{tier}", f"overhead_vs_plaintext_{tier}", + f"ore_vs_ope_{tier}"): + if (CHART_DIR / f"{base}.png").exists(): + w(f"![{base}](v3/{base}.png)") + w("") + + out.write_text("\n".join(lines)) + print(f"report: {out}") + return failures + + +def print_cli_table(rows, v3_query, threshold: float): + """Side-by-side v2/v3 terminal view — `mise run report:v3-compare`. + + The Markdown/chart artifacts are `report:build:v3-compare`'s job; this + prints the same join to stdout for quick triage after a bench run. + """ + flag_names = {"REGRESSION": "REGRESSION", "improvement": "improvement", + "semantics changed": "semantics≠"} + id_w = max((len(scenario_prefix(r["id"])) for r in rows), default=20) + print(f"{'scenario':<{id_w}} {'tier':>8} {'v2 median':>11} " + f"{'v3 median':>11} {'Δ':>8} flag") + print(f"{'-' * id_w} {'-' * 8} {'-' * 11} {'-' * 11} {'-' * 8} {'-' * 11}") + for r in sorted(rows, key=lambda r: (scenario_prefix(r["id"]), int(tier_of(r["id"])))): + print(f"{scenario_prefix(r['id']):<{id_w}} {tier_of(r['id']):>8} " + f"{fmt_ns(r['v2_ns']):>11} {fmt_ns(r['v3_ns']):>11} " + f"{r['delta_pct']:+7.1f}% {flag_names.get(r['flag'], '')}") + + n_reg = sum(1 for r in rows if r["flag"] == "REGRESSION") + n_imp = sum(1 for r in rows if r["flag"] == "improvement") + n_sem = sum(1 for r in rows if r["flag"] == "semantics changed") + print() + print(f"{len(rows)} comparable pairs: {n_reg} regressions, {n_imp} " + f"improvements (beyond ±{threshold:.0f}%), {n_sem} semantics-changed.") + + v3_only = sorted( + cid for cid in v3_query + if scenario_prefix(cid) not in {scenario_prefix(r["id"]) for r in rows} + and "_decrypt" not in cid + ) + if v3_only: + print() + print("v3-only scenarios (no v2 counterpart):") + for cid in v3_only: + print(f" {cid:<{id_w + 10}} {fmt_ns(v3_query[cid]):>11}") + print() + print("Full report + charts: mise run report:build:v3-compare") + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--threshold", type=float, default=10.0, + help="regression flag threshold in percent (default 10)") + ap.add_argument("--cli", action="store_true", + help="print the v2/v3 side-by-side table to stdout and exit " + "(no Markdown report, no charts)") + args = ap.parse_args() + + v2_query = load_criterion_dir(V2_QUERY_DIR) + v3_query = load_criterion_dir(V3_QUERY_DIR) + v3_meta = load_metadata_dir(V3_QUERY_DIR) + v2_ingest = load_ingest_dir(V2_INGEST_DIR) + v3_ingest = load_ingest_dir(V3_INGEST_DIR) + + if not v3_query: + print("No v3 query results found under results/query/v3/ — run " + "`mise run bench:v3:query:all` first.", file=sys.stderr) + sys.exit(1) + + rows = build_regression_rows(v2_query, v3_query, args.threshold) + + if args.cli: + print_cli_table(rows, v3_query, args.threshold) + return + + tiers = sorted({tier_of(cid) for cid in v3_query}, key=int) + + try: + for tier in tiers: + chart_v3_vs_v2(rows, tier) + chart_plaintext_overhead(v3_query, tier) + chart_ore_vs_ope(v3_query, tier) + except ImportError: + print("matplotlib not available — skipping charts", file=sys.stderr) + + failures = write_report(rows, v3_query, v3_meta, v2_ingest, v3_ingest, + args.threshold, tiers) + sys.exit(2 if failures else 0) + + +if __name__ == "__main__": + main() diff --git a/results/ingest/index_build_times.jsonl b/results/ingest/index_build_times.jsonl new file mode 100644 index 0000000..b866b18 --- /dev/null +++ b/results/ingest/index_build_times.jsonl @@ -0,0 +1,30 @@ +{"table": "string_encrypted_v3_10000", "build_seconds": 1, "recorded_at": "2026-07-03T13:10:14Z"} +{"table": "integer_encrypted_v3_10000", "build_seconds": 1, "recorded_at": "2026-07-03T13:10:22Z"} +{"table": "integer_encrypted_ope_v3_10000", "build_seconds": 0, "recorded_at": "2026-07-03T13:10:25Z"} +{"table": "category_encrypted_v3_10000", "build_seconds": 0, "recorded_at": "2026-07-03T13:10:27Z"} +{"table": "combo_encrypted_v3_10000", "build_seconds": 1, "recorded_at": "2026-07-03T13:10:42Z"} +{"table": "json_ste_vec_small_encrypted_v3_10000", "build_seconds": 1, "recorded_at": "2026-07-03T13:10:47Z"} +{"table": "string_encrypted_v3_100000", "build_seconds": 8, "recorded_at": "2026-07-03T13:36:20Z"} +{"table": "integer_encrypted_v3_100000", "build_seconds": 4, "recorded_at": "2026-07-03T13:38:54Z"} +{"table": "integer_encrypted_ope_v3_100000", "build_seconds": 0, "recorded_at": "2026-07-03T13:40:47Z"} +{"table": "category_encrypted_v3_100000", "build_seconds": 1, "recorded_at": "2026-07-03T13:42:37Z"} +{"table": "combo_encrypted_v3_100000", "build_seconds": 7, "recorded_at": "2026-07-03T13:45:31Z"} +{"table": "json_ste_vec_small_encrypted_v3_100000", "build_seconds": 6, "recorded_at": "2026-07-03T13:46:31Z"} +{"table": "string_encrypted_v3_1000000", "build_seconds": 78, "recorded_at": "2026-07-03T14:05:03Z"} +{"table": "integer_encrypted_v3_1000000", "build_seconds": 44, "recorded_at": "2026-07-03T14:15:06Z"} +{"table": "integer_encrypted_ope_v3_1000000", "build_seconds": 1, "recorded_at": "2026-07-03T14:16:48Z"} +{"table": "category_encrypted_v3_1000000", "build_seconds": 1, "recorded_at": "2026-07-03T14:19:32Z"} +{"table": "combo_encrypted_v3_1000000", "build_seconds": 67, "recorded_at": "2026-07-03T14:42:01Z"} +{"table": "json_ste_vec_small_encrypted_v3_1000000", "build_seconds": 55, "recorded_at": "2026-07-03T14:46:55Z"} +{"table": "integer_encrypted_1000000", "build_seconds": 42, "recorded_at": "2026-07-04T00:55:25Z"} +{"table": "json_ste_vec_small_encrypted_100000", "build_seconds": 15, "recorded_at": "2026-07-04T01:21:47Z"} +{"table": "integer_encrypted_ope_v3_10000", "build_seconds": 0, "recorded_at": "2026-07-04T01:49:59Z"} +{"table": "integer_encrypted_ope_v3_100000", "build_seconds": 0, "recorded_at": "2026-07-04T01:51:54Z"} +{"table": "integer_encrypted_ope_v3_1000000", "build_seconds": 1, "recorded_at": "2026-07-04T01:54:49Z"} +{"table": "integer_encrypted_ope_v3_10000000", "build_seconds": 8, "recorded_at": "2026-07-04T05:52:51Z"} +{"table": "json_ste_vec_small_encrypted_v3_10000000", "build_seconds": 270, "recorded_at": "2026-07-04T06:31:25Z"} +{"table": "integer_encrypted_v3_10000000", "build_seconds": 474, "recorded_at": "2026-07-04T07:55:44Z"} +{"table": "string_encrypted_v3_10000000", "build_seconds": 896, "recorded_at": "2026-07-04T10:17:38Z"} +{"table": "category_encrypted_v3_10000000", "build_seconds": 9, "recorded_at": "2026-07-04T12:11:35Z"} +{"table": "category_encrypted_10000000", "build_seconds": 148, "recorded_at": "2026-07-04T12:34:08Z"} +{"table": "string_encrypted_10000000", "build_seconds": 342, "recorded_at": "2026-07-04T12:54:54Z"} diff --git a/results/ingest/v3/encrypt_category_v3_combined.json b/results/ingest/v3/encrypt_category_v3_combined.json new file mode 100644 index 0000000..2d6ffc8 --- /dev/null +++ b/results/ingest/v3/encrypt_category_v3_combined.json @@ -0,0 +1,42 @@ +{ + "metadata": { + "timestamp": "2026-07-09T00:38:48.318293+00:00", + "rust_version": "rustc 1.86.0 (05f9846f8 2025-03-31)", + "postgres_version": "psql (PostgreSQL) 17.10 (Homebrew)", + "host_info": { + "os": "macOS", + "cpu_model": "Apple M1 Max", + "cpu_cores": 10, + "total_memory_gb": 64.0 + } + }, + "results": [ + { + "num_records": 500, + "total_time_seconds": 0.54852675818, + "total_records": 500, + "throughput_records_per_second": 911.5325597952401, + "average_memory_usage_bytes": 19496960, + "average_memory_usage_mb": 18.59375, + "num_runs": 2 + }, + { + "num_records": 1000, + "total_time_seconds": 0.25282604968000005, + "total_records": 1000, + "throughput_records_per_second": 3955.288631316639, + "average_memory_usage_bytes": 20873216, + "average_memory_usage_mb": 19.90625, + "num_runs": 2 + }, + { + "num_records": 10000, + "total_time_seconds": 0.85300580018, + "total_records": 10000, + "throughput_records_per_second": 11723.249710482407, + "average_memory_usage_bytes": 22175744, + "average_memory_usage_mb": 21.1484375, + "num_runs": 2 + } + ] +} \ No newline at end of file diff --git a/results/ingest/v3/encrypt_int_ope_v3_combined.json b/results/ingest/v3/encrypt_int_ope_v3_combined.json new file mode 100644 index 0000000..bc59a3d --- /dev/null +++ b/results/ingest/v3/encrypt_int_ope_v3_combined.json @@ -0,0 +1,42 @@ +{ + "metadata": { + "timestamp": "2026-07-09T00:38:44.532430+00:00", + "rust_version": "rustc 1.86.0 (05f9846f8 2025-03-31)", + "postgres_version": "psql (PostgreSQL) 17.10 (Homebrew)", + "host_info": { + "os": "macOS", + "cpu_model": "Apple M1 Max", + "cpu_cores": 10, + "total_memory_gb": 64.0 + } + }, + "results": [ + { + "num_records": 500, + "total_time_seconds": 0.68141903396, + "total_records": 500, + "throughput_records_per_second": 733.7628904996958, + "average_memory_usage_bytes": 19505152, + "average_memory_usage_mb": 18.6015625, + "num_runs": 2 + }, + { + "num_records": 1000, + "total_time_seconds": 0.25065899246, + "total_records": 1000, + "throughput_records_per_second": 3989.483840918172, + "average_memory_usage_bytes": 20684800, + "average_memory_usage_mb": 19.7265625, + "num_runs": 2 + }, + { + "num_records": 10000, + "total_time_seconds": 0.8379711384599999, + "total_records": 10000, + "throughput_records_per_second": 11933.585228696207, + "average_memory_usage_bytes": 22609920, + "average_memory_usage_mb": 21.5625, + "num_runs": 2 + } + ] +} \ No newline at end of file diff --git a/results/ingest/v3/encrypt_int_v3_combined.json b/results/ingest/v3/encrypt_int_v3_combined.json new file mode 100644 index 0000000..f429152 --- /dev/null +++ b/results/ingest/v3/encrypt_int_v3_combined.json @@ -0,0 +1,42 @@ +{ + "metadata": { + "timestamp": "2026-07-09T00:38:40.441833+00:00", + "rust_version": "rustc 1.86.0 (05f9846f8 2025-03-31)", + "postgres_version": "psql (PostgreSQL) 17.10 (Homebrew)", + "host_info": { + "os": "macOS", + "cpu_model": "Apple M1 Max", + "cpu_cores": 10, + "total_memory_gb": 64.0 + } + }, + "results": [ + { + "num_records": 500, + "total_time_seconds": 0.8275028266000001, + "total_records": 500, + "throughput_records_per_second": 604.2275433116931, + "average_memory_usage_bytes": 20185088, + "average_memory_usage_mb": 19.25, + "num_runs": 2 + }, + { + "num_records": 1000, + "total_time_seconds": 0.6444869301, + "total_records": 1000, + "throughput_records_per_second": 1551.6218456824838, + "average_memory_usage_bytes": 24797184, + "average_memory_usage_mb": 23.6484375, + "num_runs": 2 + }, + { + "num_records": 10000, + "total_time_seconds": 4.6422539301, + "total_records": 10000, + "throughput_records_per_second": 2154.126023818044, + "average_memory_usage_bytes": 26492928, + "average_memory_usage_mb": 25.265625, + "num_runs": 2 + } + ] +} \ No newline at end of file diff --git a/results/ingest/v3/encrypt_ste_vec_small_v3_combined.json b/results/ingest/v3/encrypt_ste_vec_small_v3_combined.json new file mode 100644 index 0000000..7030d72 --- /dev/null +++ b/results/ingest/v3/encrypt_ste_vec_small_v3_combined.json @@ -0,0 +1,42 @@ +{ + "metadata": { + "timestamp": "2026-07-09T00:38:55.335442+00:00", + "rust_version": "rustc 1.86.0 (05f9846f8 2025-03-31)", + "postgres_version": "psql (PostgreSQL) 17.10 (Homebrew)", + "host_info": { + "os": "macOS", + "cpu_model": "Apple M1 Max", + "cpu_cores": 10, + "total_memory_gb": 64.0 + } + }, + "results": [ + { + "num_records": 500, + "total_time_seconds": 0.6083774457800001, + "total_records": 500, + "throughput_records_per_second": 821.8582123125069, + "average_memory_usage_bytes": 25174016, + "average_memory_usage_mb": 24.0078125, + "num_runs": 2 + }, + { + "num_records": 1000, + "total_time_seconds": 0.41082944528, + "total_records": 1000, + "throughput_records_per_second": 2434.100114996509, + "average_memory_usage_bytes": 36257792, + "average_memory_usage_mb": 34.578125, + "num_runs": 2 + }, + { + "num_records": 10000, + "total_time_seconds": 2.24182234128, + "total_records": 10000, + "throughput_records_per_second": 4460.656768319277, + "average_memory_usage_bytes": 41222144, + "average_memory_usage_mb": 39.3125, + "num_runs": 2 + } + ] +} \ No newline at end of file diff --git a/results/ingest/v3/encrypt_string_v3_combined.json b/results/ingest/v3/encrypt_string_v3_combined.json new file mode 100644 index 0000000..8a3c5d1 --- /dev/null +++ b/results/ingest/v3/encrypt_string_v3_combined.json @@ -0,0 +1,42 @@ +{ + "metadata": { + "timestamp": "2026-07-09T00:39:14.627484+00:00", + "rust_version": "rustc 1.86.0 (05f9846f8 2025-03-31)", + "postgres_version": "psql (PostgreSQL) 17.10 (Homebrew)", + "host_info": { + "os": "macOS", + "cpu_model": "Apple M1 Max", + "cpu_cores": 10, + "total_memory_gb": 64.0 + } + }, + "results": [ + { + "num_records": 500, + "total_time_seconds": 0.8838496053400001, + "total_records": 500, + "throughput_records_per_second": 565.7071033116086, + "average_memory_usage_bytes": 24322048, + "average_memory_usage_mb": 23.1953125, + "num_runs": 2 + }, + { + "num_records": 1000, + "total_time_seconds": 0.96437570934, + "total_records": 1000, + "throughput_records_per_second": 1036.940261264337, + "average_memory_usage_bytes": 34250752, + "average_memory_usage_mb": 32.6640625, + "num_runs": 2 + }, + { + "num_records": 10000, + "total_time_seconds": 7.55954937634, + "total_records": 10000, + "throughput_records_per_second": 1322.8301717689897, + "average_memory_usage_bytes": 36913152, + "average_memory_usage_mb": 35.203125, + "num_runs": 2 + } + ] +} \ No newline at end of file diff --git a/results/query/v3/combo_metadata_10000.json b/results/query/v3/combo_metadata_10000.json new file mode 100644 index 0000000..e355308 --- /dev/null +++ b/results/query/v3/combo_metadata_10000.json @@ -0,0 +1,303 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "combo_encrypted_v3_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbL>skz&>@ZwHR>sj! (eql_v3_internal.bloom_filter((('{\"c\": \"mBbL>skz&>@ZwHR>sj!skz&>@ZwHR>sj! $1 ORDER BY eql_v3.ord_term(age) LIMIT 10", + "rows_returned": 4 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Group Key": [ + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Alias": "combo_encrypted_v3_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJUhfrb`JEtIr&txLSDer*96|pI`;UA|QJV{i$g$y (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJUhfrb`JEtIr&txLSDer*96|pI`;UA|QJV{i$g$y> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Startup Cost": 61.0, + "Total Cost": 61.01 + } + ], + "Startup Cost": 61.0, + "Strategy": "Sorted", + "Total Cost": 61.02 + } + } + ], + "id": "COMBO/combo/filtered_group_by/10000", + "indexes_used": [ + "combo_encrypted_v3_10000_name_match_gin_index" + ], + "parameters": [ + { + "bf": [ + 1673, + 1471, + 943, + 567, + 1076, + 1346 + ], + "c": "mBbJUhfrb`JEtIr&txLSDer*96|pI`;UA|QJV{i$g$y $1 GROUP BY 1", + "rows_returned": 4 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Alias": "combo_encrypted_v3_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLJ@{d+gEr3m|9$?(a<5Y^o6;FpZkwW+twq$9c1+3#Hbqm5C`c1?j6pob<4Idq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_10000\"}, \"v\": 3, \"bf\": [1471, 1346, 567, 1076, 943, 1673], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c357a2e1e684606d053a7d2ea49601d879065c9cfcdcca0cdbfaa451191dabbd50cd556c39b6153a2254d357110460b9b07e97eb7704c3bd2e41190846ea00770cd425c4de22b019e2ef89a44d4a82e106f6a6698cb3d099040376ead796b31d400d66583dc98d18d8c6c5ad0ae5c3b73e572f13127872afbd811fc4f37a0ffd8d15db4add60cf7d6c9f8fee87e7b40214764f859f3177b8a9a80be27d1fe4b04eed3392a810b4f3da263205f3ce3563350be0e9783e3b33fb5a357c727fce4fb325f3074064e90b18dc875a200d888b6028afbf2cbf08e35e171e15b32fa6bd35b57a9e32347ea5cd91aaa200fa1059e614ee03e093ce7e49b2ca66bed0db7265e13f46ba7a55d4acdefa9d4f9cd88145\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Index Name": "combo_encrypted_v3_10000_name_match_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 56.47 + } + ], + "Recheck Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLJ@{d+gEr3m|9$?(a<5Y^o6;FpZkwW+twq$9c1+3#Hbqm5C`c1?j6pob<4Idq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_10000\"}, \"v\": 3, \"bf\": [1471, 1346, 567, 1076, 943, 1673], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c357a2e1e684606d053a7d2ea49601d879065c9cfcdcca0cdbfaa451191dabbd50cd556c39b6153a2254d357110460b9b07e97eb7704c3bd2e41190846ea00770cd425c4de22b019e2ef89a44d4a82e106f6a6698cb3d099040376ead796b31d400d66583dc98d18d8c6c5ad0ae5c3b73e572f13127872afbd811fc4f37a0ffd8d15db4add60cf7d6c9f8fee87e7b40214764f859f3177b8a9a80be27d1fe4b04eed3392a810b4f3da263205f3ce3563350be0e9783e3b33fb5a357c727fce4fb325f3074064e90b18dc875a200d888b6028afbf2cbf08e35e171e15b32fa6bd35b57a9e32347ea5cd91aaa200fa1059e614ee03e093ce7e49b2ca66bed0db7265e13f46ba7a55d4acdefa9d4f9cd88145\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Relation Name": "combo_encrypted_v3_10000", + "Startup Cost": 56.47, + "Total Cost": 60.99 + } + ], + "Sort Key": [ + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Startup Cost": 61.0, + "Total Cost": 61.01 + } + ], + "Startup Cost": 61.0, + "Strategy": "Sorted", + "Total Cost": 61.02 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 61.03, + "Total Cost": 61.04 + } + ], + "Startup Cost": 61.03, + "Total Cost": 61.04 + } + } + ], + "id": "COMBO/combo/top_n_filtered_group_by/10000", + "indexes_used": [ + "combo_encrypted_v3_10000_name_match_gin_index" + ], + "parameters": [ + { + "bf": [ + 1471, + 1346, + 567, + 1076, + 943, + 1673 + ], + "c": "mBbLJ@{d+gEr3m|9$?(a<5Y^o6;FpZkwW+twq$9c1+3#Hbqm5C`c1?j6pob<4Idq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h", + "hm": "d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795", + "i": { + "c": "name", + "t": "combo_encrypted_v3_10000" + }, + "ob": [ + "f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c357a2e1e684606d053a7d2ea49601d879065c9cfcdcca0cdbfaa451191dabbd50cd556c39b6153a2254d357110460b9b07e97eb7704c3bd2e41190846ea00770cd425c4de22b019e2ef89a44d4a82e106f6a6698cb3d099040376ead796b31d400d66583dc98d18d8c6c5ad0ae5c3b73e572f13127872afbd811fc4f37a0ffd8d15db4add60cf7d6c9f8fee87e7b40214764f859f3177b8a9a80be27d1fe4b04eed3392a810b4f3da263205f3ce3563350be0e9783e3b33fb5a357c727fce4fb325f3074064e90b18dc875a200d888b6028afbf2cbf08e35e171e15b32fa6bd35b57a9e32347ea5cd91aaa200fa1059e614ee03e093ce7e49b2ca66bed0db7265e13f46ba7a55d4acdefa9d4f9cd88145" + ], + "v": 3 + } + ], + "query": "SELECT eql_v3.eq_term(category), count(*) FROM combo_encrypted_v3_10000 WHERE name @> $1 GROUP BY 1 ORDER BY count(*) DESC LIMIT 10", + "rows_returned": 4 + } + ], + "target_rows": "10000" +} \ No newline at end of file diff --git a/results/query/v3/combo_metadata_100000.json b/results/query/v3/combo_metadata_100000.json new file mode 100644 index 0000000..75d999a --- /dev/null +++ b/results/query/v3/combo_metadata_100000.json @@ -0,0 +1,303 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "combo_encrypted_v3_100000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJtpEKZ-1_Rlb9xuzbSS7Z^6}IlL&FPAi!hQM-qlov%c*O9uu5-j7QD)aGa`MU~ga (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJtpEKZ-1_Rlb9xuzbSS7Z^6}IlL&FPAi!hQM-qlov%c*O9uu5-j7QD)aGa`MU~ga $1 ORDER BY eql_v3.ord_term(age) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Group Key": [ + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Alias": "combo_encrypted_v3_100000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLH8|5ql4M2Q_Pp`vyaAZWp6+X-lgSi|Z5MHiX>KE^)(=s*NOLxQ|R!;$YnKh-wL)>^x9Zn|24Dt^$rm)!b)|?E^*5Z;+q;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_100000\"}, \"v\": 3, \"bf\": [1471, 943, 1346, 1076, 567, 1673], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c35bc10e47437489ceccd697f83c193e402f589e059b223b6367059997df64e15305798f235df5f24135f52eceeed140c773b69166ff84df05ef43cd4979584f524f55026fa0e987397b59cfec41626e7fcd430dd7d4d72a501f0d3e20c3f57e7e6846351d12010108c409522fd5076798228081070549dd640d1a0092d002d9f9b62805158abae3850b48b25f7ba2424196b1224ecf056dd4afce29f352a480118f4c9f2c0fe7331f862cbddff09432f8d19dc48cfcb784e01ba365e32137e3eaea6c4c2acd4d218973067a199c1a9bd37e4047c766fb9a357e39931fa21c24725455138a6d75799b92be48db6550ef6d18539fafae82d416eccded84d87789f48d9353709ec734ac6b535f73c7c86e43\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Index Name": "combo_encrypted_v3_100000_name_match_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 93.6 + } + ], + "Recheck Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLH8|5ql4M2Q_Pp`vyaAZWp6+X-lgSi|Z5MHiX>KE^)(=s*NOLxQ|R!;$YnKh-wL)>^x9Zn|24Dt^$rm)!b)|?E^*5Z;+q;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_100000\"}, \"v\": 3, \"bf\": [1471, 943, 1346, 1076, 567, 1673], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c35bc10e47437489ceccd697f83c193e402f589e059b223b6367059997df64e15305798f235df5f24135f52eceeed140c773b69166ff84df05ef43cd4979584f524f55026fa0e987397b59cfec41626e7fcd430dd7d4d72a501f0d3e20c3f57e7e6846351d12010108c409522fd5076798228081070549dd640d1a0092d002d9f9b62805158abae3850b48b25f7ba2424196b1224ecf056dd4afce29f352a480118f4c9f2c0fe7331f862cbddff09432f8d19dc48cfcb784e01ba365e32137e3eaea6c4c2acd4d218973067a199c1a9bd37e4047c766fb9a357e39931fa21c24725455138a6d75799b92be48db6550ef6d18539fafae82d416eccded84d87789f48d9353709ec734ac6b535f73c7c86e43\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Relation Name": "combo_encrypted_v3_100000", + "Startup Cost": 93.6, + "Total Cost": 98.12 + } + ], + "Sort Key": [ + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Startup Cost": 98.13, + "Total Cost": 98.13 + } + ], + "Startup Cost": 98.13, + "Strategy": "Sorted", + "Total Cost": 98.15 + } + } + ], + "id": "COMBO/combo/filtered_group_by/100000", + "indexes_used": [ + "combo_encrypted_v3_100000_name_match_gin_index" + ], + "parameters": [ + { + "bf": [ + 1471, + 943, + 1346, + 1076, + 567, + 1673 + ], + "c": "mBbLH8|5ql4M2Q_Pp`vyaAZWp6+X-lgSi|Z5MHiX>KE^)(=s*NOLxQ|R!;$YnKh-wL)>^x9Zn|24Dt^$rm)!b)|?E^*5Z;+q;6qtWyBEWG)cPL_Dk-y$tP`SR?}h", + "hm": "d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795", + "i": { + "c": "name", + "t": "combo_encrypted_v3_100000" + }, + "ob": [ + "f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c35bc10e47437489ceccd697f83c193e402f589e059b223b6367059997df64e15305798f235df5f24135f52eceeed140c773b69166ff84df05ef43cd4979584f524f55026fa0e987397b59cfec41626e7fcd430dd7d4d72a501f0d3e20c3f57e7e6846351d12010108c409522fd5076798228081070549dd640d1a0092d002d9f9b62805158abae3850b48b25f7ba2424196b1224ecf056dd4afce29f352a480118f4c9f2c0fe7331f862cbddff09432f8d19dc48cfcb784e01ba365e32137e3eaea6c4c2acd4d218973067a199c1a9bd37e4047c766fb9a357e39931fa21c24725455138a6d75799b92be48db6550ef6d18539fafae82d416eccded84d87789f48d9353709ec734ac6b535f73c7c86e43" + ], + "v": 3 + } + ], + "query": "SELECT eql_v3.eq_term(category), count(*) FROM combo_encrypted_v3_100000 WHERE name @> $1 GROUP BY 1", + "rows_returned": 51 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Alias": "combo_encrypted_v3_100000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbM6EwWN2VRz*I3DdDB#Fmo86+?kTUDQ)3C~$YCfpIWtH3*?`N1MbTs_dsnSw}Szu~U`$sq7vNWOvE$ptPi!+(lKfM!NLJq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_100000\"}, \"v\": 3, \"bf\": [567, 943, 1673, 1346, 1076, 1471], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c34318ae765150f77b3a53a263bc7d2993112769788be44c691b6bb7dd0d108287ccf62da1c7b66cce8a289f4b0952dda6525ef989cd7dc0234274f4210812bc6c6cf77842215f4ee0069d5d53a44978ba9afa08fc508dfb429c9ae59fe09b1273671429c50943643b8d06a953cefefaff93a57437960fae6da97d06605a455e9d42ea642245ab451b32f59c3377a7d22e6cdaf03ea0db72f487cc24ec8cffa2f93bee652ef90dd93ef1a753a3c6b9ec87c1685b79444cdeeff126163034a7b0250223b500e6739e976a0feac92b54cde7c0249b106c1ceb8617407131b893b688bdfaba895f2345ae848dac6078c107cdce8aa0b27658eb23c31483eaa2189f56b7cda0d2d5b068905f006440337a0ae6\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Index Name": "combo_encrypted_v3_100000_name_match_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 93.6 + } + ], + "Recheck Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbM6EwWN2VRz*I3DdDB#Fmo86+?kTUDQ)3C~$YCfpIWtH3*?`N1MbTs_dsnSw}Szu~U`$sq7vNWOvE$ptPi!+(lKfM!NLJq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_100000\"}, \"v\": 3, \"bf\": [567, 943, 1673, 1346, 1076, 1471], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c34318ae765150f77b3a53a263bc7d2993112769788be44c691b6bb7dd0d108287ccf62da1c7b66cce8a289f4b0952dda6525ef989cd7dc0234274f4210812bc6c6cf77842215f4ee0069d5d53a44978ba9afa08fc508dfb429c9ae59fe09b1273671429c50943643b8d06a953cefefaff93a57437960fae6da97d06605a455e9d42ea642245ab451b32f59c3377a7d22e6cdaf03ea0db72f487cc24ec8cffa2f93bee652ef90dd93ef1a753a3c6b9ec87c1685b79444cdeeff126163034a7b0250223b500e6739e976a0feac92b54cde7c0249b106c1ceb8617407131b893b688bdfaba895f2345ae848dac6078c107cdce8aa0b27658eb23c31483eaa2189f56b7cda0d2d5b068905f006440337a0ae6\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Relation Name": "combo_encrypted_v3_100000", + "Startup Cost": 93.6, + "Total Cost": 98.12 + } + ], + "Sort Key": [ + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Startup Cost": 98.13, + "Total Cost": 98.13 + } + ], + "Startup Cost": 98.13, + "Strategy": "Sorted", + "Total Cost": 98.15 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 98.16, + "Total Cost": 98.16 + } + ], + "Startup Cost": 98.16, + "Total Cost": 98.16 + } + } + ], + "id": "COMBO/combo/top_n_filtered_group_by/100000", + "indexes_used": [ + "combo_encrypted_v3_100000_name_match_gin_index" + ], + "parameters": [ + { + "bf": [ + 567, + 943, + 1673, + 1346, + 1076, + 1471 + ], + "c": "mBbM6EwWN2VRz*I3DdDB#Fmo86+?kTUDQ)3C~$YCfpIWtH3*?`N1MbTs_dsnSw}Szu~U`$sq7vNWOvE$ptPi!+(lKfM!NLJq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h", + "hm": "d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795", + "i": { + "c": "name", + "t": "combo_encrypted_v3_100000" + }, + "ob": [ + "f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c34318ae765150f77b3a53a263bc7d2993112769788be44c691b6bb7dd0d108287ccf62da1c7b66cce8a289f4b0952dda6525ef989cd7dc0234274f4210812bc6c6cf77842215f4ee0069d5d53a44978ba9afa08fc508dfb429c9ae59fe09b1273671429c50943643b8d06a953cefefaff93a57437960fae6da97d06605a455e9d42ea642245ab451b32f59c3377a7d22e6cdaf03ea0db72f487cc24ec8cffa2f93bee652ef90dd93ef1a753a3c6b9ec87c1685b79444cdeeff126163034a7b0250223b500e6739e976a0feac92b54cde7c0249b106c1ceb8617407131b893b688bdfaba895f2345ae848dac6078c107cdce8aa0b27658eb23c31483eaa2189f56b7cda0d2d5b068905f006440337a0ae6" + ], + "v": 3 + } + ], + "query": "SELECT eql_v3.eq_term(category), count(*) FROM combo_encrypted_v3_100000 WHERE name @> $1 GROUP BY 1 ORDER BY count(*) DESC LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "100000" +} \ No newline at end of file diff --git a/results/query/v3/combo_metadata_1000000.json b/results/query/v3/combo_metadata_1000000.json new file mode 100644 index 0000000..90c87e9 --- /dev/null +++ b/results/query/v3/combo_metadata_1000000.json @@ -0,0 +1,303 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Alias": "combo_encrypted_v3_1000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK!3*9Wj3Ebjn%k4>m4}Mm}6`(v@xTT!hH9xjbl!rG=xu{D9cc=Q (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK!3*9Wj3Ebjn%k4>m4}Mm}6`(v@xTT!hH9xjbl!rG=xu{D9cc=Qm4}Mm}6`(v@xTT!hH9xjbl!rG=xu{D9cc=Q $1 ORDER BY eql_v3.ord_term(age) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Group Key": [ + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Alias": "combo_encrypted_v3_1000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbKd&X$zB8z`*yRf!732|Aj@6>qjSB^1sS$Vw%h{e>9i#x~6z*1*IdoEQeVkw1nOVCi8ZO{!0oK#}5CWZZ8~N4Rlnr$L7wq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_1000000\"}, \"v\": 3, \"bf\": [567, 1076, 1471, 1346, 1673, 943], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c37ac803e7e33616e24d657cb0c13195c32451b0380519d765dbe59a22428dd5e37ad4c87ec1aa1e6dcf9b85af628b3b57d34aa882d23a7d616f346ee8f14d649151d95ccfa6f3aed289823153566a3c0440a315174426e0d07a15733bab9c973e5b7078ae0534ae9bcac756810b2785517f28dcb03722cc94af137415fa1c041bb1821a44875c8bbb0c7f8a1da06c77042bcd5bfd799ca1cd8333d31ed01bfddcfe0a9fadca1ba048a46f9a02ce82f68e78e1c9829fa4552dd71a205a30bca22be8b23ca2c83290983ac3ba5a9f73c0f502b267e1f462149417e3e28b29fd96fafc934c1ca29a9b78d9fbec0deaa25fd5d4b7186e680c64d2136efb47ff8f27364acb539da1a849148f74aed73200c62e\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Index Name": "combo_encrypted_v3_1000000_name_match_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 290.85 + } + ], + "Recheck Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbKd&X$zB8z`*yRf!732|Aj@6>qjSB^1sS$Vw%h{e>9i#x~6z*1*IdoEQeVkw1nOVCi8ZO{!0oK#}5CWZZ8~N4Rlnr$L7wq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_1000000\"}, \"v\": 3, \"bf\": [567, 1076, 1471, 1346, 1673, 943], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c37ac803e7e33616e24d657cb0c13195c32451b0380519d765dbe59a22428dd5e37ad4c87ec1aa1e6dcf9b85af628b3b57d34aa882d23a7d616f346ee8f14d649151d95ccfa6f3aed289823153566a3c0440a315174426e0d07a15733bab9c973e5b7078ae0534ae9bcac756810b2785517f28dcb03722cc94af137415fa1c041bb1821a44875c8bbb0c7f8a1da06c77042bcd5bfd799ca1cd8333d31ed01bfddcfe0a9fadca1ba048a46f9a02ce82f68e78e1c9829fa4552dd71a205a30bca22be8b23ca2c83290983ac3ba5a9f73c0f502b267e1f462149417e3e28b29fd96fafc934c1ca29a9b78d9fbec0deaa25fd5d4b7186e680c64d2136efb47ff8f27364acb539da1a849148f74aed73200c62e\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Relation Name": "combo_encrypted_v3_1000000", + "Startup Cost": 290.85, + "Total Cost": 295.37 + } + ], + "Sort Key": [ + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Startup Cost": 295.38, + "Total Cost": 295.38 + } + ], + "Startup Cost": 295.38, + "Strategy": "Sorted", + "Total Cost": 295.4 + } + } + ], + "id": "COMBO/combo/filtered_group_by/1000000", + "indexes_used": [ + "combo_encrypted_v3_1000000_name_match_gin_index" + ], + "parameters": [ + { + "bf": [ + 567, + 1076, + 1471, + 1346, + 1673, + 943 + ], + "c": "mBbKd&X$zB8z`*yRf!732|Aj@6>qjSB^1sS$Vw%h{e>9i#x~6z*1*IdoEQeVkw1nOVCi8ZO{!0oK#}5CWZZ8~N4Rlnr$L7wq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h", + "hm": "d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795", + "i": { + "c": "name", + "t": "combo_encrypted_v3_1000000" + }, + "ob": [ + "f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c37ac803e7e33616e24d657cb0c13195c32451b0380519d765dbe59a22428dd5e37ad4c87ec1aa1e6dcf9b85af628b3b57d34aa882d23a7d616f346ee8f14d649151d95ccfa6f3aed289823153566a3c0440a315174426e0d07a15733bab9c973e5b7078ae0534ae9bcac756810b2785517f28dcb03722cc94af137415fa1c041bb1821a44875c8bbb0c7f8a1da06c77042bcd5bfd799ca1cd8333d31ed01bfddcfe0a9fadca1ba048a46f9a02ce82f68e78e1c9829fa4552dd71a205a30bca22be8b23ca2c83290983ac3ba5a9f73c0f502b267e1f462149417e3e28b29fd96fafc934c1ca29a9b78d9fbec0deaa25fd5d4b7186e680c64d2136efb47ff8f27364acb539da1a849148f74aed73200c62e" + ], + "v": 3 + } + ], + "query": "SELECT eql_v3.eq_term(category), count(*) FROM combo_encrypted_v3_1000000 WHERE name @> $1 GROUP BY 1", + "rows_returned": 237 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Alias": "combo_encrypted_v3_1000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK?n#yHO8S<9OhZ5wwj!b#P6_t|pj)n8K?Zo~dhrsIBju0m)@$tkUG0hZ}l)P{ufwd!^FOb85Lx~{q0-yfvT$p$FPm6Rsq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_1000000\"}, \"v\": 3, \"bf\": [1471, 567, 943, 1076, 1673, 1346], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c3f5daee23452cdc6846ef2bd879e525ea569d3c31dbe369d74c759d578f4c5a5a97a9c8f407a7058b6995f1df3f07cbdf9f7fc96dfc1dfd8ac223d5e8d50a008f3b9d6cded770d4fa28534887f6e9af5130cf7ca08321dc3572af25a063d72618ecdaef2ab55bbb159abea62804432d8d289f0f9aa78adcfda13aa8ca7269e4e34e74bf5ca2045f5b174bdfb58337b8e0ddd6824dc6d6cb1ec3553fd88a2b1d259c33ab069a5d564e2a981077324f60431a8294d8cae96f5b8f120b164c5a2341a34e3242bd4102eedefc38665e5990703d9ed7bbd22c2b7bdb905ed14ed67e6b1a87b6a1544d58e1a69d45d11ddd19630d374848465eefee3327cfedc631f70230eadbbf80547c17dac2524a297e6720\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Index Name": "combo_encrypted_v3_1000000_name_match_gin_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 290.85 + } + ], + "Recheck Cond": "((eql_v3_internal.bloom_filter((name)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK?n#yHO8S<9OhZ5wwj!b#P6_t|pj)n8K?Zo~dhrsIBju0m)@$tkUG0hZ}l)P{ufwd!^FOb85Lx~{q0-yfvT$p$FPm6Rsq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h\", \"i\": {\"c\": \"name\", \"t\": \"combo_encrypted_v3_1000000\"}, \"v\": 3, \"bf\": [1471, 567, 943, 1076, 1673, 1346], \"hm\": \"d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795\", \"ob\": [\"f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c3f5daee23452cdc6846ef2bd879e525ea569d3c31dbe369d74c759d578f4c5a5a97a9c8f407a7058b6995f1df3f07cbdf9f7fc96dfc1dfd8ac223d5e8d50a008f3b9d6cded770d4fa28534887f6e9af5130cf7ca08321dc3572af25a063d72618ecdaef2ab55bbb159abea62804432d8d289f0f9aa78adcfda13aa8ca7269e4e34e74bf5ca2045f5b174bdfb58337b8e0ddd6824dc6d6cb1ec3553fd88a2b1d259c33ab069a5d564e2a981077324f60431a8294d8cae96f5b8f120b164c5a2341a34e3242bd4102eedefc38665e5990703d9ed7bbd22c2b7bdb905ed14ed67e6b1a87b6a1544d58e1a69d45d11ddd19630d374848465eefee3327cfedc631f70230eadbbf80547c17dac2524a297e6720\"]}'::jsonb)::eql_v3.text_search)::jsonb))::smallint[])", + "Relation Name": "combo_encrypted_v3_1000000", + "Startup Cost": 290.85, + "Total Cost": 295.37 + } + ], + "Sort Key": [ + "((((category)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Startup Cost": 295.38, + "Total Cost": 295.38 + } + ], + "Startup Cost": 295.38, + "Strategy": "Sorted", + "Total Cost": 295.4 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 295.41, + "Total Cost": 295.41 + } + ], + "Startup Cost": 295.41, + "Total Cost": 295.41 + } + } + ], + "id": "COMBO/combo/top_n_filtered_group_by/1000000", + "indexes_used": [ + "combo_encrypted_v3_1000000_name_match_gin_index" + ], + "parameters": [ + { + "bf": [ + 1471, + 567, + 943, + 1076, + 1673, + 1346 + ], + "c": "mBbK?n#yHO8S<9OhZ5wwj!b#P6_t|pj)n8K?Zo~dhrsIBju0m)@$tkUG0hZ}l)P{ufwd!^FOb85Lx~{q0-yfvT$p$FPm6Rsq;6qtWyBEWG)cPL_Dk-y$tP`SR?}h", + "hm": "d22ac625c9c1daba9b8150da007d2b5439805886ec39577fd9ef95ffe4f86795", + "i": { + "c": "name", + "t": "combo_encrypted_v3_1000000" + }, + "ob": [ + "f8bc8c8c8c8c8c8c148eaac3a25aee669623505bb82c16eb29a7175a9ef4e2a737a2773bf9618cb2cd9052275e9f85cd524150b3812138804ed85eb01498ba3069836158f28bed37ea70b957eba0dedb7716b5ff06e87dd519cb5b26536c0999ca90b109bda9b2e96f77317232133257105cdbf358dc8b95db957a0530f37ae1bc4014d6d80f09c3f5daee23452cdc6846ef2bd879e525ea569d3c31dbe369d74c759d578f4c5a5a97a9c8f407a7058b6995f1df3f07cbdf9f7fc96dfc1dfd8ac223d5e8d50a008f3b9d6cded770d4fa28534887f6e9af5130cf7ca08321dc3572af25a063d72618ecdaef2ab55bbb159abea62804432d8d289f0f9aa78adcfda13aa8ca7269e4e34e74bf5ca2045f5b174bdfb58337b8e0ddd6824dc6d6cb1ec3553fd88a2b1d259c33ab069a5d564e2a981077324f60431a8294d8cae96f5b8f120b164c5a2341a34e3242bd4102eedefc38665e5990703d9ed7bbd22c2b7bdb905ed14ed67e6b1a87b6a1544d58e1a69d45d11ddd19630d374848465eefee3327cfedc631f70230eadbbf80547c17dac2524a297e6720" + ], + "v": 3 + } + ], + "query": "SELECT eql_v3.eq_term(category), count(*) FROM combo_encrypted_v3_1000000 WHERE name @> $1 GROUP BY 1 ORDER BY count(*) DESC LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "1000000" +} \ No newline at end of file diff --git a/results/query/v3/combo_rows_10000.json b/results/query/v3/combo_rows_10000.json new file mode 100644 index 0000000..97e902c --- /dev/null +++ b/results/query/v3/combo_rows_10000.json @@ -0,0 +1,4 @@ +{"reason":"benchmark-complete","id":"COMBO/combo/bloom_ore_order_limit/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/COMBO/combo_bloom_ore_order_limit_10000","iteration_count":[206,412,618,824,1030,1236,1442,1648,1854,2060],"measured_values":[84506042.0,173335167.0,263808084.0,425465125.0,442630041.0,580289958.0,673328792.0,730962333.0,811633333.0,1005926125.0],"unit":"ns","throughput":[],"typical":{"estimate":460778.11796746944,"lower_bound":442237.0766151578,"upper_bound":478909.5911127707,"unit":"ns"},"mean":{"estimate":450995.70337282325,"lower_bound":432549.14673274,"upper_bound":471542.01442946715,"unit":"ns"},"median":{"estimate":440659.643372438,"lower_bound":425227.16432038834,"upper_bound":477627.28138002777,"unit":"ns"},"median_abs_dev":{"estimate":34266.21018898328,"lower_bound":6687.6223575331,"upper_bound":57047.006882261805,"unit":"ns"},"slope":{"estimate":460778.11796746944,"lower_bound":442237.0766151578,"upper_bound":478909.5911127707,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"COMBO/combo/filtered_group_by/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/COMBO/combo_filtered_group_by_10000","iteration_count":[368,736,1104,1472,1840,2208,2576,2944,3312,3680],"measured_values":[81600000.0,163856500.0,252565500.0,372551792.0,424449791.0,550573500.0,591511417.0,711277666.0,805351625.0,804035667.0],"unit":"ns","throughput":[],"typical":{"estimate":234346.6203063241,"lower_bound":225177.7692743022,"upper_bound":243365.81225276765,"unit":"ns"},"mean":{"estimate":233914.49077143715,"lower_bound":226975.68071256042,"upper_bound":241146.00779287438,"unit":"ns"},"median":{"estimate":230151.61576086958,"lower_bound":222631.11413043478,"upper_bound":245478.20414402173,"unit":"ns"},"median_abs_dev":{"estimate":14724.691928054552,"lower_bound":1413.0188979030327,"upper_bound":19938.971862656494,"unit":"ns"},"slope":{"estimate":234346.6203063241,"lower_bound":225177.7692743022,"upper_bound":243365.81225276765,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"COMBO/combo/top_n_filtered_group_by/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/COMBO/combo_top_n_filtered_group_by_10000","iteration_count":[357,714,1071,1428,1785,2142,2499,2856,3213,3570],"measured_values":[85337041.0,166195209.0,249389500.0,332771792.0,472401333.0,490820334.0,633038167.0,742153125.0,825010208.0,890678667.0],"unit":"ns","throughput":[],"typical":{"estimate":251040.6526756157,"lower_bound":242779.06431733217,"upper_bound":256439.15926832092,"unit":"ns"},"mean":{"estimate":245092.4130264328,"lower_bound":237494.84250900365,"upper_bound":252887.23786434295,"unit":"ns"},"median":{"estimate":244264.57661064426,"lower_bound":232856.6760037348,"upper_bound":256772.55150949268,"unit":"ns"},"median_abs_dev":{"estimate":16980.2753628536,"lower_bound":264.9001933363074,"upper_bound":20149.582173400886,"unit":"ns"},"slope":{"estimate":251040.6526756157,"lower_bound":242779.06431733217,"upper_bound":256439.15926832092,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"COMBO","benchmarks":["COMBO/combo/bloom_ore_order_limit/10000","COMBO/combo/filtered_group_by/10000","COMBO/combo/top_n_filtered_group_by/10000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/COMBO"} diff --git a/results/query/v3/combo_rows_100000.json b/results/query/v3/combo_rows_100000.json new file mode 100644 index 0000000..8dfff6e --- /dev/null +++ b/results/query/v3/combo_rows_100000.json @@ -0,0 +1,4 @@ +{"reason":"benchmark-complete","id":"COMBO/combo/bloom_ore_order_limit/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/COMBO/combo_bloom_ore_order_limit_100000","iteration_count":[43,86,129,172,215,258,301,344,387,430],"measured_values":[86975875.0,174983416.0,264837833.0,388396833.0,510192083.0,575497375.0,619226125.0,727930875.0,810233084.0,885613041.0],"unit":"ns","throughput":[],"typical":{"estimate":2119918.226759287,"lower_bound":2077705.7291407776,"upper_bound":2199655.563428783,"unit":"ns"},"mean":{"estimate":2129860.817164083,"lower_bound":2067398.6817958658,"upper_bound":2203313.2029069765,"unit":"ns"},"median":{"estimate":2076595.3758397931,"lower_bound":2045960.2674418604,"upper_bound":2230609.980620155,"unit":"ns"},"median_abs_dev":{"estimate":60332.360889060925,"lower_bound":6261.3070144209405,"upper_bound":190446.12501175408,"unit":"ns"},"slope":{"estimate":2119918.226759287,"lower_bound":2077705.7291407776,"upper_bound":2199655.563428783,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"COMBO/combo/filtered_group_by/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/COMBO/combo_filtered_group_by_100000","iteration_count":[116,232,348,464,580,696,812,928,1044,1160],"measured_values":[87838917.0,176012958.0,264603958.0,384834583.0,441973542.0,564800625.0,616305792.0,746141709.0,842940916.0,965776375.0],"unit":"ns","throughput":[],"typical":{"estimate":803833.2447156291,"lower_bound":779027.0920493884,"upper_bound":820106.4696533978,"unit":"ns"},"mean":{"estimate":788217.796946155,"lower_bound":770033.9637038177,"upper_bound":807011.0245952468,"unit":"ns"},"median":{"estimate":783027.6811422413,"lower_bound":758997.2807881774,"upper_bound":818399.7738266283,"unit":"ns"},"median_abs_dev":{"estimate":36129.573196215555,"lower_bound":1308.570672458039,"upper_bound":41635.41986659947,"unit":"ns"},"slope":{"estimate":803833.2447156291,"lower_bound":779027.0920493884,"upper_bound":820106.4696533978,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"COMBO/combo/top_n_filtered_group_by/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/COMBO/combo_top_n_filtered_group_by_100000","iteration_count":[116,232,348,464,580,696,812,928,1044,1160],"measured_values":[84889792.0,170275042.0,259154375.0,377387375.0,435808792.0,617817458.0,603723125.0,735250458.0,849982458.0,985372292.0],"unit":"ns","throughput":[],"typical":{"estimate":810793.367442902,"lower_bound":772373.7369928346,"upper_bound":839229.4769470849,"unit":"ns"},"mean":{"estimate":786226.2721100164,"lower_bound":756132.0312315271,"upper_bound":819299.8338936782,"unit":"ns"},"median":{"estimate":771845.1105603448,"lower_bound":739320.3132183908,"upper_bound":831396.8661637931,"unit":"ns"},"median_abs_dev":{"estimate":57775.08465915775,"lower_bound":5851.142692845594,"upper_bound":98020.56736995948,"unit":"ns"},"slope":{"estimate":810793.367442902,"lower_bound":772373.7369928346,"upper_bound":839229.4769470849,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"COMBO","benchmarks":["COMBO/combo/bloom_ore_order_limit/100000","COMBO/combo/filtered_group_by/100000","COMBO/combo/top_n_filtered_group_by/100000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/COMBO"} diff --git a/results/query/v3/combo_rows_1000000.json b/results/query/v3/combo_rows_1000000.json new file mode 100644 index 0000000..57bcf21 --- /dev/null +++ b/results/query/v3/combo_rows_1000000.json @@ -0,0 +1,4 @@ +{"reason":"benchmark-complete","id":"COMBO/combo/bloom_ore_order_limit/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/COMBO/combo_bloom_ore_order_limit_1000000","iteration_count":[7,14,21,28,35,42,49,56,63,70],"measured_values":[98483209.0,196502750.0,292287458.0,408574542.0,485710375.0,602321083.0,678036917.0,803944458.0,893891417.0,994400750.0],"unit":"ns","throughput":[],"typical":{"estimate":14178839.317254175,"lower_bound":14028036.853881279,"upper_bound":14296030.628205128,"unit":"ns"},"mean":{"estimate":14142187.312188208,"lower_bound":14006460.236848071,"upper_bound":14288695.583730157,"unit":"ns"},"median":{"estimate":14128891.253968254,"lower_bound":13918450.38095238,"upper_bound":14340978.166666666,"unit":"ns"},"median_abs_dev":{"estimate":313219.841989236,"lower_bound":59231.62386271413,"upper_bound":412190.37963215815,"unit":"ns"},"slope":{"estimate":14178839.317254175,"lower_bound":14028036.853881279,"upper_bound":14296030.628205128,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"COMBO/combo/filtered_group_by/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/COMBO/combo_filtered_group_by_1000000","iteration_count":[18,36,54,72,90,108,126,144,162,180],"measured_values":[111936792.0,188491625.0,278931875.0,372574500.0,491852375.0,555328625.0,677380375.0,764351833.0,858786292.0,946793167.0],"unit":"ns","throughput":[],"typical":{"estimate":5290149.044588745,"lower_bound":5238992.40694053,"upper_bound":5343842.671948716,"unit":"ns"},"mean":{"estimate":5364674.371867283,"lower_bound":5224602.336790509,"upper_bound":5576624.396921296,"unit":"ns"},"median":{"estimate":5280555.994753086,"lower_bound":5174645.833333333,"upper_bound":5386512.614583334,"unit":"ns"},"median_abs_dev":{"estimate":149289.58068291354,"lower_bound":31101.137989511015,"upper_bound":241134.03677063575,"unit":"ns"},"slope":{"estimate":5290149.044588745,"lower_bound":5238992.40694053,"upper_bound":5343842.671948716,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"COMBO/combo/top_n_filtered_group_by/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/COMBO/combo_top_n_filtered_group_by_1000000","iteration_count":[18,36,54,72,90,108,126,144,162,180],"measured_values":[92486166.0,184586916.0,277296667.0,389793167.0,462648042.0,590726125.0,645255791.0,769196958.0,852892000.0,956493875.0],"unit":"ns","throughput":[],"typical":{"estimate":5284509.751515152,"lower_bound":5207565.141574547,"upper_bound":5349108.741087861,"unit":"ns"},"mean":{"estimate":5246601.5799559085,"lower_bound":5172084.163505292,"upper_bound":5326157.3359567905,"unit":"ns"},"median":{"estimate":5202649.616049383,"lower_bound":5132767.333333333,"upper_bound":5363824.423611111,"unit":"ns"},"median_abs_dev":{"estimate":116241.1696744554,"lower_bound":4443.159932229203,"upper_bound":230301.26802781728,"unit":"ns"},"slope":{"estimate":5284509.751515152,"lower_bound":5207565.141574547,"upper_bound":5349108.741087861,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"COMBO","benchmarks":["COMBO/combo/bloom_ore_order_limit/1000000","COMBO/combo/filtered_group_by/1000000","COMBO/combo/top_n_filtered_group_by/1000000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/COMBO"} diff --git a/results/query/v3/exact_metadata_10000.json b/results/query/v3/exact_metadata_10000.json new file mode 100644 index 0000000..51502dc --- /dev/null +++ b/results/query/v3/exact_metadata_10000.json @@ -0,0 +1,281 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 649, + "Plans": [ + { + "Alias": "string_encrypted_v3_10000", + "Async Capable": false, + "Index Cond": "(((value)::jsonb ->> 'hm'::text) = ((('{\"c\": \"mBbJ@pO<31RWq<2Vo1gF#%gQCBETb!kn=gu2|2J}0jLelmc+1B&xl*WJMGZJ&??7QhzJM7AR)R^oa~Ft;Gcf*^=SZ8Ap{Y9ZJUzWuXn&w#ikBUE~R#1Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"string_encrypted_v3_10000\"}, \"v\": 3, \"bf\": [6, 870, 1786, 1726, 2009, 927, 1853, 551, 1662, 1592, 529, 300, 1710, 488, 167, 621, 485, 19, 88, 1112, 528, 558, 1154, 687, 966, 1603, 1454, 1455, 1268, 393, 569, 309, 463, 1197, 238, 1970, 193, 843, 1824, 1766, 964, 1756, 981, 1325, 1414, 578, 1108, 2012, 296, 1953, 373, 1221, 1675, 1161, 1563, 857, 1854, 1470, 1582, 1911, 884, 1545, 697, 1637, 1066, 38, 1912, 164, 1412, 365, 1651, 207, 17, 277, 62, 699, 761, 923, 1772, 712, 385, 1370, 1925], \"hm\": \"b0b055247cded917baabf9b0200b89d76d32981c1ed299fd2210b3217f5baf57\", \"ob\": [\"c5c5aa2ca88a380754bc68f51c80961f466ccfbf630a65e114447e0fc086de94d65e963662935ec00983ec4e8ac643ce31599f418d5df32d71b4d66e9892c679f909bd89cfe0a01152cbe053126d527a31615775bd8c15940a1850271dacff08bcfb2463b6e4e0e2c1f5d65e2778db270453134bad4d46314f0ce95e8a271753b7b6efa372c122690b9a0f0f3031fbfda479b57c8e5ac902b7711944809b948182f305eaa132dfc25cdb32b699c5fb1dcc607b6bdcec05e65f0f114fe2c26f470609e79c78606ae0edf49443476643a98bb90dc97b833748fd6fc3b5b8317afaeac1ce8bcaca9a2d5dec9df1e25ae856b367a21d056325e85534d89a8a832ae885801e152af64b7f7f73eaaf1f49a2f8be3a7fe210ba811d97ab5e00374f1e567f7c078b37d4e443731e3f8d84a8fe4caeca9267d2e812da5ef3ffe41a7a30ae505d228ea7dcc54e10eceee3a88bf852737c588dbccd9d372054da2caa8038a1e311db50b4f7eeb03b7d3aef8fd3c89f4e21caf21a22fe67e2f42122b0a0b847d30dedf0d65fe828d2744c046ce04505a5c7084226e42f73\", \"951757575757575733f0468c7d82d838dbe077939798e6a3ad43556be5c5ed05ea70a2e354ee8b6f3d0566d065838731e54792d7fc5828ccde3e800c818bc246243c799bbe9f15d5b0b8ef862c5b8e740435aabc91b2babea3dc1f93e9828651582e0b25dd28a2f7e8522b56556151b6ce7ef45ab2fb89af4e88ba5c55eff0f1d8137b92e7b94f88cdf7b76e477a88d906c2c1567ec0c8d7dfa51aec655a24daf78a819637261a1ee677f8cf19140db4143dd4584466db2ce3a856e4341dd24302f7783e9e727d3aede3adddf4df01d81ec4a7393ad26f6fbbbcf5b285058c0692e45cac1f292875afac0da65b33d5e9350561da510541f31ed2da8ecdc429ba91db0deb1f8bf6b519e8433a033e07d0d6c268f57f99f1810357fda0bc8e7dbccf2169e87e15bb2386cf1186f712871413faa946ae6e790e6844dafe73cddb50787d0044db7c7a935004e9c6459640c8642036773e57ae198a70211077dbd3541f8638a7daac3082c479c917ea23a7aabf069a821d04ed213e28fe3f0268b08bfbd525974ca8b403a6d7aa2667a5bd409e2a710d7f9f64a8\"]}'::jsonb)::eql_v3.text_search)::jsonb ->> 'hm'::text))", + "Index Name": "string_encrypted_v3_10000_eq_btree_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 649, + "Relation Name": "string_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.41, + "Total Cost": 8.43 + } + ], + "Startup Cost": 0.41, + "Total Cost": 8.43 + } + } + ], + "id": "EXACT/exact/eql_cast/10000", + "indexes_used": [ + "string_encrypted_v3_10000_eq_btree_index" + ], + "parameters": [ + { + "bf": [ + 6, + 870, + 1786, + 1726, + 2009, + 927, + 1853, + 551, + 1662, + 1592, + 529, + 300, + 1710, + 488, + 167, + 621, + 485, + 19, + 88, + 1112, + 528, + 558, + 1154, + 687, + 966, + 1603, + 1454, + 1455, + 1268, + 393, + 569, + 309, + 463, + 1197, + 238, + 1970, + 193, + 843, + 1824, + 1766, + 964, + 1756, + 981, + 1325, + 1414, + 578, + 1108, + 2012, + 296, + 1953, + 373, + 1221, + 1675, + 1161, + 1563, + 857, + 1854, + 1470, + 1582, + 1911, + 884, + 1545, + 697, + 1637, + 1066, + 38, + 1912, + 164, + 1412, + 365, + 1651, + 207, + 17, + 277, + 62, + 699, + 761, + 923, + 1772, + 712, + 385, + 1370, + 1925 + ], + "c": "mBbJ@pO<31RWq<2Vo1gF#%gQCBETb!kn=gu2|2J}0jLelmc+1B&xl*WJMGZJ&??7QhzJM7AR)R^oa~Ft;Gcf*^=SZ8Ap{Y9ZJUzWuXn&w#ikBUE~R#1Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "hm": "b0b055247cded917baabf9b0200b89d76d32981c1ed299fd2210b3217f5baf57", + "i": { + "c": "value", + "t": "string_encrypted_v3_10000" + }, + "ob": [ + "c5c5aa2ca88a380754bc68f51c80961f466ccfbf630a65e114447e0fc086de94d65e963662935ec00983ec4e8ac643ce31599f418d5df32d71b4d66e9892c679f909bd89cfe0a01152cbe053126d527a31615775bd8c15940a1850271dacff08bcfb2463b6e4e0e2c1f5d65e2778db270453134bad4d46314f0ce95e8a271753b7b6efa372c122690b9a0f0f3031fbfda479b57c8e5ac902b7711944809b948182f305eaa132dfc25cdb32b699c5fb1dcc607b6bdcec05e65f0f114fe2c26f470609e79c78606ae0edf49443476643a98bb90dc97b833748fd6fc3b5b8317afaeac1ce8bcaca9a2d5dec9df1e25ae856b367a21d056325e85534d89a8a832ae885801e152af64b7f7f73eaaf1f49a2f8be3a7fe210ba811d97ab5e00374f1e567f7c078b37d4e443731e3f8d84a8fe4caeca9267d2e812da5ef3ffe41a7a30ae505d228ea7dcc54e10eceee3a88bf852737c588dbccd9d372054da2caa8038a1e311db50b4f7eeb03b7d3aef8fd3c89f4e21caf21a22fe67e2f42122b0a0b847d30dedf0d65fe828d2744c046ce04505a5c7084226e42f73", + "951757575757575733f0468c7d82d838dbe077939798e6a3ad43556be5c5ed05ea70a2e354ee8b6f3d0566d065838731e54792d7fc5828ccde3e800c818bc246243c799bbe9f15d5b0b8ef862c5b8e740435aabc91b2babea3dc1f93e9828651582e0b25dd28a2f7e8522b56556151b6ce7ef45ab2fb89af4e88ba5c55eff0f1d8137b92e7b94f88cdf7b76e477a88d906c2c1567ec0c8d7dfa51aec655a24daf78a819637261a1ee677f8cf19140db4143dd4584466db2ce3a856e4341dd24302f7783e9e727d3aede3adddf4df01d81ec4a7393ad26f6fbbbcf5b285058c0692e45cac1f292875afac0da65b33d5e9350561da510541f31ed2da8ecdc429ba91db0deb1f8bf6b519e8433a033e07d0d6c268f57f99f1810357fda0bc8e7dbccf2169e87e15bb2386cf1186f712871413faa946ae6e790e6844dafe73cddb50787d0044db7c7a935004e9c6459640c8642036773e57ae198a70211077dbd3541f8638a7daac3082c479c917ea23a7aabf069a821d04ed213e28fe3f0268b08bfbd525974ca8b403a6d7aa2667a5bd409e2a710d7f9f64a8" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM string_encrypted_v3_10000 WHERE value = $1 LIMIT 1", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 649, + "Plans": [ + { + "Alias": "string_encrypted_v3_10000", + "Async Capable": false, + "Index Cond": "(((value)::jsonb ->> 'hm'::text) = ((('{\"c\": \"mBbL*j*tj3m5o(Z#9rYvPK@!yBA^dMUbV6lODN0kzh%wSOZvH;SP?cwVd|3(Tlb(y5K95XAh4LoF4BlBpTdz~k>&{o(!)ZtPrXNt`~%ERYb%=RW~FvvY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"string_encrypted_v3_10000\"}, \"v\": 3, \"bf\": [300, 843, 1592, 385, 981, 88, 1197, 1414, 1970, 1824, 569, 1112, 558, 697, 463, 1221, 1925, 1603, 485, 19, 309, 238, 1786, 1637, 488, 2012, 1726, 207, 193, 373, 687, 699, 1710, 528, 927, 164, 277, 62, 529, 1545, 1154, 761, 1470, 966, 1766, 1582, 1066, 296, 1772, 578, 1325, 923, 1370, 1455, 1108, 1953, 1675, 1161, 1454, 167, 2009, 6, 1268, 1651, 1912, 870, 1412, 884, 1563, 38, 1854, 1911, 1756, 712, 551, 964, 393, 365, 857, 621, 1853, 17, 1662], \"hm\": \"b0b055247cded917baabf9b0200b89d76d32981c1ed299fd2210b3217f5baf57\", \"ob\": [\"c5c5aa2ca88a380754bc68f51c80961f466ccfbf630a65e114447e0fc086de94d65e963662935ec00983ec4e8ac643ce31599f418d5df32d71b4d66e9892c679f909bd89cfe0a01152cbe053126d527a31615775bd8c15940a1850271dacff08bcfb2463b6e4e0e2c1f5d65e2778db270453134bad4d46314f0ce95e8a271753b7b6efa372c1226905db028b6741814138b847c3ef7ff694294e05d9bc3eb206b825c928d0798cedad94dba2dec18774787269a2e8a98158e71af371c8280edb61059015d16dd3f6e43644dfccbcad9942e49342a7c5915b9fe7f4d4a912c02e0d61c30725008867b4c6996122a637bc9367ae24cd4e721bfcbdb56830f048d2819a83062346cc2e5409eed776f39ae54261f9f5ce184fdc0a5764e7c9a3f71580984112f1f5cf47835f60b6bcc56ca0bee345fc7047c7e8e7675a2e6097d6a48b7d3cfe9ac52937407bd570bc268ab82e060ddc569f4b08c6f48f8bf77e594ca47198b686529a0086c8ba116595f5e04714be721a235208f6d7ab4f6575d2f3ada740668d4fb7606481bd9265bf2b8c5e1c3cfd7e70449e\", \"951757575757575733f0468c7d82d838dbe077939798e6a3ad43556be5c5ed05ea70a2e354ee8b6f3d0566d065838731e54792d7fc5828ccde3e800c818bc246243c799bbe9f15d5b0b8ef862c5b8e740435aabc91b2babea3dc1f93e9828651582e0b25dd28a2f7e8522b56556151b6ce7ef45ab2fb89af4e88ba5c55eff0f1d8137b92e7b94f88416b4cb4144a3a960ac995d76fcd1dd1821eb2c081aead71ff9a373e62d740c80119a344c6d14a96f2bc78b21849458b507d1b2a2c9ca2b64260122b1834111d7f4582b76cfd0d8ec516a7dc72bdc0d3248ccf39e8182f855b164190e86279d4a7b46b053286fb13aed52abdd9952a168c8cd567b435512ee76f952a17a403d80c254539c7c7018eb2902716688c98008594eb0e77e9ba7e7c41f13080c4088428182db3565a5ec76ec611949cf1a1e2624942eceff2c8e6fa81fe91118c7bd718cd3c476ab3f08d9643c9f2a0ccd8c3d1304f5c3917f1ff31e55743a438dc2a104b61a92440036a90998a8aba29777d63713af08326dfc7340ca68e58c71cec1053a14d0c016ae1aca548d84e1c39ee\"]}'::jsonb)::eql_v3.text_search)::jsonb ->> 'hm'::text))", + "Index Name": "string_encrypted_v3_10000_eq_btree_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 649, + "Relation Name": "string_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.41, + "Total Cost": 8.43 + } + ], + "Startup Cost": 0.41, + "Total Cost": 8.43 + } + } + ], + "id": "EXACT/exact/eql_hash/10000", + "indexes_used": [ + "string_encrypted_v3_10000_eq_btree_index" + ], + "parameters": [ + { + "bf": [ + 300, + 843, + 1592, + 385, + 981, + 88, + 1197, + 1414, + 1970, + 1824, + 569, + 1112, + 558, + 697, + 463, + 1221, + 1925, + 1603, + 485, + 19, + 309, + 238, + 1786, + 1637, + 488, + 2012, + 1726, + 207, + 193, + 373, + 687, + 699, + 1710, + 528, + 927, + 164, + 277, + 62, + 529, + 1545, + 1154, + 761, + 1470, + 966, + 1766, + 1582, + 1066, + 296, + 1772, + 578, + 1325, + 923, + 1370, + 1455, + 1108, + 1953, + 1675, + 1161, + 1454, + 167, + 2009, + 6, + 1268, + 1651, + 1912, + 870, + 1412, + 884, + 1563, + 38, + 1854, + 1911, + 1756, + 712, + 551, + 964, + 393, + 365, + 857, + 621, + 1853, + 17, + 1662 + ], + "c": "mBbL*j*tj3m5o(Z#9rYvPK@!yBA^dMUbV6lODN0kzh%wSOZvH;SP?cwVd|3(Tlb(y5K95XAh4LoF4BlBpTdz~k>&{o(!)ZtPrXNt`~%ERYb%=RW~FvvY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "hm": "b0b055247cded917baabf9b0200b89d76d32981c1ed299fd2210b3217f5baf57", + "i": { + "c": "value", + "t": "string_encrypted_v3_10000" + }, + "ob": [ + "c5c5aa2ca88a380754bc68f51c80961f466ccfbf630a65e114447e0fc086de94d65e963662935ec00983ec4e8ac643ce31599f418d5df32d71b4d66e9892c679f909bd89cfe0a01152cbe053126d527a31615775bd8c15940a1850271dacff08bcfb2463b6e4e0e2c1f5d65e2778db270453134bad4d46314f0ce95e8a271753b7b6efa372c1226905db028b6741814138b847c3ef7ff694294e05d9bc3eb206b825c928d0798cedad94dba2dec18774787269a2e8a98158e71af371c8280edb61059015d16dd3f6e43644dfccbcad9942e49342a7c5915b9fe7f4d4a912c02e0d61c30725008867b4c6996122a637bc9367ae24cd4e721bfcbdb56830f048d2819a83062346cc2e5409eed776f39ae54261f9f5ce184fdc0a5764e7c9a3f71580984112f1f5cf47835f60b6bcc56ca0bee345fc7047c7e8e7675a2e6097d6a48b7d3cfe9ac52937407bd570bc268ab82e060ddc569f4b08c6f48f8bf77e594ca47198b686529a0086c8ba116595f5e04714be721a235208f6d7ab4f6575d2f3ada740668d4fb7606481bd9265bf2b8c5e1c3cfd7e70449e", + "951757575757575733f0468c7d82d838dbe077939798e6a3ad43556be5c5ed05ea70a2e354ee8b6f3d0566d065838731e54792d7fc5828ccde3e800c818bc246243c799bbe9f15d5b0b8ef862c5b8e740435aabc91b2babea3dc1f93e9828651582e0b25dd28a2f7e8522b56556151b6ce7ef45ab2fb89af4e88ba5c55eff0f1d8137b92e7b94f88416b4cb4144a3a960ac995d76fcd1dd1821eb2c081aead71ff9a373e62d740c80119a344c6d14a96f2bc78b21849458b507d1b2a2c9ca2b64260122b1834111d7f4582b76cfd0d8ec516a7dc72bdc0d3248ccf39e8182f855b164190e86279d4a7b46b053286fb13aed52abdd9952a168c8cd567b435512ee76f952a17a403d80c254539c7c7018eb2902716688c98008594eb0e77e9ba7e7c41f13080c4088428182db3565a5ec76ec611949cf1a1e2624942eceff2c8e6fa81fe91118c7bd718cd3c476ab3f08d9643c9f2a0ccd8c3d1304f5c3917f1ff31e55743a438dc2a104b61a92440036a90998a8aba29777d63713af08326dfc7340ca68e58c71cec1053a14d0c016ae1aca548d84e1c39ee" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM string_encrypted_v3_10000 WHERE eql_v3.eq_term(value) = eql_v3.eq_term($1::eql_v3.text_search) LIMIT 1", + "rows_returned": 1 + } + ], + "target_rows": "10000" +} \ No newline at end of file diff --git a/results/query/v3/exact_metadata_100000.json b/results/query/v3/exact_metadata_100000.json new file mode 100644 index 0000000..147dd97 --- /dev/null +++ b/results/query/v3/exact_metadata_100000.json @@ -0,0 +1,267 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 635, + "Plans": [ + { + "Alias": "string_encrypted_v3_100000", + "Async Capable": false, + "Index Cond": "(((value)::jsonb ->> 'hm'::text) = ((('{\"c\": \"mBbLN+r8g4YgcBdu+5a_Lnqe6A#q049S2ijJ3B5-T>G%kqL=V?kAf;R~XSl>5Z(?Nrmp-cHXD2slwK}s02`W`yy5>p<#pW>YmsLmarFLO#b!Eg5> 'hm'::text))", + "Index Name": "string_encrypted_v3_100000_eq_btree_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 635, + "Relation Name": "string_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.42, + "Total Cost": 8.44 + } + ], + "Startup Cost": 0.42, + "Total Cost": 8.44 + } + } + ], + "id": "EXACT/exact/eql_cast/100000", + "indexes_used": [ + "string_encrypted_v3_100000_eq_btree_index" + ], + "parameters": [ + { + "bf": [ + 1350, + 141, + 1697, + 1485, + 1453, + 1805, + 286, + 1531, + 1254, + 204, + 1615, + 748, + 36, + 763, + 461, + 1589, + 1885, + 1315, + 588, + 607, + 827, + 300, + 925, + 1504, + 1373, + 1090, + 159, + 1309, + 130, + 586, + 351, + 725, + 792, + 1672, + 1920, + 1841, + 1765, + 1247, + 1641, + 1592, + 438, + 1405, + 556, + 426, + 1081, + 951, + 147, + 233, + 251, + 1333, + 1341, + 632, + 808, + 1230, + 1699, + 804, + 410, + 1422, + 1556, + 2021, + 1593, + 1818, + 1355, + 1590, + 1969, + 1994, + 1541, + 1400, + 1826, + 238, + 1537, + 677, + 1075, + 637, + 18, + 1813 + ], + "c": "mBbLN+r8g4YgcBdu+5a_Lnqe6A#q049S2ijJ3B5-T>G%kqL=V?kAf;R~XSl>5Z(?Nrmp-cHXD2slwK}s02`W`yy5>p<#pW>YmsLmarFLO#b!Eg5> 'hm'::text) = ((('{\"c\": \"mBbJSl}Ec!H_TSK+j{`dYu2U2A+WSn+k~c)jauZ$1dPl4hr;4M{-+}t2P>1$}+?t)i&A-hFy)yv#8w{K!4|Jn!!_<<+Oe!$FC%WjGyu3rFLO#b!Eg5> 'hm'::text))", + "Index Name": "string_encrypted_v3_100000_eq_btree_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 635, + "Relation Name": "string_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.42, + "Total Cost": 8.44 + } + ], + "Startup Cost": 0.42, + "Total Cost": 8.44 + } + } + ], + "id": "EXACT/exact/eql_hash/100000", + "indexes_used": [ + "string_encrypted_v3_100000_eq_btree_index" + ], + "parameters": [ + { + "bf": [ + 1765, + 1818, + 1593, + 1485, + 1373, + 1920, + 1333, + 725, + 1309, + 1969, + 586, + 1350, + 1531, + 159, + 792, + 36, + 925, + 556, + 438, + 804, + 426, + 827, + 1841, + 1090, + 204, + 637, + 141, + 1254, + 238, + 147, + 1315, + 1230, + 1556, + 1541, + 1355, + 1247, + 351, + 1504, + 286, + 1590, + 588, + 1081, + 748, + 951, + 410, + 1615, + 1537, + 1422, + 1400, + 1075, + 1592, + 1885, + 1826, + 233, + 1453, + 461, + 632, + 1813, + 18, + 1405, + 677, + 251, + 1699, + 1341, + 808, + 763, + 1589, + 1641, + 607, + 1994, + 1697, + 300, + 1805, + 130, + 1672, + 2021 + ], + "c": "mBbJSl}Ec!H_TSK+j{`dYu2U2A+WSn+k~c)jauZ$1dPl4hr;4M{-+}t2P>1$}+?t)i&A-hFy)yv#8w{K!4|Jn!!_<<+Oe!$FC%WjGyu3rFLO#b!Eg5> 'hm'::text) = ((('{\"c\": \"mBbJdt#m#xF-e-eiNK9exV6i~9!7y^kZw24Q{Ux3r)d74=laAYW?=YKsT+08{odOj1_;s(tmi-sG_stf(ev$Oo>sBBgd=Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"string_encrypted_v3_1000000\"}, \"v\": 3, \"bf\": [220, 422, 1613, 1366, 1893, 677, 748, 621, 167, 884, 1770, 973, 986, 1392, 578, 1098, 1114, 1968, 141, 1529, 290, 1897, 1772, 1106, 964, 981, 1603, 93, 1662, 830, 1066, 1470, 802, 1663, 38, 1325, 1412, 1592, 1487, 788, 1699, 1360, 1370, 1563, 602, 173, 1369, 584, 887, 551, 769, 331, 1710, 365, 296, 1766, 761, 2036, 2018, 1637], \"hm\": \"848bc7b916bdb4038118ecad4ec5cca948ff41d628e9c1c7f79c4b595dda3b4f\", \"ob\": [\"26157d3ada2a0dacf1e9f3d8959225b29bf4516b76043b053b4322e06c45b0bf7094c9b385464299cef6045327c7d2dbb09ac938175caf732efa2fd5fc9d5a04b6e61bc7df41237b3bcc3ea0fae2d492766d799e3c3beeeb24d82f43039473ba8faa768120b72af48d7e60373a1adb47c0fc48bb40bc8f01f4d9fa25c414db43799b04523bd26ef40c2ee80dbea777b741bed5c88384bab3405b928a948a9b35e886d7f3f585f7886e6621c7b18e6da2ef5c16ce142f23eebaf840370767702ad4ca227fba25fe07156c64d0e4786256f1b9fcde333d52ae825a0fe91a3e43945acbbdf38e9f2f65479f59d59c0985275875204b88b056f05f1abccdf10d7428dcfe0cf55f002fce27ff62e6e2b07c90e450311f5898391bc6062e035dd1346c7dce1dea519a88037c45a603adb1b3bd9295d3e633865c4ff98a51b1669c5c04dbcf76739f00b28481107b4166a7582f65387f31df13424b4c491d4c056261aae6888e821a3f86a06e8f24c3136e7ed801d15b3095db408a1a63e2ce7cef8462612c2948cbe34948daede275b3ee8588533668af10763068\"]}'::jsonb)::eql_v3.text_search)::jsonb ->> 'hm'::text))", + "Index Name": "string_encrypted_v3_1000000_eq_btree_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 2, + "Plan Width": 640, + "Relation Name": "string_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.56, + "Total Cost": 12.59 + } + ], + "Startup Cost": 0.56, + "Total Cost": 6.57 + } + } + ], + "id": "EXACT/exact/eql_cast/1000000", + "indexes_used": [ + "string_encrypted_v3_1000000_eq_btree_index" + ], + "parameters": [ + { + "bf": [ + 220, + 422, + 1613, + 1366, + 1893, + 677, + 748, + 621, + 167, + 884, + 1770, + 973, + 986, + 1392, + 578, + 1098, + 1114, + 1968, + 141, + 1529, + 290, + 1897, + 1772, + 1106, + 964, + 981, + 1603, + 93, + 1662, + 830, + 1066, + 1470, + 802, + 1663, + 38, + 1325, + 1412, + 1592, + 1487, + 788, + 1699, + 1360, + 1370, + 1563, + 602, + 173, + 1369, + 584, + 887, + 551, + 769, + 331, + 1710, + 365, + 296, + 1766, + 761, + 2036, + 2018, + 1637 + ], + "c": "mBbJdt#m#xF-e-eiNK9exV6i~9!7y^kZw24Q{Ux3r)d74=laAYW?=YKsT+08{odOj1_;s(tmi-sG_stf(ev$Oo>sBBgd=Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "hm": "848bc7b916bdb4038118ecad4ec5cca948ff41d628e9c1c7f79c4b595dda3b4f", + "i": { + "c": "value", + "t": "string_encrypted_v3_1000000" + }, + "ob": [ + "26157d3ada2a0dacf1e9f3d8959225b29bf4516b76043b053b4322e06c45b0bf7094c9b385464299cef6045327c7d2dbb09ac938175caf732efa2fd5fc9d5a04b6e61bc7df41237b3bcc3ea0fae2d492766d799e3c3beeeb24d82f43039473ba8faa768120b72af48d7e60373a1adb47c0fc48bb40bc8f01f4d9fa25c414db43799b04523bd26ef40c2ee80dbea777b741bed5c88384bab3405b928a948a9b35e886d7f3f585f7886e6621c7b18e6da2ef5c16ce142f23eebaf840370767702ad4ca227fba25fe07156c64d0e4786256f1b9fcde333d52ae825a0fe91a3e43945acbbdf38e9f2f65479f59d59c0985275875204b88b056f05f1abccdf10d7428dcfe0cf55f002fce27ff62e6e2b07c90e450311f5898391bc6062e035dd1346c7dce1dea519a88037c45a603adb1b3bd9295d3e633865c4ff98a51b1669c5c04dbcf76739f00b28481107b4166a7582f65387f31df13424b4c491d4c056261aae6888e821a3f86a06e8f24c3136e7ed801d15b3095db408a1a63e2ce7cef8462612c2948cbe34948daede275b3ee8588533668af10763068" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM string_encrypted_v3_1000000 WHERE value = $1 LIMIT 1", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 640, + "Plans": [ + { + "Alias": "string_encrypted_v3_1000000", + "Async Capable": false, + "Index Cond": "(((value)::jsonb ->> 'hm'::text) = ((('{\"c\": \"mBbLpfeKUBfl{rFVU-@|sB|z?Ay}8nH44)4k_@#DXY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"string_encrypted_v3_1000000\"}, \"v\": 3, \"bf\": [964, 1360, 1369, 830, 1663, 748, 1968, 1710, 1098, 365, 2018, 1766, 331, 884, 38, 1770, 1370, 1529, 1487, 220, 1772, 296, 981, 621, 1114, 141, 2036, 1412, 1366, 1897, 788, 1603, 1066, 986, 1637, 173, 887, 167, 1699, 677, 602, 1563, 761, 769, 973, 584, 93, 1592, 1106, 1470, 290, 1392, 1893, 578, 1662, 802, 1613, 422, 1325, 551], \"hm\": \"848bc7b916bdb4038118ecad4ec5cca948ff41d628e9c1c7f79c4b595dda3b4f\", \"ob\": [\"26157d3ada2a0dacf1e9f3d8959225b29bf4516b76043b053b4322e06c45b0bf7094c9b385464299cef6045327c7d2dbb09ac938175caf732efa2fd5fc9d5a04b6e61bc7df41237b3bcc3ea0fae2d492766d799e3c3beeeb24d82f43039473ba8faa768120b72af48d7e60373a1adb47c0fc48bb40bc8f01f4d9fa25c414db43799b04523bd26ef441d4aa82be97710bebf2a5ab7b20d4f9d5ed764b7f1c85713311594bbc7d4ed56ce568ae730c28fc8bb37ffb6f72486f02f910903a78727abe013d2e3ab2025aecc80da2ecec6fffa65775c9448f76a34940235cdc8b3526de544e0c6eb2803de8016a3e8f59be3f0e8d06aa30aa58543eba5cabad8c17aff95452483600d1a9a901a2b112b66cfc46c33dc710426a84436c3d33bfd8c006a118e0898d3a15c09d1bf97f9b6864c807a8920fa5705c0bba2c274b817a3cf89a1c21e796b47dff20c4da5150996cb965dce5de13e13fce060b001cbce747dfca51cd8dc74da9892a2c1df3a2da233eb30d5a597ad2c76bfd4a9d2b220815681e9163966d85fe30eec8b9ce1dcf3ce84a146a9ddb72d6f6\"]}'::jsonb)::eql_v3.text_search)::jsonb ->> 'hm'::text))", + "Index Name": "string_encrypted_v3_1000000_eq_btree_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 2, + "Plan Width": 640, + "Relation Name": "string_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.56, + "Total Cost": 12.59 + } + ], + "Startup Cost": 0.56, + "Total Cost": 6.57 + } + } + ], + "id": "EXACT/exact/eql_hash/1000000", + "indexes_used": [ + "string_encrypted_v3_1000000_eq_btree_index" + ], + "parameters": [ + { + "bf": [ + 964, + 1360, + 1369, + 830, + 1663, + 748, + 1968, + 1710, + 1098, + 365, + 2018, + 1766, + 331, + 884, + 38, + 1770, + 1370, + 1529, + 1487, + 220, + 1772, + 296, + 981, + 621, + 1114, + 141, + 2036, + 1412, + 1366, + 1897, + 788, + 1603, + 1066, + 986, + 1637, + 173, + 887, + 167, + 1699, + 677, + 602, + 1563, + 761, + 769, + 973, + 584, + 93, + 1592, + 1106, + 1470, + 290, + 1392, + 1893, + 578, + 1662, + 802, + 1613, + 422, + 1325, + 551 + ], + "c": "mBbLpfeKUBfl{rFVU-@|sB|z?Ay}8nH44)4k_@#DXY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "hm": "848bc7b916bdb4038118ecad4ec5cca948ff41d628e9c1c7f79c4b595dda3b4f", + "i": { + "c": "value", + "t": "string_encrypted_v3_1000000" + }, + "ob": [ + "26157d3ada2a0dacf1e9f3d8959225b29bf4516b76043b053b4322e06c45b0bf7094c9b385464299cef6045327c7d2dbb09ac938175caf732efa2fd5fc9d5a04b6e61bc7df41237b3bcc3ea0fae2d492766d799e3c3beeeb24d82f43039473ba8faa768120b72af48d7e60373a1adb47c0fc48bb40bc8f01f4d9fa25c414db43799b04523bd26ef441d4aa82be97710bebf2a5ab7b20d4f9d5ed764b7f1c85713311594bbc7d4ed56ce568ae730c28fc8bb37ffb6f72486f02f910903a78727abe013d2e3ab2025aecc80da2ecec6fffa65775c9448f76a34940235cdc8b3526de544e0c6eb2803de8016a3e8f59be3f0e8d06aa30aa58543eba5cabad8c17aff95452483600d1a9a901a2b112b66cfc46c33dc710426a84436c3d33bfd8c006a118e0898d3a15c09d1bf97f9b6864c807a8920fa5705c0bba2c274b817a3cf89a1c21e796b47dff20c4da5150996cb965dce5de13e13fce060b001cbce747dfca51cd8dc74da9892a2c1df3a2da233eb30d5a597ad2c76bfd4a9d2b220815681e9163966d85fe30eec8b9ce1dcf3ce84a146a9ddb72d6f6" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM string_encrypted_v3_1000000 WHERE eql_v3.eq_term(value) = eql_v3.eq_term($1::eql_v3.text_search) LIMIT 1", + "rows_returned": 1 + } + ], + "target_rows": "1000000" +} \ No newline at end of file diff --git a/results/query/v3/exact_metadata_10000000.json b/results/query/v3/exact_metadata_10000000.json new file mode 100644 index 0000000..7d661e1 --- /dev/null +++ b/results/query/v3/exact_metadata_10000000.json @@ -0,0 +1,293 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 636, + "Plans": [ + { + "Alias": "string_encrypted_v3_10000000", + "Async Capable": false, + "Index Cond": "(((value)::jsonb ->> 'hm'::text) = ((('{\"c\": \"mBbLA^%@(97XVTaaM9LYMt-ftBR5CY5R#2|34Hi1MR-oCrXvA%LspSYovTTH9Ey}M> 'hm'::text))", + "Index Name": "string_encrypted_v3_10000000_eq_btree_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 8, + "Plan Width": 636, + "Relation Name": "string_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.56, + "Total Cost": 36.7 + } + ], + "Startup Cost": 0.56, + "Total Cost": 5.08 + } + } + ], + "id": "EXACT/exact/eql_cast/10000000", + "indexes_used": [ + "string_encrypted_v3_10000000_eq_btree_index" + ], + "parameters": [ + { + "bf": [ + 1885, + 295, + 902, + 1007, + 808, + 951, + 792, + 1645, + 1593, + 607, + 661, + 286, + 1097, + 159, + 516, + 870, + 426, + 1767, + 1590, + 1693, + 151, + 1751, + 1664, + 1058, + 1561, + 804, + 802, + 1641, + 750, + 556, + 1821, + 166, + 1765, + 341, + 1451, + 620, + 474, + 464, + 315, + 1774, + 1350, + 386, + 586, + 1805, + 1467, + 1254, + 1341, + 1355, + 780, + 408, + 1315, + 1670, + 402, + 1453, + 925, + 1676, + 1699, + 289, + 1348, + 588, + 2021, + 36, + 1405, + 1065, + 1762, + 1875, + 564, + 1309, + 763, + 1671, + 383, + 637, + 410, + 1075, + 434, + 634, + 632, + 723, + 20, + 38, + 1241, + 417, + 1877, + 1064, + 83, + 1081, + 1952, + 1589, + 677 + ], + "c": "mBbLA^%@(97XVTaaM9LYMt-ftBR5CY5R#2|34Hi1MR-oCrXvA%LspSYovTTH9Ey}M> 'hm'::text) = ((('{\"c\": \"mBbLqC5@G1suIviQg^nWXnOg?BbiPoYlp6+G9t?!&!?K%ASRq!)qQ37AlfBV@ejYDkVIUE#2}J{*(X&vygtFk*+>$~{febuEPC^=d=Ht)hn?;Yg=(dCVQh6}#1Q2)NxIzjOYXJFCv9j}(_#\", \"i\": {\"c\": \"value\", \"t\": \"string_encrypted_v3_10000000\"}, \"v\": 3, \"bf\": [2021, 286, 410, 802, 1065, 386, 780, 1341, 1467, 632, 289, 1670, 516, 402, 1254, 808, 1451, 36, 1699, 1664, 1676, 1315, 38, 1081, 1075, 1405, 607, 1875, 341, 951, 408, 556, 1453, 426, 295, 1767, 166, 564, 151, 1885, 1589, 586, 804, 315, 1877, 792, 474, 902, 1007, 1821, 83, 1762, 1751, 634, 925, 417, 677, 1350, 434, 1097, 1693, 1952, 1348, 870, 1590, 1241, 1309, 1058, 637, 20, 1355, 763, 383, 1805, 1064, 1765, 159, 1774, 1593, 464, 661, 723, 1645, 1671, 588, 1561, 620, 750, 1641], \"hm\": \"d2724b9d2d45e0f740a3e916f1c6dbd21ba93c51b1e298a24d6018ba6044696d\", \"ob\": [\"e23a02c59ee11eab8020a79df213755783bcaf970aaf69061eac8ea97b8b912015cb1436737b200f5b9a3094a55f8766eab33944b6845c16adecc15df7879a9d6ac329cc890a2ed026395d422c1de4f0221f10655a3fa5dd3617fd9587add7ca996d485751069db560add03feed5fd5616682fb53c2680db98d951dcf77d2b35ac8b002486588470df6572451311826120cb16cb80f64253c8b50c85154266fd70ff15fd2858b9e6770ba811816ccf00a648fe382f730637bbe32ca7200e7c3949d50c3c7b36a27e4a1f0c53998479afb8d3fce537b7e01102ad77477f182da29923fc84a285ecc7b9b003acbdaf56783f7e773f88a6cd47e0e157d533e8a169ab6d3fdef0a292a620f89d04a2f1926ba4d7826c49a04ba122e3e30bf1e068327e2cb438a859b6801a52a38da654bf9c0f647c1e4c35e1b23e42a74621ae027c23322becbc337879fb230f3b019516fbc6b38e1bda57bac2286b9e471f9042b2cb578cde41f66bcd23c03e6b2d04d97f63fc70cddd8ad73f82a6ee293431b451bcfa17f5e5bd7f1a26f73d8eae9312ac507e925e77f9a8c7\", \"6e8a31fdfdfdfdfdd2a053164937bd39150b308f9210a6e0cdc08b07417c519d6ad5de4cd889057cbc2a7f8adf8c7b3ddcc2473e84b00b73a4d10f0e589325765d79859d47ade23cc46291670457cb1ba250da2b8b65b6c81fb158654d6d129a6e6e3a4955e7f9915b203582b0e8cd55897c95fecb19f69bf075819846b0efbe80f131fd8b586e2c66cb75d1cdebeb53ed1fac08762e77a03c76bd6b3c30ed6506f8979827234f39bb0c7a2854e0f559f330b220509ad0b637e0e591d2ad107dfc546bba015d25704e9884a83a918ac136dfdfd858aa5dd3b4154e84a54859faced3ab538d993caf8be511d26ed0dcf8991adfa956bda96ed4d1bcef8f4819a99acd9560c825ead72134b715b07156deb9538641936a96d10f8ab163af40d54011ca03e2caaef477ac36c9b56ca5ec2a930d75b8b4c35e45e40d3be8419f71dc16c45031f9f5a5d6c0a2719f84acf367c754318d7d6a0d65af7bd1f00e4b1df511b3af76e98fc701655bcdc5c9765b7539e6918b316a6b045ee5a463e5bf2bed05ce9e6a6947ee524391cd85db4397c688006e171da346bd\"]}'::jsonb)::eql_v3.text_search)::jsonb ->> 'hm'::text))", + "Index Name": "string_encrypted_v3_10000000_eq_btree_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 8, + "Plan Width": 636, + "Relation Name": "string_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.56, + "Total Cost": 36.7 + } + ], + "Startup Cost": 0.56, + "Total Cost": 5.08 + } + } + ], + "id": "EXACT/exact/eql_hash/10000000", + "indexes_used": [ + "string_encrypted_v3_10000000_eq_btree_index" + ], + "parameters": [ + { + "bf": [ + 2021, + 286, + 410, + 802, + 1065, + 386, + 780, + 1341, + 1467, + 632, + 289, + 1670, + 516, + 402, + 1254, + 808, + 1451, + 36, + 1699, + 1664, + 1676, + 1315, + 38, + 1081, + 1075, + 1405, + 607, + 1875, + 341, + 951, + 408, + 556, + 1453, + 426, + 295, + 1767, + 166, + 564, + 151, + 1885, + 1589, + 586, + 804, + 315, + 1877, + 792, + 474, + 902, + 1007, + 1821, + 83, + 1762, + 1751, + 634, + 925, + 417, + 677, + 1350, + 434, + 1097, + 1693, + 1952, + 1348, + 870, + 1590, + 1241, + 1309, + 1058, + 637, + 20, + 1355, + 763, + 383, + 1805, + 1064, + 1765, + 159, + 1774, + 1593, + 464, + 661, + 723, + 1645, + 1671, + 588, + 1561, + 620, + 750, + 1641 + ], + "c": "mBbLqC5@G1suIviQg^nWXnOg?BbiPoYlp6+G9t?!&!?K%ASRq!)qQ37AlfBV@ejYDkVIUE#2}J{*(X&vygtFk*+>$~{febuEPC^=d=Ht)hn?;Yg=(dCVQh6}#1Q2)NxIzjOYXJFCv9j}(_#", + "hm": "d2724b9d2d45e0f740a3e916f1c6dbd21ba93c51b1e298a24d6018ba6044696d", + "i": { + "c": "value", + "t": "string_encrypted_v3_10000000" + }, + "ob": [ + "e23a02c59ee11eab8020a79df213755783bcaf970aaf69061eac8ea97b8b912015cb1436737b200f5b9a3094a55f8766eab33944b6845c16adecc15df7879a9d6ac329cc890a2ed026395d422c1de4f0221f10655a3fa5dd3617fd9587add7ca996d485751069db560add03feed5fd5616682fb53c2680db98d951dcf77d2b35ac8b002486588470df6572451311826120cb16cb80f64253c8b50c85154266fd70ff15fd2858b9e6770ba811816ccf00a648fe382f730637bbe32ca7200e7c3949d50c3c7b36a27e4a1f0c53998479afb8d3fce537b7e01102ad77477f182da29923fc84a285ecc7b9b003acbdaf56783f7e773f88a6cd47e0e157d533e8a169ab6d3fdef0a292a620f89d04a2f1926ba4d7826c49a04ba122e3e30bf1e068327e2cb438a859b6801a52a38da654bf9c0f647c1e4c35e1b23e42a74621ae027c23322becbc337879fb230f3b019516fbc6b38e1bda57bac2286b9e471f9042b2cb578cde41f66bcd23c03e6b2d04d97f63fc70cddd8ad73f82a6ee293431b451bcfa17f5e5bd7f1a26f73d8eae9312ac507e925e77f9a8c7", + "6e8a31fdfdfdfdfdd2a053164937bd39150b308f9210a6e0cdc08b07417c519d6ad5de4cd889057cbc2a7f8adf8c7b3ddcc2473e84b00b73a4d10f0e589325765d79859d47ade23cc46291670457cb1ba250da2b8b65b6c81fb158654d6d129a6e6e3a4955e7f9915b203582b0e8cd55897c95fecb19f69bf075819846b0efbe80f131fd8b586e2c66cb75d1cdebeb53ed1fac08762e77a03c76bd6b3c30ed6506f8979827234f39bb0c7a2854e0f559f330b220509ad0b637e0e591d2ad107dfc546bba015d25704e9884a83a918ac136dfdfd858aa5dd3b4154e84a54859faced3ab538d993caf8be511d26ed0dcf8991adfa956bda96ed4d1bcef8f4819a99acd9560c825ead72134b715b07156deb9538641936a96d10f8ab163af40d54011ca03e2caaef477ac36c9b56ca5ec2a930d75b8b4c35e45e40d3be8419f71dc16c45031f9f5a5d6c0a2719f84acf367c754318d7d6a0d65af7bd1f00e4b1df511b3af76e98fc701655bcdc5c9765b7539e6918b316a6b045ee5a463e5bf2bed05ce9e6a6947ee524391cd85db4397c688006e171da346bd" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM string_encrypted_v3_10000000 WHERE eql_v3.eq_term(value) = eql_v3.eq_term($1::eql_v3.text_search) LIMIT 1", + "rows_returned": 1 + } + ], + "target_rows": "10000000" +} \ No newline at end of file diff --git a/results/query/v3/exact_rows_10000.json b/results/query/v3/exact_rows_10000.json new file mode 100644 index 0000000..14d4343 --- /dev/null +++ b/results/query/v3/exact_rows_10000.json @@ -0,0 +1,5 @@ +{"reason":"benchmark-complete","id":"EXACT/exact/eql_cast/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_eql_cast_10000","iteration_count":[714,1428,2142,2856,3570,4284,4998,5712,6426,7140],"measured_values":[75542208.0,156337875.0,263346834.0,341981333.0,465738708.0,609119667.0,673543750.0,759563000.0,866580417.0,903623292.0],"unit":"ns","throughput":[],"typical":{"estimate":131530.29305176617,"lower_bound":127498.67750219816,"upper_bound":135273.90727395608,"unit":"ns"},"mean":{"estimate":125976.38596138456,"lower_bound":118923.1781112445,"upper_bound":132472.52836334534,"unit":"ns"},"median":{"estimate":128508.45294117647,"lower_bound":116212.33578431373,"upper_bound":134762.6550620248,"unit":"ns"},"median_abs_dev":{"estimate":9341.187492227997,"lower_bound":1461.3320206948474,"upper_bound":18810.513641046622,"unit":"ns"},"slope":{"estimate":131530.29305176617,"lower_bound":127498.67750219816,"upper_bound":135273.90727395608,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"EXACT/exact_decrypt/eql_cast/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_decrypt_eql_cast_10000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[90414958.0,199535250.0,294509458.0,444694958.0,490433167.0,603302042.0,701465667.0,774522417.0,847873541.0,937610166.0],"unit":"ns","throughput":[],"typical":{"estimate":24244918.366883118,"lower_bound":23749158.284176093,"upper_bound":25155538.08504846,"unit":"ns"},"mean":{"estimate":24578924.662847225,"lower_bound":23833567.74277778,"upper_bound":25455818.60173611,"unit":"ns"},"median":{"estimate":24532056.59166667,"lower_bound":23552042.805555556,"upper_bound":25052345.25,"unit":"ns"},"median_abs_dev":{"estimate":834568.2384784481,"lower_bound":145056.71657472756,"upper_bound":2012104.4632630036,"unit":"ns"},"slope":{"estimate":24244918.366883118,"lower_bound":23749158.284176093,"upper_bound":25155538.08504846,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"EXACT/exact/eql_hash/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_eql_hash_10000","iteration_count":[739,1478,2217,2956,3695,4434,5173,5912,6651,7390],"measured_values":[86738375.0,174579500.0,265202792.0,407233500.0,444470959.0,586272750.0,615302500.0,729428125.0,847748417.0,928861417.0],"unit":"ns","throughput":[],"typical":{"estimate":125340.74993937051,"lower_bound":122278.56295875271,"upper_bound":128247.22441722453,"unit":"ns"},"mean":{"estimate":124087.01359811627,"lower_bound":120404.85364000042,"upper_bound":128275.19555270959,"unit":"ns"},"median":{"estimate":121835.39067997294,"lower_bound":118870.55525484889,"upper_bound":128956.87868741542,"unit":"ns"},"median_abs_dev":{"estimate":5613.809328223998,"lower_bound":1004.2629136998623,"upper_bound":10826.87607712936,"unit":"ns"},"slope":{"estimate":125340.74993937051,"lower_bound":122278.56295875271,"upper_bound":128247.22441722453,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"EXACT/exact_decrypt/eql_hash/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_decrypt_eql_hash_10000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[93810958.0,184796292.0,283423000.0,368956291.0,470207875.0,576314667.0,684290083.0,759972708.0,851832583.0,970503291.0],"unit":"ns","throughput":[],"typical":{"estimate":23921924.34090909,"lower_bound":23618298.08371936,"upper_bound":24161414.285509683,"unit":"ns"},"mean":{"estimate":23686680.952599205,"lower_bound":23427249.326850694,"upper_bound":23954979.573730163,"unit":"ns"},"median":{"estimate":23640299.763888888,"lower_bound":23304965.125,"upper_bound":24013111.125,"unit":"ns"},"median_abs_dev":{"estimate":415403.47823761404,"lower_bound":96786.9370441893,"upper_bound":831215.8503408842,"unit":"ns"},"slope":{"estimate":23921924.34090909,"lower_bound":23618298.08371936,"upper_bound":24161414.285509683,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"EXACT","benchmarks":["EXACT/exact/eql_cast/10000","EXACT/exact_decrypt/eql_cast/10000","EXACT/exact/eql_hash/10000","EXACT/exact_decrypt/eql_hash/10000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT"} diff --git a/results/query/v3/exact_rows_100000.json b/results/query/v3/exact_rows_100000.json new file mode 100644 index 0000000..6058254 --- /dev/null +++ b/results/query/v3/exact_rows_100000.json @@ -0,0 +1,5 @@ +{"reason":"benchmark-complete","id":"EXACT/exact/eql_cast/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_eql_cast_100000","iteration_count":[793,1586,2379,3172,3965,4758,5551,6344,7137,7930],"measured_values":[140676209.0,176585417.0,274587542.0,353537791.0,490469083.0,502295666.0,673618625.0,742037833.0,785200250.0,904863833.0],"unit":"ns","throughput":[],"typical":{"estimate":114524.6683251175,"lower_bound":111165.4557059784,"upper_bound":118499.57610368256,"unit":"ns"},"mean":{"estimate":120732.55026987128,"lower_bound":112009.05336766147,"upper_bound":134465.63604455654,"unit":"ns"},"median":{"estimate":114763.9117065994,"lower_bound":110737.02394213254,"upper_bound":121350.8602053684,"unit":"ns"},"median_abs_dev":{"estimate":6056.021959453429,"lower_bound":1151.412545468392,"upper_bound":13248.11442138155,"unit":"ns"},"slope":{"estimate":114524.6683251175,"lower_bound":111165.4557059784,"upper_bound":118499.57610368256,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"EXACT/exact_decrypt/eql_cast/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_decrypt_eql_cast_100000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[103219583.0,191540792.0,290783791.0,397020375.0,481413958.0,595602458.0,680577709.0,794917667.0,873433875.0,971828083.0],"unit":"ns","throughput":[],"typical":{"estimate":24435058.17012987,"lower_bound":24270864.585757896,"upper_bound":24667835.980964467,"unit":"ns"},"mean":{"estimate":24538599.575625,"lower_bound":24249202.397359375,"upper_bound":24888765.132104166,"unit":"ns"},"median":{"estimate":24301024.4125,"lower_bound":24166374.991666667,"upper_bound":24827475.265625,"unit":"ns"},"median_abs_dev":{"estimate":436441.7942541126,"lower_bound":22290.519954264164,"upper_bound":840517.0673997123,"unit":"ns"},"slope":{"estimate":24435058.17012987,"lower_bound":24270864.585757896,"upper_bound":24667835.980964467,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"EXACT/exact/eql_hash/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_eql_hash_100000","iteration_count":[650,1300,1950,2600,3250,3900,4550,5200,5850,6500],"measured_values":[68875917.0,143666041.0,290703667.0,297835292.0,372540708.0,490550917.0,725833375.0,764395833.0,690867375.0,708284000.0],"unit":"ns","throughput":[],"typical":{"estimate":126762.500995005,"lower_bound":114253.2467077954,"upper_bound":143463.52825641027,"unit":"ns"},"mean":{"estimate":125410.30977454214,"lower_bound":114813.19588626832,"upper_bound":137291.405896337,"unit":"ns"},"median":{"estimate":116362.44866666666,"lower_bound":110512.33923076923,"upper_bound":146999.19865384616,"unit":"ns"},"median_abs_dev":{"estimate":12465.34266384977,"lower_bound":2627.872718884387,"upper_bound":30709.709647101372,"unit":"ns"},"slope":{"estimate":126762.500995005,"lower_bound":114253.2467077954,"upper_bound":143463.52825641027,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"EXACT/exact_decrypt/eql_hash/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_decrypt_eql_hash_100000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[101536083.0,187722334.0,297972500.0,393831459.0,482459917.0,601223792.0,675190125.0,795230208.0,890121958.0,981500750.0],"unit":"ns","throughput":[],"typical":{"estimate":24597496.15909091,"lower_bound":24366200.91831683,"upper_bound":24787458.84446254,"unit":"ns"},"mean":{"estimate":24569681.326765876,"lower_bound":24235941.185892858,"upper_bound":24876029.592638887,"unit":"ns"},"median":{"estimate":24670038.065972224,"lower_bound":24122995.85,"upper_bound":24941016.5,"unit":"ns"},"median_abs_dev":{"estimate":416506.21859511646,"lower_bound":92910.13373384904,"upper_bound":934273.8609549897,"unit":"ns"},"slope":{"estimate":24597496.15909091,"lower_bound":24366200.91831683,"upper_bound":24787458.84446254,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"EXACT","benchmarks":["EXACT/exact/eql_cast/100000","EXACT/exact_decrypt/eql_cast/100000","EXACT/exact/eql_hash/100000","EXACT/exact_decrypt/eql_hash/100000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT"} diff --git a/results/query/v3/exact_rows_1000000.json b/results/query/v3/exact_rows_1000000.json new file mode 100644 index 0000000..c41ebb4 --- /dev/null +++ b/results/query/v3/exact_rows_1000000.json @@ -0,0 +1,5 @@ +{"reason":"benchmark-complete","id":"EXACT/exact/eql_cast/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_eql_cast_1000000","iteration_count":[738,1476,2214,2952,3690,4428,5166,5904,6642,7380],"measured_values":[86006958.0,172544000.0,258658167.0,378059208.0,462834625.0,604864375.0,586312875.0,726472000.0,869085416.0,923992458.0],"unit":"ns","throughput":[],"typical":{"estimate":125436.68431703797,"lower_bound":120381.27287476823,"upper_bound":129794.04386951769,"unit":"ns"},"mean":{"estimate":123295.80993655096,"lower_bound":119059.75920634919,"upper_bound":127720.29702009397,"unit":"ns"},"median":{"estimate":124124.82777777778,"lower_bound":116720.16124661246,"upper_bound":128138.1918849744,"unit":"ns"},"median_abs_dev":{"estimate":10339.07185510783,"lower_bound":319.07339392881715,"upper_bound":12863.326739155134,"unit":"ns"},"slope":{"estimate":125436.68431703797,"lower_bound":120381.27287476823,"upper_bound":129794.04386951769,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"EXACT/exact_decrypt/eql_cast/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_decrypt_eql_cast_1000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[97808125.0,188816083.0,309357000.0,405855083.0,465284250.0,593091417.0,660648084.0,770651916.0,848290875.0,966931750.0],"unit":"ns","throughput":[],"typical":{"estimate":24029603.02987013,"lower_bound":23723498.578868765,"upper_bound":24418935.491681345,"unit":"ns"},"mean":{"estimate":24259046.51577381,"lower_bound":23801208.727380954,"upper_bound":24771075.25625,"unit":"ns"},"median":{"estimate":24128083.0625,"lower_bound":23582822.895833336,"upper_bound":24908986.96875,"unit":"ns"},"median_abs_dev":{"estimate":813914.9757376193,"lower_bound":45870.178235640495,"upper_bound":1336050.3561491137,"unit":"ns"},"slope":{"estimate":24029603.02987013,"lower_bound":23723498.578868765,"upper_bound":24418935.491681345,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"EXACT/exact/eql_hash/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_eql_hash_1000000","iteration_count":[742,1484,2226,2968,3710,4452,5194,5936,6678,7420],"measured_values":[87150833.0,171038667.0,260407667.0,385315833.0,458920833.0,602255708.0,618690542.0,726540583.0,816815250.0,904674834.0],"unit":"ns","throughput":[],"typical":{"estimate":123222.93891903244,"lower_bound":121098.08840616545,"upper_bound":126980.11403024496,"unit":"ns"},"mean":{"estimate":122424.321801598,"lower_bound":119100.79223389167,"upper_bound":126286.97350628933,"unit":"ns"},"median":{"estimate":122119.09258760107,"lower_bound":117453.95283018867,"upper_bound":126109.52232142858,"unit":"ns"},"median_abs_dev":{"estimate":5684.169668250233,"lower_bound":349.7591957009188,"upper_bound":9886.963492584518,"unit":"ns"},"slope":{"estimate":123222.93891903244,"lower_bound":121098.08840616545,"upper_bound":126980.11403024496,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"EXACT/exact_decrypt/eql_hash/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_decrypt_eql_hash_1000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[97613542.0,185823167.0,282576458.0,391444709.0,479235334.0,590282208.0,674141709.0,770621083.0,863685459.0,995227458.0],"unit":"ns","throughput":[],"typical":{"estimate":24305222.3,"lower_bound":24003153.214808702,"upper_bound":24624880.185677398,"unit":"ns"},"mean":{"estimate":24123182.020505954,"lower_bound":23826175.783541664,"upper_bound":24406714.495828126,"unit":"ns"},"median":{"estimate":24079199.22544643,"lower_bound":23769650.458333336,"upper_bound":24499238.75,"unit":"ns"},"median_abs_dev":{"estimate":526531.5640115703,"lower_bound":67195.94810390845,"upper_bound":820883.6275976502,"unit":"ns"},"slope":{"estimate":24305222.3,"lower_bound":24003153.214808702,"upper_bound":24624880.185677398,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"EXACT","benchmarks":["EXACT/exact/eql_cast/1000000","EXACT/exact_decrypt/eql_cast/1000000","EXACT/exact/eql_hash/1000000","EXACT/exact_decrypt/eql_hash/1000000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT"} diff --git a/results/query/v3/exact_rows_10000000.json b/results/query/v3/exact_rows_10000000.json new file mode 100644 index 0000000..e94952b --- /dev/null +++ b/results/query/v3/exact_rows_10000000.json @@ -0,0 +1,5 @@ +{"reason":"benchmark-complete","id":"EXACT/exact/eql_cast/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_eql_cast_10000000","iteration_count":[711,1422,2133,2844,3555,4266,4977,5688,6399,7110],"measured_values":[163209709.0,179007958.0,238096583.0,321267875.0,506729291.0,530555292.0,648498125.0,1013186750.0,794465666.0,904842958.0],"unit":"ns","throughput":[],"typical":{"estimate":135463.7387619413,"lower_bound":124407.14542815318,"upper_bound":154094.16029833697,"unit":"ns"},"mean":{"estimate":140677.5128468734,"lower_bound":122747.92317024982,"upper_bound":164682.96794839037,"unit":"ns"},"median":{"estimate":126574.0329113924,"lower_bound":118754.92733239569,"upper_bound":154213.03307715492,"unit":"ns"},"median_abs_dev":{"estimate":12850.8893683701,"lower_bound":1282.4344964540003,"upper_bound":43850.11384677913,"unit":"ns"},"slope":{"estimate":135463.7387619413,"lower_bound":124407.14542815318,"upper_bound":154094.16029833697,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"EXACT/exact_decrypt/eql_cast/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_decrypt_eql_cast_10000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[98620625.0,204351209.0,295282208.0,397207250.0,493417958.0,579350417.0,697105000.0,797292208.0,895338209.0,989474084.0],"unit":"ns","throughput":[],"typical":{"estimate":24763667.755844157,"lower_bound":24578354.696650125,"upper_bound":24883135.36048387,"unit":"ns"},"mean":{"estimate":24786120.63234127,"lower_bound":24587720.755799606,"upper_bound":25001653.429150794,"unit":"ns"},"median":{"estimate":24781152.6125,"lower_bound":24638874.28333333,"upper_bound":24896607.14285714,"unit":"ns"},"median_abs_dev":{"estimate":178987.5436973351,"lower_bound":33397.55150290858,"upper_bound":561168.8599497613,"unit":"ns"},"slope":{"estimate":24763667.755844157,"lower_bound":24578354.696650125,"upper_bound":24883135.36048387,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"EXACT/exact/eql_hash/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_eql_hash_10000000","iteration_count":[746,1492,2238,2984,3730,4476,5222,5968,6714,7460],"measured_values":[90302417.0,185707375.0,271017583.0,369883833.0,462613917.0,549983916.0,595102291.0,739702500.0,816552667.0,915752792.0],"unit":"ns","throughput":[],"typical":{"estimate":121712.74081334216,"lower_bound":118954.23452839802,"upper_bound":123445.13497109938,"unit":"ns"},"mean":{"estimate":121975.04092418826,"lower_bound":119920.0540795353,"upper_bound":123447.40460493,"unit":"ns"},"median":{"estimate":122814.52091152815,"lower_bound":121098.11572832886,"upper_bound":123984.98384718498,"unit":"ns"},"median_abs_dev":{"estimate":1783.4021075518726,"lower_bound":67.68749564147107,"upper_bound":3463.806941610581,"unit":"ns"},"slope":{"estimate":121712.74081334216,"lower_bound":118954.23452839802,"upper_bound":123445.13497109938,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"EXACT/exact_decrypt/eql_hash/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT/exact_decrypt_eql_hash_10000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[107821167.0,191258833.0,294428166.0,406420916.0,488482292.0,593782959.0,704564458.0,800481708.0,890420334.0,997064125.0],"unit":"ns","throughput":[],"typical":{"estimate":24886133.334415585,"lower_bound":24729835.967281878,"upper_bound":25026205.4775,"unit":"ns"},"mean":{"estimate":24980327.587380953,"lower_bound":24566586.304809522,"upper_bound":25503690.316312496,"unit":"ns"},"median":{"estimate":24833779.875,"lower_bound":24535680.5,"upper_bound":25208180.3125,"unit":"ns"},"median_abs_dev":{"estimate":465044.06264381827,"lower_bound":142852.18307636585,"upper_bound":1012791.9254893495,"unit":"ns"},"slope":{"estimate":24886133.334415585,"lower_bound":24729835.967281878,"upper_bound":25026205.4775,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"EXACT","benchmarks":["EXACT/exact/eql_cast/10000000","EXACT/exact_decrypt/eql_cast/10000000","EXACT/exact/eql_hash/10000000","EXACT/exact_decrypt/eql_hash/10000000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/EXACT"} diff --git a/results/query/v3/group_by_metadata_10000.json b/results/query/v3/group_by_metadata_10000.json new file mode 100644 index 0000000..b5abd6c --- /dev/null +++ b/results/query/v3/group_by_metadata_10000.json @@ -0,0 +1,247 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((category_encrypted_v3_10000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 36, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_v3_10000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 32, + "Relation Name": "category_encrypted_v3_10000", + "Startup Cost": 0.0, + "Total Cost": 542.0 + } + ], + "Startup Cost": 567.0, + "Strategy": "Hashed", + "Total Cost": 570.12 + } + ], + "Startup Cost": 573.25, + "Strategy": "Plain", + "Total Cost": 573.26 + } + } + ], + "id": "GROUP_BY/group_by/low_cardinality_groups_encrypted/10000", + "indexes_used": [], + "parameters": [], + "query": "SELECT count(*) FROM (SELECT 1 FROM category_encrypted_v3_10000 GROUP BY eql_v3.eq_term(value)) g", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "category_plaintext_10000.value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 12, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_10000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 8, + "Relation Name": "category_plaintext_10000", + "Startup Cost": 0.0, + "Total Cost": 155.0 + } + ], + "Startup Cost": 180.0, + "Strategy": "Hashed", + "Total Cost": 182.5 + } + ], + "Startup Cost": 185.62, + "Strategy": "Plain", + "Total Cost": 185.63 + } + } + ], + "id": "GROUP_BY/group_by/low_cardinality_groups_plaintext/10000", + "indexes_used": [], + "parameters": [], + "query": "SELECT count(*) FROM (SELECT 1 FROM category_plaintext_10000 GROUP BY value) g", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 40, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_v3_10000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 32, + "Relation Name": "category_encrypted_v3_10000", + "Startup Cost": 0.0, + "Total Cost": 542.0 + } + ], + "Startup Cost": 592.0, + "Strategy": "Hashed", + "Total Cost": 595.12 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 600.53, + "Total Cost": 601.15 + } + ], + "Startup Cost": 600.53, + "Total Cost": 600.55 + } + } + ], + "id": "GROUP_BY/group_by/top_n_groups_encrypted/10000", + "indexes_used": [], + "parameters": [], + "query": "SELECT eql_v3.eq_term(value), count(*) FROM category_encrypted_v3_10000 GROUP BY 1 ORDER BY count(*) DESC LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 16, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_10000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 8, + "Relation Name": "category_plaintext_10000", + "Startup Cost": 0.0, + "Total Cost": 155.0 + } + ], + "Startup Cost": 205.0, + "Strategy": "Hashed", + "Total Cost": 207.5 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 212.9, + "Total Cost": 213.53 + } + ], + "Startup Cost": 212.9, + "Total Cost": 212.93 + } + } + ], + "id": "GROUP_BY/group_by/top_n_groups_plaintext/10000", + "indexes_used": [], + "parameters": [], + "query": "SELECT value, count(*) FROM category_plaintext_10000 GROUP BY 1 ORDER BY count(*) DESC LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "10000" +} \ No newline at end of file diff --git a/results/query/v3/group_by_metadata_100000.json b/results/query/v3/group_by_metadata_100000.json new file mode 100644 index 0000000..33fc934 --- /dev/null +++ b/results/query/v3/group_by_metadata_100000.json @@ -0,0 +1,247 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((category_encrypted_v3_100000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 36, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_v3_100000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 32, + "Relation Name": "category_encrypted_v3_100000", + "Startup Cost": 0.0, + "Total Cost": 5417.0 + } + ], + "Startup Cost": 5667.0, + "Strategy": "Hashed", + "Total Cost": 5670.12 + } + ], + "Startup Cost": 5673.25, + "Strategy": "Plain", + "Total Cost": 5673.26 + } + } + ], + "id": "GROUP_BY/group_by/low_cardinality_groups_encrypted/100000", + "indexes_used": [], + "parameters": [], + "query": "SELECT count(*) FROM (SELECT 1 FROM category_encrypted_v3_100000 GROUP BY eql_v3.eq_term(value)) g", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "category_plaintext_100000.value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 12, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_100000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 8, + "Relation Name": "category_plaintext_100000", + "Startup Cost": 0.0, + "Total Cost": 1541.0 + } + ], + "Startup Cost": 1791.0, + "Strategy": "Hashed", + "Total Cost": 1793.5 + } + ], + "Startup Cost": 1796.62, + "Strategy": "Plain", + "Total Cost": 1796.63 + } + } + ], + "id": "GROUP_BY/group_by/low_cardinality_groups_plaintext/100000", + "indexes_used": [], + "parameters": [], + "query": "SELECT count(*) FROM (SELECT 1 FROM category_plaintext_100000 GROUP BY value) g", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 40, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_v3_100000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 32, + "Relation Name": "category_encrypted_v3_100000", + "Startup Cost": 0.0, + "Total Cost": 5417.0 + } + ], + "Startup Cost": 5917.0, + "Strategy": "Hashed", + "Total Cost": 5920.12 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 5925.53, + "Total Cost": 5926.15 + } + ], + "Startup Cost": 5925.53, + "Total Cost": 5925.55 + } + } + ], + "id": "GROUP_BY/group_by/top_n_groups_encrypted/100000", + "indexes_used": [], + "parameters": [], + "query": "SELECT eql_v3.eq_term(value), count(*) FROM category_encrypted_v3_100000 GROUP BY 1 ORDER BY count(*) DESC LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Simple", + "Plan Rows": 250, + "Plan Width": 16, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_100000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 8, + "Relation Name": "category_plaintext_100000", + "Startup Cost": 0.0, + "Total Cost": 1541.0 + } + ], + "Startup Cost": 2041.0, + "Strategy": "Hashed", + "Total Cost": 2043.5 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 2048.9, + "Total Cost": 2049.53 + } + ], + "Startup Cost": 2048.9, + "Total Cost": 2048.93 + } + } + ], + "id": "GROUP_BY/group_by/top_n_groups_plaintext/100000", + "indexes_used": [], + "parameters": [], + "query": "SELECT value, count(*) FROM category_plaintext_100000 GROUP BY 1 ORDER BY count(*) DESC LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "100000" +} \ No newline at end of file diff --git a/results/query/v3/group_by_metadata_1000000.json b/results/query/v3/group_by_metadata_1000000.json new file mode 100644 index 0000000..a093613 --- /dev/null +++ b/results/query/v3/group_by_metadata_1000000.json @@ -0,0 +1,423 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((category_encrypted_v3_1000000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Node Type": "Group", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((category_encrypted_v3_1000000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 32, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_v3_1000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 416665, + "Plan Width": 32, + "Relation Name": "category_encrypted_v3_1000000", + "Startup Cost": 0.0, + "Total Cost": 46875.32 + } + ], + "Startup Cost": 47916.98, + "Strategy": "Hashed", + "Total Cost": 47920.1 + } + ], + "Sort Key": [ + "((((category_encrypted_v3_1000000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Startup Cost": 47930.06, + "Total Cost": 47930.69 + } + ], + "Startup Cost": 48930.09, + "Total Cost": 48988.42, + "Workers Planned": 2 + } + ], + "Startup Cost": 48930.09, + "Total Cost": 48990.3 + } + ], + "Startup Cost": 48993.42, + "Strategy": "Plain", + "Total Cost": 48993.43 + } + } + ], + "id": "GROUP_BY/group_by/low_cardinality_groups_encrypted/1000000", + "indexes_used": [], + "parameters": [], + "query": "SELECT count(*) FROM (SELECT 1 FROM category_encrypted_v3_1000000 GROUP BY eql_v3.eq_term(value)) g", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "category_plaintext_1000000.value" + ], + "Node Type": "Group", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 12, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "category_plaintext_1000000.value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 8, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_1000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 416667, + "Plan Width": 8, + "Relation Name": "category_plaintext_1000000", + "Startup Cost": 0.0, + "Total Cost": 9572.67 + } + ], + "Startup Cost": 10614.33, + "Strategy": "Hashed", + "Total Cost": 10616.83 + } + ], + "Sort Key": [ + "category_plaintext_1000000.value" + ], + "Startup Cost": 10626.79, + "Total Cost": 10627.42 + } + ], + "Startup Cost": 11626.82, + "Total Cost": 11685.15, + "Workers Planned": 2 + } + ], + "Startup Cost": 11626.82, + "Total Cost": 11686.4 + } + ], + "Startup Cost": 11689.53, + "Strategy": "Plain", + "Total Cost": 11689.54 + } + } + ], + "id": "GROUP_BY/group_by/low_cardinality_groups_plaintext/1000000", + "indexes_used": [], + "parameters": [], + "query": "SELECT count(*) FROM (SELECT 1 FROM category_plaintext_1000000 GROUP BY value) g", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Finalize", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 40, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_v3_1000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 416665, + "Plan Width": 32, + "Relation Name": "category_encrypted_v3_1000000", + "Startup Cost": 0.0, + "Total Cost": 46875.32 + } + ], + "Startup Cost": 48958.64, + "Strategy": "Hashed", + "Total Cost": 48961.77 + } + ], + "Sort Key": [ + "((((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Startup Cost": 48971.72, + "Total Cost": 48972.35 + } + ], + "Startup Cost": 49971.75, + "Total Cost": 50030.09, + "Workers Planned": 2 + } + ], + "Startup Cost": 49971.75, + "Strategy": "Sorted", + "Total Cost": 50035.71 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 50041.11, + "Total Cost": 50041.74 + } + ], + "Startup Cost": 50041.11, + "Total Cost": 50041.14 + } + } + ], + "id": "GROUP_BY/group_by/top_n_groups_encrypted/1000000", + "indexes_used": [], + "parameters": [], + "query": "SELECT eql_v3.eq_term(value), count(*) FROM category_encrypted_v3_1000000 GROUP BY 1 ORDER BY count(*) DESC LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Finalize", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 16, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_1000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 416667, + "Plan Width": 8, + "Relation Name": "category_plaintext_1000000", + "Startup Cost": 0.0, + "Total Cost": 9572.67 + } + ], + "Startup Cost": 11656.0, + "Strategy": "Hashed", + "Total Cost": 11658.5 + } + ], + "Sort Key": [ + "value" + ], + "Startup Cost": 11668.46, + "Total Cost": 11669.08 + } + ], + "Startup Cost": 12668.48, + "Total Cost": 12726.82, + "Workers Planned": 2 + } + ], + "Startup Cost": 12668.48, + "Strategy": "Sorted", + "Total Cost": 12731.82 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 12737.22, + "Total Cost": 12737.85 + } + ], + "Startup Cost": 12737.22, + "Total Cost": 12737.25 + } + } + ], + "id": "GROUP_BY/group_by/top_n_groups_plaintext/1000000", + "indexes_used": [], + "parameters": [], + "query": "SELECT value, count(*) FROM category_plaintext_1000000 GROUP BY 1 ORDER BY count(*) DESC LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "1000000" +} \ No newline at end of file diff --git a/results/query/v3/group_by_metadata_10000000.json b/results/query/v3/group_by_metadata_10000000.json new file mode 100644 index 0000000..18052ac --- /dev/null +++ b/results/query/v3/group_by_metadata_10000000.json @@ -0,0 +1,423 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((category_encrypted_v3_10000000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Node Type": "Group", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 36, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 32, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((category_encrypted_v3_10000000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 32, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_v3_10000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 4166670, + "Plan Width": 32, + "Relation Name": "category_encrypted_v3_10000000", + "Startup Cost": 0.0, + "Total Cost": 468750.38 + } + ], + "Startup Cost": 479167.05, + "Strategy": "Hashed", + "Total Cost": 479170.17 + } + ], + "Sort Key": [ + "((((category_encrypted_v3_10000000.value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Startup Cost": 479180.13, + "Total Cost": 479180.76 + } + ], + "Startup Cost": 480180.16, + "Total Cost": 480238.49, + "Workers Planned": 2 + } + ], + "Startup Cost": 480180.16, + "Total Cost": 480240.37 + } + ], + "Startup Cost": 480243.49, + "Strategy": "Plain", + "Total Cost": 480243.5 + } + } + ], + "id": "GROUP_BY/group_by/low_cardinality_groups_encrypted/10000000", + "indexes_used": [], + "parameters": [], + "query": "SELECT count(*) FROM (SELECT 1 FROM category_encrypted_v3_10000000 GROUP BY eql_v3.eq_term(value)) g", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Aggregate", + "Parallel Aware": false, + "Partial Mode": "Simple", + "Plan Rows": 1, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "category_plaintext_10000000.value" + ], + "Node Type": "Group", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 12, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 8, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "category_plaintext_10000000.value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 8, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_10000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 4166608, + "Plan Width": 8, + "Relation Name": "category_plaintext_10000000", + "Startup Cost": 0.0, + "Total Cost": 95721.08 + } + ], + "Startup Cost": 106137.6, + "Strategy": "Hashed", + "Total Cost": 106140.1 + } + ], + "Sort Key": [ + "category_plaintext_10000000.value" + ], + "Startup Cost": 106150.06, + "Total Cost": 106150.69 + } + ], + "Startup Cost": 107150.08, + "Total Cost": 107208.42, + "Workers Planned": 2 + } + ], + "Startup Cost": 107150.08, + "Total Cost": 107209.67 + } + ], + "Startup Cost": 107212.8, + "Strategy": "Plain", + "Total Cost": 107212.81 + } + } + ], + "id": "GROUP_BY/group_by/low_cardinality_groups_plaintext/10000000", + "indexes_used": [], + "parameters": [], + "query": "SELECT count(*) FROM (SELECT 1 FROM category_plaintext_10000000 GROUP BY value) g", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "((((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Finalize", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 40, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "(((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 40, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_encrypted_v3_10000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 4166670, + "Plan Width": 32, + "Relation Name": "category_encrypted_v3_10000000", + "Startup Cost": 0.0, + "Total Cost": 468750.38 + } + ], + "Startup Cost": 489583.72, + "Strategy": "Hashed", + "Total Cost": 489586.85 + } + ], + "Sort Key": [ + "((((value)::jsonb ->> 'hm'::text))::eql_v3_internal.hmac_256)" + ], + "Startup Cost": 489596.81, + "Total Cost": 489597.43 + } + ], + "Startup Cost": 490596.83, + "Total Cost": 490655.17, + "Workers Planned": 2 + } + ], + "Startup Cost": 490596.83, + "Strategy": "Sorted", + "Total Cost": 490660.79 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 490666.2, + "Total Cost": 490666.82 + } + ], + "Startup Cost": 490666.2, + "Total Cost": 490666.22 + } + } + ], + "id": "GROUP_BY/group_by/top_n_groups_encrypted/10000000", + "indexes_used": [], + "parameters": [], + "query": "SELECT eql_v3.eq_term(value), count(*) FROM category_encrypted_v3_10000000 GROUP BY 1 ORDER BY count(*) DESC LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Finalize", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Gather Merge", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Node Type": "Sort", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 250, + "Plan Width": 16, + "Plans": [ + { + "Async Capable": false, + "Group Key": [ + "value" + ], + "Node Type": "Aggregate", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Partial Mode": "Partial", + "Plan Rows": 250, + "Plan Width": 16, + "Planned Partitions": 0, + "Plans": [ + { + "Alias": "category_plaintext_10000000", + "Async Capable": false, + "Node Type": "Seq Scan", + "Parallel Aware": true, + "Parent Relationship": "Outer", + "Plan Rows": 4166608, + "Plan Width": 8, + "Relation Name": "category_plaintext_10000000", + "Startup Cost": 0.0, + "Total Cost": 95721.08 + } + ], + "Startup Cost": 116554.12, + "Strategy": "Hashed", + "Total Cost": 116556.62 + } + ], + "Sort Key": [ + "value" + ], + "Startup Cost": 116566.58, + "Total Cost": 116567.21 + } + ], + "Startup Cost": 117566.6, + "Total Cost": 117624.94, + "Workers Planned": 2 + } + ], + "Startup Cost": 117566.6, + "Strategy": "Sorted", + "Total Cost": 117629.94 + } + ], + "Sort Key": [ + "(count(*)) DESC" + ], + "Startup Cost": 117635.34, + "Total Cost": 117635.97 + } + ], + "Startup Cost": 117635.34, + "Total Cost": 117635.37 + } + } + ], + "id": "GROUP_BY/group_by/top_n_groups_plaintext/10000000", + "indexes_used": [], + "parameters": [], + "query": "SELECT value, count(*) FROM category_plaintext_10000000 GROUP BY 1 ORDER BY count(*) DESC LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "10000000" +} \ No newline at end of file diff --git a/results/query/v3/group_by_rows_10000.json b/results/query/v3/group_by_rows_10000.json new file mode 100644 index 0000000..66d7152 --- /dev/null +++ b/results/query/v3/group_by_rows_10000.json @@ -0,0 +1,5 @@ +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/low_cardinality_groups_encrypted/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_low_cardinality_groups_encrypted_10000","iteration_count":[42,84,126,168,210,252,294,336,378,420],"measured_values":[120433917.0,183466291.0,254496667.0,346510791.0,449476875.0,504681417.0,627470166.0,678029833.0,796443750.0,891569000.0],"unit":"ns","throughput":[],"typical":{"estimate":2091069.0239332097,"lower_bound":2047157.6926308984,"upper_bound":2123628.5285714287,"unit":"ns"},"mean":{"estimate":2165902.1460742624,"lower_bound":2059320.815728458,"upper_bound":2334204.8437510626,"unit":"ns"},"median":{"estimate":2114888.6904761903,"lower_bound":2019814.8174603174,"upper_bound":2159187.3886054424,"unit":"ns"},"median_abs_dev":{"estimate":90111.15118770751,"lower_bound":13034.083518598596,"upper_bound":162548.4431460342,"unit":"ns"},"slope":{"estimate":2091069.0239332097,"lower_bound":2047157.6926308984,"upper_bound":2123628.5285714287,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/low_cardinality_groups_plaintext/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_low_cardinality_groups_plaintext_10000","iteration_count":[75,150,225,300,375,450,525,600,675,750],"measured_values":[88172917.0,175433666.0,291799250.0,348314458.0,432869041.0,575446958.0,710351166.0,697279709.0,809688500.0,889584167.0],"unit":"ns","throughput":[],"typical":{"estimate":1214145.6896277056,"lower_bound":1177959.4504582211,"upper_bound":1272169.6280067002,"unit":"ns"},"mean":{"estimate":1213705.2305518517,"lower_bound":1176311.3126444444,"upper_bound":1257301.9903851852,"unit":"ns"},"median":{"estimate":1180875.558,"lower_bound":1162132.8483333334,"upper_bound":1278771.0177777777,"unit":"ns"},"median_abs_dev":{"estimate":28591.995595690492,"lower_bound":6308.151542008151,"upper_bound":109492.65422256089,"unit":"ns"},"slope":{"estimate":1214145.6896277056,"lower_bound":1177959.4504582211,"upper_bound":1272169.6280067002,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/top_n_groups_encrypted/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_top_n_groups_encrypted_10000","iteration_count":[44,88,132,176,220,264,308,352,396,440],"measured_values":[89946584.0,178321208.0,314795167.0,358090084.0,445536625.0,571865958.0,650312333.0,715749083.0,844893125.0,923567625.0],"unit":"ns","throughput":[],"typical":{"estimate":2101541.149940968,"lower_bound":2064456.405834239,"upper_bound":2138227.0593069056,"unit":"ns"},"mean":{"estimate":2105872.5521690114,"lower_bound":2052095.8761273448,"upper_bound":2179030.0258522728,"unit":"ns"},"median":{"estimate":2071628.9375,"lower_bound":2030490.0568181816,"upper_bound":2138781.3051948054,"unit":"ns"},"median_abs_dev":{"estimate":63030.006142357466,"lower_bound":6097.478803112,"upper_bound":134206.42192152631,"unit":"ns"},"slope":{"estimate":2101541.149940968,"lower_bound":2064456.405834239,"upper_bound":2138227.0593069056,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/top_n_groups_plaintext/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_top_n_groups_plaintext_10000","iteration_count":[72,144,216,288,360,432,504,576,648,720],"measured_values":[84012292.0,173206333.0,291914125.0,344203292.0,432900083.0,553504125.0,633790958.0,686050583.0,813901083.0,912475375.0],"unit":"ns","throughput":[],"typical":{"estimate":1246151.1736291486,"lower_bound":1216709.0807761734,"upper_bound":1266382.8551133333,"unit":"ns"},"mean":{"estimate":1237195.2408382937,"lower_bound":1206270.000119337,"upper_bound":1271540.1434589948,"unit":"ns"},"median":{"estimate":1229420.9733796297,"lower_bound":1195150.3194444445,"upper_bound":1269390.6453373015,"unit":"ns"},"median_abs_dev":{"estimate":53504.505423021794,"lower_bound":5686.83651778847,"upper_bound":99740.44018967,"unit":"ns"},"slope":{"estimate":1246151.1736291486,"lower_bound":1216709.0807761734,"upper_bound":1266382.8551133333,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"GROUP_BY","benchmarks":["GROUP_BY/group_by/low_cardinality_groups_encrypted/10000","GROUP_BY/group_by/low_cardinality_groups_plaintext/10000","GROUP_BY/group_by/top_n_groups_encrypted/10000","GROUP_BY/group_by/top_n_groups_plaintext/10000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY"} diff --git a/results/query/v3/group_by_rows_100000.json b/results/query/v3/group_by_rows_100000.json new file mode 100644 index 0000000..4146cfe --- /dev/null +++ b/results/query/v3/group_by_rows_100000.json @@ -0,0 +1,5 @@ +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/low_cardinality_groups_encrypted/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_low_cardinality_groups_encrypted_100000","iteration_count":[5,10,15,20,25,30,35,40,45,50],"measured_values":[92556834.0,181240292.0,276326792.0,412965542.0,481453916.0,598904416.0,637723750.0,859698667.0,874350292.0,953480375.0],"unit":"ns","throughput":[],"typical":{"estimate":19575162.59844156,"lower_bound":18897018.926865652,"upper_bound":20472409.41860247,"unit":"ns"},"mean":{"estimate":19313985.564198412,"lower_bound":18708101.676984128,"upper_bound":19997800.832384724,"unit":"ns"},"median":{"estimate":19163882.07,"lower_bound":18366022.685714286,"upper_bound":20039141.794444446,"unit":"ns"},"median_abs_dev":{"estimate":1142858.0384302156,"lower_bound":215487.18001434152,"upper_bound":1799578.757281092,"unit":"ns"},"slope":{"estimate":19575162.59844156,"lower_bound":18897018.926865652,"upper_bound":20472409.41860247,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/low_cardinality_groups_plaintext/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_low_cardinality_groups_plaintext_100000","iteration_count":[10,20,30,40,50,60,70,80,90,100],"measured_values":[95878666.0,188311375.0,282403458.0,390378375.0,471133958.0,584696167.0,665637833.0,780351667.0,859890125.0,982266917.0],"unit":"ns","throughput":[],"typical":{"estimate":9664683.258181818,"lower_bound":9539881.66938076,"upper_bound":9762445.0670553,"unit":"ns"},"mean":{"estimate":9598447.02313889,"lower_bound":9504551.779620832,"upper_bound":9691860.228943055,"unit":"ns"},"median":{"estimate":9571100.66111111,"lower_bound":9422679.16,"upper_bound":9754395.8375,"unit":"ns"},"median_abs_dev":{"estimate":232163.27448661113,"lower_bound":8414.28117361731,"upper_bound":249655.16894723463,"unit":"ns"},"slope":{"estimate":9664683.258181818,"lower_bound":9539881.66938076,"upper_bound":9762445.0670553,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/top_n_groups_encrypted/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_top_n_groups_encrypted_100000","iteration_count":[5,10,15,20,25,30,35,40,45,50],"measured_values":[98293167.0,197253167.0,292410834.0,407932833.0,493177833.0,605707625.0,690589417.0,826975791.0,911656875.0,1003749375.0],"unit":"ns","throughput":[],"typical":{"estimate":20152849.933506493,"lower_bound":19904337.566153847,"upper_bound":20380634.291964285,"unit":"ns"},"mean":{"estimate":19993156.497833334,"lower_bound":19775899.151666664,"upper_bound":20223922.6895,"unit":"ns"},"median":{"estimate":19903056.85,"lower_bound":19692873.36,"upper_bound":20293447.90833333,"unit":"ns"},"median_abs_dev":{"estimate":394090.46733349765,"lower_bound":5638.416655896106,"upper_bound":666794.680327024,"unit":"ns"},"slope":{"estimate":20152849.933506493,"lower_bound":19904337.566153847,"upper_bound":20380634.291964285,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/top_n_groups_plaintext/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_top_n_groups_plaintext_100000","iteration_count":[10,20,30,40,50,60,70,80,90,100],"measured_values":[97503000.0,198022291.0,333702042.0,395322208.0,491865792.0,607616250.0,703100750.0,785222666.0,901853083.0,1023921458.0],"unit":"ns","throughput":[],"typical":{"estimate":10062428.027272727,"lower_bound":9919375.219666313,"upper_bound":10198742.01889457,"unit":"ns"},"mean":{"estimate":10074150.863468256,"lower_bound":9888986.351963095,"upper_bound":10337550.355244642,"unit":"ns"},"median":{"estimate":9960852.180555556,"lower_bound":9837315.84,"upper_bound":10141755.504285716,"unit":"ns"},"median_abs_dev":{"estimate":199487.6783355537,"lower_bound":47293.982883364624,"upper_bound":375819.76763686794,"unit":"ns"},"slope":{"estimate":10062428.027272727,"lower_bound":9919375.219666313,"upper_bound":10198742.01889457,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"GROUP_BY","benchmarks":["GROUP_BY/group_by/low_cardinality_groups_encrypted/100000","GROUP_BY/group_by/low_cardinality_groups_plaintext/100000","GROUP_BY/group_by/top_n_groups_encrypted/100000","GROUP_BY/group_by/top_n_groups_plaintext/100000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY"} diff --git a/results/query/v3/group_by_rows_1000000.json b/results/query/v3/group_by_rows_1000000.json new file mode 100644 index 0000000..40bed87 --- /dev/null +++ b/results/query/v3/group_by_rows_1000000.json @@ -0,0 +1,5 @@ +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/low_cardinality_groups_encrypted/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_low_cardinality_groups_encrypted_1000000","iteration_count":[2,4,6,8,10,12,14,16,18,20],"measured_values":[162897959.0,350963000.0,492785709.0,664890375.0,819885292.0,1005227083.0,1161848917.0,1318934834.0,1498217666.0,1672430417.0],"unit":"ns","throughput":[],"typical":{"estimate":83150929.60909091,"lower_bound":82680357.5808096,"upper_bound":83522619.5052134,"unit":"ns"},"mean":{"estimate":83246790.17682539,"lower_bound":82402299.43154761,"upper_bound":84395293.89710318,"unit":"ns"},"median":{"estimate":83050252.61607143,"lower_bound":82130951.5,"upper_bound":83621520.85,"unit":"ns"},"median_abs_dev":{"estimate":990003.5069864206,"lower_bound":181697.38639090778,"upper_bound":1870737.3696927757,"unit":"ns"},"slope":{"estimate":83150929.60909091,"lower_bound":82680357.5808096,"upper_bound":83522619.5052134,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/low_cardinality_groups_plaintext/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_low_cardinality_groups_plaintext_1000000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[108912000.0,232944250.0,328891084.0,434735167.0,573710458.0,669747875.0,765921042.0,892401292.0,1004716333.0,1112978958.0],"unit":"ns","throughput":[],"typical":{"estimate":37108526.551515155,"lower_bound":36831135.402700394,"upper_bound":37386521.21978022,"unit":"ns"},"mean":{"estimate":37132183.75473545,"lower_bound":36671495.33475066,"upper_bound":37658883.52121694,"unit":"ns"},"median":{"estimate":37141342.88333333,"lower_bound":36423726.88888889,"upper_bound":37727789.57222222,"unit":"ns"},"median_abs_dev":{"estimate":939079.874091331,"lower_bound":23595.304025542016,"upper_bound":1396979.8046069797,"unit":"ns"},"slope":{"estimate":37108526.551515155,"lower_bound":36831135.402700394,"upper_bound":37386521.21978022,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/top_n_groups_encrypted/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_top_n_groups_encrypted_1000000","iteration_count":[2,4,6,8,10,12,14,16,18,20],"measured_values":[210481083.0,339873333.0,502237542.0,688404416.0,941243666.0,1041041791.0,1195867416.0,1346154459.0,1544969375.0,1679458167.0],"unit":"ns","throughput":[],"typical":{"estimate":85639793.17402597,"lower_bound":84506457.16666667,"upper_bound":87811373.30152671,"unit":"ns"},"mean":{"estimate":88020182.8058135,"lower_bound":84870020.18509921,"upper_bound":92501464.93189731,"unit":"ns"},"median":{"estimate":85625366.5436508,"lower_bound":84134653.6875,"upper_bound":90087459.3,"unit":"ns"},"median_abs_dev":{"estimate":1941337.8260156102,"lower_bound":395337.28449135134,"upper_bound":6615498.603114744,"unit":"ns"},"slope":{"estimate":85639793.17402597,"lower_bound":84506457.16666667,"upper_bound":87811373.30152671,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/top_n_groups_plaintext/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_top_n_groups_plaintext_1000000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[113293750.0,227652625.0,359690084.0,455136792.0,588687500.0,713167000.0,820940291.0,921097500.0,1033304959.0,1164241625.0],"unit":"ns","throughput":[],"typical":{"estimate":38743011.98095238,"lower_bound":38441775.42121015,"upper_bound":39129964.007882886,"unit":"ns"},"mean":{"estimate":38701660.612433866,"lower_bound":38266803.125396825,"upper_bound":39161189.26746032,"unit":"ns"},"median":{"estimate":38593558.33333333,"lower_bound":37942104.166666664,"upper_bound":39356391.84920634,"unit":"ns"},"median_abs_dev":{"estimate":966454.414092008,"lower_bound":142002.68417894287,"upper_bound":1256511.5221702382,"unit":"ns"},"slope":{"estimate":38743011.98095238,"lower_bound":38441775.42121015,"upper_bound":39129964.007882886,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"GROUP_BY","benchmarks":["GROUP_BY/group_by/low_cardinality_groups_encrypted/1000000","GROUP_BY/group_by/low_cardinality_groups_plaintext/1000000","GROUP_BY/group_by/top_n_groups_encrypted/1000000","GROUP_BY/group_by/top_n_groups_plaintext/1000000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY"} diff --git a/results/query/v3/group_by_rows_10000000.json b/results/query/v3/group_by_rows_10000000.json new file mode 100644 index 0000000..c7501e4 --- /dev/null +++ b/results/query/v3/group_by_rows_10000000.json @@ -0,0 +1,5 @@ +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/low_cardinality_groups_encrypted/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_low_cardinality_groups_encrypted_10000000","iteration_count":[1,1,1,1,1,1,1,1,1,1],"measured_values":[847105750.0,877032916.0,889790084.0,859849917.0,870948042.0,885164084.0,939099000.0,912182958.0,1013000375.0,905755500.0],"unit":"ns","throughput":[],"typical":{"estimate":899992862.6,"lower_bound":875317667.6550001,"upper_bound":931250270.0675,"unit":"ns"},"mean":{"estimate":899992862.6,"lower_bound":875317667.6550001,"upper_bound":931250270.0675,"unit":"ns"},"median":{"estimate":887477084.0,"lower_bound":868441416.5,"upper_bound":922427250.0,"unit":"ns"},"median_abs_dev":{"estimate":31864253.611296415,"lower_bound":9456888.470506668,"upper_bound":64699488.632154465,"unit":"ns"},"slope":null,"change":null} +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/low_cardinality_groups_plaintext/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_low_cardinality_groups_plaintext_10000000","iteration_count":[2,2,2,2,2,2,2,2,2,2],"measured_values":[656074333.0,720298291.0,709534083.0,675645625.0,690621458.0,656207500.0,698656083.0,687310792.0,658019042.0,726150834.0],"unit":"ns","throughput":[],"typical":{"estimate":343925902.05,"lower_bound":336291160.35,"upper_bound":351648331.7525,"unit":"ns"},"mean":{"estimate":343925902.05,"lower_bound":336291160.35,"upper_bound":351648331.7525,"unit":"ns"},"median":{"estimate":344483062.5,"lower_bound":329009521.0,"upper_bound":354767041.5,"unit":"ns"},"median_abs_dev":{"estimate":19094049.607662857,"lower_bound":1342896.0607588291,"upper_bound":23226534.24344659,"unit":"ns"},"slope":null,"change":null} +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/top_n_groups_encrypted/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_top_n_groups_encrypted_10000000","iteration_count":[1,1,1,1,1,1,1,1,1,1],"measured_values":[874330541.0,896287667.0,929246167.0,899786792.0,905717708.0,869179792.0,887687500.0,902294958.0,1006676000.0,957771833.0],"unit":"ns","throughput":[],"typical":{"estimate":912897895.8,"lower_bound":890855035.2175,"upper_bound":939471126.88,"unit":"ns"},"mean":{"estimate":912897895.8,"lower_bound":890855035.2175,"upper_bound":939471126.88,"unit":"ns"},"median":{"estimate":901040875.0,"lower_bound":885309104.0,"upper_bound":931744770.5,"unit":"ns"},"median_abs_dev":{"estimate":29699226.954433322,"lower_bound":4396587.952744961,"upper_bound":61855028.661453724,"unit":"ns"},"slope":null,"change":null} +{"reason":"benchmark-complete","id":"GROUP_BY/group_by/top_n_groups_plaintext/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY/group_by_top_n_groups_plaintext_10000000","iteration_count":[2,2,2,2,2,2,2,2,2,2],"measured_values":[711029958.0,694200708.0,755897708.0,884883875.0,697727125.0,708312458.0,719737167.0,680191875.0,712959584.0,696736625.0],"unit":"ns","throughput":[],"typical":{"estimate":363083854.15,"lower_bound":349858250.09125,"upper_bound":382716727.05,"unit":"ns"},"mean":{"estimate":363083854.15,"lower_bound":349858250.09125,"upper_bound":382716727.05,"unit":"ns"},"median":{"estimate":354835604.0,"lower_bound":347981958.25,"upper_bound":367214323.0,"unit":"ns"},"median_abs_dev":{"estimate":9221277.389189601,"lower_bound":1430431.7284047604,"upper_bound":24073037.300518155,"unit":"ns"},"slope":null,"change":null} +{"reason":"group-complete","group_name":"GROUP_BY","benchmarks":["GROUP_BY/group_by/low_cardinality_groups_encrypted/10000000","GROUP_BY/group_by/low_cardinality_groups_plaintext/10000000","GROUP_BY/group_by/top_n_groups_encrypted/10000000","GROUP_BY/group_by/top_n_groups_plaintext/10000000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/GROUP_BY"} diff --git a/results/query/v3/json_metadata_10000.json b/results/query/v3/json_metadata_10000.json new file mode 100644 index 0000000..87e031c --- /dev/null +++ b/results/query/v3/json_metadata_10000.json @@ -0,0 +1,256 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445b99a8145a992feffd27dbccc23403644ed2feffa7aa72ca2e78d163b006e9765c25c979709adfac3eb53f92dcfcff868232545184a5122622c6d2e57\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ae112c2089404a378b7e03856b6281edd02159fedc2e7e61244c43b14ce9d67921f590c328d1587160f9af113ae95aaf453a37514c268eb4317678bfe4365cfa8f689edce9796f5ec194f8e6a48882b07607ae6e03c16a6a3d985d5edbe516bbca6094d9b73343a57de5f0311c4e25df6eaf7c094fe5d1b97ea3696a3043f38c68c7560242188228687fbb7880bbe891b3aaa83029995d9553b71bc27d8de087dfd65eb12f1a976887c322c729\\\"}\",\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed445b99a8145a992fefe400f7a9a1f0253ffa837b76c1602d4a28ae81114\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d8b88e748150ce18ba0d1fa98dda6bf96cb47d12150661d4710365e26993420af2ccd1d836df55ccbc9bb7a6fb4f5589c09032c4bf\\\"}\"}'::jsonb[])", + "Index Name": "json_ste_vec_small_encrypted_v3_10000_jsonb_array_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 68.86 + } + ], + "Recheck Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445b99a8145a992feffd27dbccc23403644ed2feffa7aa72ca2e78d163b006e9765c25c979709adfac3eb53f92dcfcff868232545184a5122622c6d2e57\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ae112c2089404a378b7e03856b6281edd02159fedc2e7e61244c43b14ce9d67921f590c328d1587160f9af113ae95aaf453a37514c268eb4317678bfe4365cfa8f689edce9796f5ec194f8e6a48882b07607ae6e03c16a6a3d985d5edbe516bbca6094d9b73343a57de5f0311c4e25df6eaf7c094fe5d1b97ea3696a3043f38c68c7560242188228687fbb7880bbe891b3aaa83029995d9553b71bc27d8de087dfd65eb12f1a976887c322c729\\\"}\",\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed445b99a8145a992fefe400f7a9a1f0253ffa837b76c1602d4a28ae81114\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d8b88e748150ce18ba0d1fa98dda6bf96cb47d12150661d4710365e26993420af2ccd1d836df55ccbc9bb7a6fb4f5589c09032c4bf\\\"}\"}'::jsonb[])", + "Relation Name": "json_ste_vec_small_encrypted_v3_10000", + "Startup Cost": 68.86, + "Total Cost": 73.13 + } + ], + "Startup Cost": 68.86, + "Total Cost": 73.13 + } + } + ], + "id": "JSON/json/contains/functional/10000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_10000_jsonb_array_index" + ], + "parameters": [ + "{\"sv\":[{\"hm\":\"98b7664512c8c0125772e43e47dde0ce\",\"s\":\"75146c96a91ff82146e29e87b5accb95\"},{\"oc\":\"e108bb37379dfda0f0143886d8b88e748150ce18ba0d1fa98dda6bf96cb47d12150661d4710365e26993420af2ccd1d836df55ccbc9bb7a6fb4f5589c09032c4bf\",\"s\":\"1c16090f62b45fc9a1404b2135beab94\"},{\"oc\":\"e2847ed5ae112c2089404a378b7e03856b6281edd02159fedc2e7e61244c43b14ce9d67921f590c328d1587160f9af113ae95aaf453a37514c268eb4317678bfe4365cfa8f689edce9796f5ec194f8e6a48882b07607ae6e03c16a6a3d985d5edbe516bbca6094d9b73343a57de5f0311c4e25df6eaf7c094fe5d1b97ea3696a3043f38c68c7560242188228687fbb7880bbe891b3aaa83029995d9553b71bc27d8de087dfd65eb12f1a976887c322c729\",\"s\":\"25519d3ecf26f1d3833f11d9757135a7\"},{\"oc\":\"e2847ed445b99a8145a992fefe400f7a9a1f0253ffa837b76c1602d4a28ae81114\",\"s\":\"6b769ff71409e303be5ca17b08063375\"},{\"oc\":\"e2847ed445b99a8145a992feffd27dbccc23403644ed2feffa7aa72ca2e78d163b006e9765c25c979709adfac3eb53f92dcfcff868232545184a5122622c6d2e57\",\"s\":\"b7cb88c99e692f82aa89ac83e6d52a83\"}]}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_10000 WHERE eql_v3.jsonb_contains(value, $1::jsonb) LIMIT 10", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_10000", + "Async Capable": false, + "Index Cond": "(eql_v3.eq_term(eql_v3.jsonb_path_query_first((value)::jsonb, '75146c96a91ff82146e29e87b5accb95'::text)) = eql_v3.eq_term(('{\"a\": false, \"c\": \"mBbKl&U3G&rdmu!jlvOTNtai|WzTf%GxRRf|8D&*yFcQeZw~`a2wXjcee|dUu?(RM*o=Mf^e@IT*g|>~0V||-vzKbT*s~X`M^rdAlgWgZ#Jz9V6vZ`F(4Uv%?$9NLh8{gxllTC75JJ6cXpEbP!uwg-8nnb9kNg%aApC#s*+tb_lY_4JjIjc(PWht(iJW)gKqCBRpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_10000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_10000_field_eq_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.54, + "Total Cost": 2242.54 + } + ], + "Startup Cost": 0.54, + "Total Cost": 2.78 + } + } + ], + "id": "JSON/json/field_eq/bare/10000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_10000_field_eq_idx" + ], + "parameters": [ + "{\"a\":false,\"c\":\"mBbKl&U3G&rdmu!jlvOTNtai|WzTf%GxRRf|8D&*yFcQeZw~`a2wXjcee|dUu?(RM*o=Mf^e@IT*g|>~0V||-vzKbT*s~X`M^rdAlgWgZ#Jz9V6vZ`F(4Uv%?$9NLh8{gxllTC75JJ6cXpEbP!uwg-8nnb9kNg%aApC#s*+tb_lY_4JjIjc(PWht(iJW)gKqCBRpuh\",\"hm\":\"98b7664512c8c0125772e43e47dde0ce\",\"i\":{\"c\":\"value\",\"t\":\"json_ste_vec_small_encrypted_v3_10000\"},\"s\":\"75146c96a91ff82146e29e87b5accb95\",\"v\":3}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_10000 WHERE eql_v3.jsonb_path_query_first(value, '75146c96a91ff82146e29e87b5accb95') = $1::jsonb::public.jsonb_entry LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_10000", + "Async Capable": false, + "Filter": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\"}'::jsonb[])", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_10000", + "Startup Cost": 0.0, + "Total Cost": 4645.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 4.64 + } + } + ], + "id": "JSON/json/field_eq/extractor/10000", + "indexes_used": [], + "parameters": [ + "{\"sv\":[{\"s\":\"75146c96a91ff82146e29e87b5accb95\",\"hm\":\"98b7664512c8c0125772e43e47dde0ce\"}]}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_10000 WHERE eql_v3.jsonb_contains(value, $1::jsonb) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_10000", + "Async Capable": false, + "Index Cond": "(eql_v3.eq_term(eql_v3.jsonb_path_query_first((value)::jsonb, '75146c96a91ff82146e29e87b5accb95'::text)) = eql_v3.eq_term(('{\"a\": false, \"c\": \"mBbKl&U3G&rdmu!jlvOTNtai|WzTf%GxRRf|8D&*yFcQeZw~`a2wXjcee|dUu?(RM*o=Mf^e@IT*g|>~0V||-vzKbT*s~X`M^rdAlgWgZ#Jz9V6vZ`F(4Uv%?$9NLh8{gxllTC75JJ6cXpEbP!uwg-8nnb9kNg%aApC#s*+tb_lY_4JjIjc(PWht(iJW)gKqCBRpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_10000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_10000_field_eq_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.54, + "Total Cost": 2242.54 + } + ], + "Startup Cost": 0.54, + "Total Cost": 2.78 + } + } + ], + "id": "JSON/json/field_eq/functional/10000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_10000_field_eq_idx" + ], + "parameters": [ + "{\"a\":false,\"c\":\"mBbKl&U3G&rdmu!jlvOTNtai|WzTf%GxRRf|8D&*yFcQeZw~`a2wXjcee|dUu?(RM*o=Mf^e@IT*g|>~0V||-vzKbT*s~X`M^rdAlgWgZ#Jz9V6vZ`F(4Uv%?$9NLh8{gxllTC75JJ6cXpEbP!uwg-8nnb9kNg%aApC#s*+tb_lY_4JjIjc(PWht(iJW)gKqCBRpuh\",\"hm\":\"98b7664512c8c0125772e43e47dde0ce\",\"i\":{\"c\":\"value\",\"t\":\"json_ste_vec_small_encrypted_v3_10000\"},\"s\":\"75146c96a91ff82146e29e87b5accb95\",\"v\":3}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_10000 WHERE eql_v3.eq_term(eql_v3.jsonb_path_query_first(value, '75146c96a91ff82146e29e87b5accb95')) = eql_v3.eq_term($1::jsonb::public.jsonb_entry) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 36, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_10000", + "Async Capable": false, + "Index Name": "json_ste_vec_small_encrypted_v3_10000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10000, + "Plan Width": 36, + "Relation Name": "json_ste_vec_small_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.41, + "Total Cost": 13797.16 + } + ], + "Startup Cost": 0.41, + "Total Cost": 14.21 + } + } + ], + "id": "JSON/json/field_order/functional/10000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_10000_field_order_idx" + ], + "parameters": [], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_10000 ORDER BY eql_v3.ore_cllw(eql_v3.jsonb_path_query_first(value, '1c16090f62b45fc9a1404b2135beab94')) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_10000", + "Async Capable": false, + "Index Cond": "(eql_v3.ore_cllw(eql_v3.jsonb_path_query_first((value)::jsonb, '1c16090f62b45fc9a1404b2135beab94'::text)) > eql_v3.ore_cllw(('{\"a\": false, \"c\": \"mBbKl&U3G&rdmu!jlvOTNtai|6gK>*kN_ZyJpH9*c*$KTw9`)`)x;o={1z-A{D1D*Mb%o9gRb|Cu>!45`J)1foOj_sBK&5czy\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_10000\"}, \"s\": \"1c16090f62b45fc9a1404b2135beab94\", \"v\": 3, \"oc\": \"e108bb37379dfda0f0143886d8b88e748150ce18ba0d1fa98dda6bf96cb47d12150661d4710365e26993420af2ccd1d836df55ccbc9bb7a6fb4f5589c09032c4bf\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_10000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 2646, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.66, + "Total Cost": 6593.76 + } + ], + "Startup Cost": 0.66, + "Total Cost": 25.58 + } + } + ], + "id": "JSON/json/field_gt/functional/10000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_10000_field_order_idx" + ], + "parameters": [ + "{\"a\":false,\"c\":\"mBbKl&U3G&rdmu!jlvOTNtai|6gK>*kN_ZyJpH9*c*$KTw9`)`)x;o={1z-A{D1D*Mb%o9gRb|Cu>!45`J)1foOj_sBK&5czy\",\"i\":{\"c\":\"value\",\"t\":\"json_ste_vec_small_encrypted_v3_10000\"},\"oc\":\"e108bb37379dfda0f0143886d8b88e748150ce18ba0d1fa98dda6bf96cb47d12150661d4710365e26993420af2ccd1d836df55ccbc9bb7a6fb4f5589c09032c4bf\",\"s\":\"1c16090f62b45fc9a1404b2135beab94\",\"v\":3}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_10000 WHERE eql_v3.jsonb_path_query_first(value, '1c16090f62b45fc9a1404b2135beab94') > $1::jsonb::public.jsonb_entry LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "10000" +} \ No newline at end of file diff --git a/results/query/v3/json_metadata_100000.json b/results/query/v3/json_metadata_100000.json new file mode 100644 index 0000000..8f0a780 --- /dev/null +++ b/results/query/v3/json_metadata_100000.json @@ -0,0 +1,256 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_100000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed445baee82925a7a5a663fa0a488c796509325fbe46fee6db4348e604e9fca13c9c6dab8f19e6380c88111eca6e1024946c57cd2189644e055f6e3da741d\\\"}\",\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445baeddd580ed0f4e600b1a1b0a795e861d0738c0807142caf160adc5367814641383016a79c782539e7c3c74094a26998670debf9\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d759d250a567842a7c3f5af2a6b3f2a58a8160fc3e4079dc9e54b19e671a8834488db7592a060356887c3e718a86beaefae5648294\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ad759eaaa77577c5c0fa51b44f31e10c15d77798a69fe38252a01a79d62483c88ca828f2f55b01f2ce53421931e02a7425637d9aab24caf3f8184fa93b84fb2a933202bd7b27a38fa1d6eaeddeee178e882b82275ca68f35401ef1ced3167a7e0df4852a35c4042b081517fc9e45eb66b68285f26d619787ae9a2873ec2f0bee0f17ff420f38d30c9366a12709cb076e0da9aae5109dcb3d2f23105c3fba4c802a8d948bac8f609f84f2f73702fa5a4eeb1362738de9e4bd2b2e91b1a83867e0bba8c1b56b6d5b1f0b274539a841071fc02399a4d7\\\"}\"}'::jsonb[])", + "Index Name": "json_ste_vec_small_encrypted_v3_100000_jsonb_array_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 90.19 + } + ], + "Recheck Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed445baee82925a7a5a663fa0a488c796509325fbe46fee6db4348e604e9fca13c9c6dab8f19e6380c88111eca6e1024946c57cd2189644e055f6e3da741d\\\"}\",\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445baeddd580ed0f4e600b1a1b0a795e861d0738c0807142caf160adc5367814641383016a79c782539e7c3c74094a26998670debf9\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d759d250a567842a7c3f5af2a6b3f2a58a8160fc3e4079dc9e54b19e671a8834488db7592a060356887c3e718a86beaefae5648294\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ad759eaaa77577c5c0fa51b44f31e10c15d77798a69fe38252a01a79d62483c88ca828f2f55b01f2ce53421931e02a7425637d9aab24caf3f8184fa93b84fb2a933202bd7b27a38fa1d6eaeddeee178e882b82275ca68f35401ef1ced3167a7e0df4852a35c4042b081517fc9e45eb66b68285f26d619787ae9a2873ec2f0bee0f17ff420f38d30c9366a12709cb076e0da9aae5109dcb3d2f23105c3fba4c802a8d948bac8f609f84f2f73702fa5a4eeb1362738de9e4bd2b2e91b1a83867e0bba8c1b56b6d5b1f0b274539a841071fc02399a4d7\\\"}\"}'::jsonb[])", + "Relation Name": "json_ste_vec_small_encrypted_v3_100000", + "Startup Cost": 90.19, + "Total Cost": 94.45 + } + ], + "Startup Cost": 90.19, + "Total Cost": 94.45 + } + } + ], + "id": "JSON/json/contains/functional/100000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_100000_jsonb_array_index" + ], + "parameters": [ + "{\"sv\":[{\"hm\":\"98b7664512c8c0125772e43e47dde0ce\",\"s\":\"75146c96a91ff82146e29e87b5accb95\"},{\"oc\":\"e108bb37379dfda0f0143886d759d250a567842a7c3f5af2a6b3f2a58a8160fc3e4079dc9e54b19e671a8834488db7592a060356887c3e718a86beaefae5648294\",\"s\":\"1c16090f62b45fc9a1404b2135beab94\"},{\"oc\":\"e2847ed5ad759eaaa77577c5c0fa51b44f31e10c15d77798a69fe38252a01a79d62483c88ca828f2f55b01f2ce53421931e02a7425637d9aab24caf3f8184fa93b84fb2a933202bd7b27a38fa1d6eaeddeee178e882b82275ca68f35401ef1ced3167a7e0df4852a35c4042b081517fc9e45eb66b68285f26d619787ae9a2873ec2f0bee0f17ff420f38d30c9366a12709cb076e0da9aae5109dcb3d2f23105c3fba4c802a8d948bac8f609f84f2f73702fa5a4eeb1362738de9e4bd2b2e91b1a83867e0bba8c1b56b6d5b1f0b274539a841071fc02399a4d7\",\"s\":\"25519d3ecf26f1d3833f11d9757135a7\"},{\"oc\":\"e2847ed445baee82925a7a5a663fa0a488c796509325fbe46fee6db4348e604e9fca13c9c6dab8f19e6380c88111eca6e1024946c57cd2189644e055f6e3da741d\",\"s\":\"6b769ff71409e303be5ca17b08063375\"},{\"oc\":\"e2847ed445baeddd580ed0f4e600b1a1b0a795e861d0738c0807142caf160adc5367814641383016a79c782539e7c3c74094a26998670debf9\",\"s\":\"b7cb88c99e692f82aa89ac83e6d52a83\"}]}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_100000 WHERE eql_v3.jsonb_contains(value, $1::jsonb) LIMIT 10", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_100000", + "Async Capable": false, + "Index Cond": "(eql_v3.eq_term(eql_v3.jsonb_path_query_first((value)::jsonb, '75146c96a91ff82146e29e87b5accb95'::text)) = eql_v3.eq_term(('{\"a\": false, \"c\": \"mBbL>G+POZxYGacl>M3T^U9ILZDpH%1hfdNmea4A8^XTV*dGo;>8yO5r?BT&aSI_ZsSuV&t8=ymMaG~D6e7#MN-qMs)Y%I_YVN-rsOB%cplB^itOiGKiEl{QCd4G!M9XzS&)=SJlG6IPjHQ5xoo1+$vm3D)DE!$9mVU$_o~@jtT%uE4Q&7M?5}sa{E9tIM-1n8!Nah=}AiNxXpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_100000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_100000_field_eq_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.54, + "Total Cost": 22303.54 + } + ], + "Startup Cost": 0.54, + "Total Cost": 2.78 + } + } + ], + "id": "JSON/json/field_eq/bare/100000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_100000_field_eq_idx" + ], + "parameters": [ + "{\"a\":false,\"c\":\"mBbL>G+POZxYGacl>M3T^U9ILZDpH%1hfdNmea4A8^XTV*dGo;>8yO5r?BT&aSI_ZsSuV&t8=ymMaG~D6e7#MN-qMs)Y%I_YVN-rsOB%cplB^itOiGKiEl{QCd4G!M9XzS&)=SJlG6IPjHQ5xoo1+$vm3D)DE!$9mVU$_o~@jtT%uE4Q&7M?5}sa{E9tIM-1n8!Nah=}AiNxXpuh\",\"hm\":\"98b7664512c8c0125772e43e47dde0ce\",\"i\":{\"c\":\"value\",\"t\":\"json_ste_vec_small_encrypted_v3_100000\"},\"s\":\"75146c96a91ff82146e29e87b5accb95\",\"v\":3}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_100000 WHERE eql_v3.jsonb_path_query_first(value, '75146c96a91ff82146e29e87b5accb95') = $1::jsonb::public.jsonb_entry LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_100000", + "Async Capable": false, + "Filter": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\"}'::jsonb[])", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_100000", + "Startup Cost": 0.0, + "Total Cost": 46444.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 4.64 + } + } + ], + "id": "JSON/json/field_eq/extractor/100000", + "indexes_used": [], + "parameters": [ + "{\"sv\":[{\"s\":\"75146c96a91ff82146e29e87b5accb95\",\"hm\":\"98b7664512c8c0125772e43e47dde0ce\"}]}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_100000 WHERE eql_v3.jsonb_contains(value, $1::jsonb) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_100000", + "Async Capable": false, + "Index Cond": "(eql_v3.eq_term(eql_v3.jsonb_path_query_first((value)::jsonb, '75146c96a91ff82146e29e87b5accb95'::text)) = eql_v3.eq_term(('{\"a\": false, \"c\": \"mBbL>G+POZxYGacl>M3T^U9ILZDpH%1hfdNmea4A8^XTV*dGo;>8yO5r?BT&aSI_ZsSuV&t8=ymMaG~D6e7#MN-qMs)Y%I_YVN-rsOB%cplB^itOiGKiEl{QCd4G!M9XzS&)=SJlG6IPjHQ5xoo1+$vm3D)DE!$9mVU$_o~@jtT%uE4Q&7M?5}sa{E9tIM-1n8!Nah=}AiNxXpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_100000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_100000_field_eq_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.54, + "Total Cost": 22303.54 + } + ], + "Startup Cost": 0.54, + "Total Cost": 2.78 + } + } + ], + "id": "JSON/json/field_eq/functional/100000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_100000_field_eq_idx" + ], + "parameters": [ + "{\"a\":false,\"c\":\"mBbL>G+POZxYGacl>M3T^U9ILZDpH%1hfdNmea4A8^XTV*dGo;>8yO5r?BT&aSI_ZsSuV&t8=ymMaG~D6e7#MN-qMs)Y%I_YVN-rsOB%cplB^itOiGKiEl{QCd4G!M9XzS&)=SJlG6IPjHQ5xoo1+$vm3D)DE!$9mVU$_o~@jtT%uE4Q&7M?5}sa{E9tIM-1n8!Nah=}AiNxXpuh\",\"hm\":\"98b7664512c8c0125772e43e47dde0ce\",\"i\":{\"c\":\"value\",\"t\":\"json_ste_vec_small_encrypted_v3_100000\"},\"s\":\"75146c96a91ff82146e29e87b5accb95\",\"v\":3}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_100000 WHERE eql_v3.eq_term(eql_v3.jsonb_path_query_first(value, '75146c96a91ff82146e29e87b5accb95')) = eql_v3.eq_term($1::jsonb::public.jsonb_entry) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 36, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_100000", + "Async Capable": false, + "Index Name": "json_ste_vec_small_encrypted_v3_100000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 100000, + "Plan Width": 36, + "Relation Name": "json_ste_vec_small_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.42, + "Total Cost": 137868.42 + } + ], + "Startup Cost": 0.42, + "Total Cost": 14.2 + } + } + ], + "id": "JSON/json/field_order/functional/100000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_100000_field_order_idx" + ], + "parameters": [], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_100000 ORDER BY eql_v3.ore_cllw(eql_v3.jsonb_path_query_first(value, '1c16090f62b45fc9a1404b2135beab94')) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_100000", + "Async Capable": false, + "Index Cond": "(eql_v3.ore_cllw(eql_v3.jsonb_path_query_first((value)::jsonb, '1c16090f62b45fc9a1404b2135beab94'::text)) > eql_v3.ore_cllw(('{\"a\": false, \"c\": \"mBbL>G+POZxYGacl>M3T^U9IL6fdmJ|9;<-fD;-|!-w$DNLmafTf`uqt(>D=qElQ`P{2JBo?e$L>8?`T_m$H~<{Pshyc~U?zy\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_100000\"}, \"s\": \"1c16090f62b45fc9a1404b2135beab94\", \"v\": 3, \"oc\": \"e108bb37379dfda0f0143886d759d250a567842a7c3f5af2a6b3f2a58a8160fc3e4079dc9e54b19e671a8834488db7592a060356887c3e718a86beaefae5648294\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_100000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 62310, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.67, + "Total Cost": 85355.09 + } + ], + "Startup Cost": 0.67, + "Total Cost": 14.37 + } + } + ], + "id": "JSON/json/field_gt/functional/100000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_100000_field_order_idx" + ], + "parameters": [ + "{\"a\":false,\"c\":\"mBbL>G+POZxYGacl>M3T^U9IL6fdmJ|9;<-fD;-|!-w$DNLmafTf`uqt(>D=qElQ`P{2JBo?e$L>8?`T_m$H~<{Pshyc~U?zy\",\"i\":{\"c\":\"value\",\"t\":\"json_ste_vec_small_encrypted_v3_100000\"},\"oc\":\"e108bb37379dfda0f0143886d759d250a567842a7c3f5af2a6b3f2a58a8160fc3e4079dc9e54b19e671a8834488db7592a060356887c3e718a86beaefae5648294\",\"s\":\"1c16090f62b45fc9a1404b2135beab94\",\"v\":3}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_100000 WHERE eql_v3.jsonb_path_query_first(value, '1c16090f62b45fc9a1404b2135beab94') > $1::jsonb::public.jsonb_entry LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "100000" +} \ No newline at end of file diff --git a/results/query/v3/json_metadata_1000000.json b/results/query/v3/json_metadata_1000000.json new file mode 100644 index 0000000..57389bc --- /dev/null +++ b/results/query/v3/json_metadata_1000000.json @@ -0,0 +1,256 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_1000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed446d572477e0e74ae828304897b9f568962af078cdd5e9f431c2c05d49d78229e2d75115eee93156538ce6055ce65b627f446147bd3\\\"}\",\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445b99b00a005cc452ce307db927ed0c8b81d13e19cbb4c97c25a98a345ce77a106ed1accffff18f5c5a8d521f49164c2570fe0e15944dabc246a97232eed758beac7af182c7c455eb7763c5421a9eec34836c60124\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ae112c208a42fb629a590c3da6f55830676a44954cfacabcf6e315666343ea53c93db241fd37c6ba98ac8f703af8286961605cb53c8ca249738e035ca41ac9c92fe8ca38c498b62165de133166c7f9de09cdce5c1c54456b27e990e2d61075c67d683c61e87bcead8a94af1bf1d9c91f88e6dd8f38e76312d2e77c622afc00c6bfbd5bdebe01a36c6e63b205f42dd9798d6befe357093808609fed789160e166fefd9c137a72b2db8795d532d964e2a9ff3df18176\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d8b97d5813f5decb57cd129b4a3cfe86ba1339f27bee6833a277032ea11fd3cdaea0249e4dfd806fd691c652212db9a671e096a540\\\"}\"}'::jsonb[])", + "Index Name": "json_ste_vec_small_encrypted_v3_1000000_jsonb_array_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 111.51 + } + ], + "Recheck Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed446d572477e0e74ae828304897b9f568962af078cdd5e9f431c2c05d49d78229e2d75115eee93156538ce6055ce65b627f446147bd3\\\"}\",\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445b99b00a005cc452ce307db927ed0c8b81d13e19cbb4c97c25a98a345ce77a106ed1accffff18f5c5a8d521f49164c2570fe0e15944dabc246a97232eed758beac7af182c7c455eb7763c5421a9eec34836c60124\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ae112c208a42fb629a590c3da6f55830676a44954cfacabcf6e315666343ea53c93db241fd37c6ba98ac8f703af8286961605cb53c8ca249738e035ca41ac9c92fe8ca38c498b62165de133166c7f9de09cdce5c1c54456b27e990e2d61075c67d683c61e87bcead8a94af1bf1d9c91f88e6dd8f38e76312d2e77c622afc00c6bfbd5bdebe01a36c6e63b205f42dd9798d6befe357093808609fed789160e166fefd9c137a72b2db8795d532d964e2a9ff3df18176\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d8b97d5813f5decb57cd129b4a3cfe86ba1339f27bee6833a277032ea11fd3cdaea0249e4dfd806fd691c652212db9a671e096a540\\\"}\"}'::jsonb[])", + "Relation Name": "json_ste_vec_small_encrypted_v3_1000000", + "Startup Cost": 111.51, + "Total Cost": 115.78 + } + ], + "Startup Cost": 111.51, + "Total Cost": 115.78 + } + } + ], + "id": "JSON/json/contains/functional/1000000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_1000000_jsonb_array_index" + ], + "parameters": [ + "{\"sv\":[{\"hm\":\"98b7664512c8c0125772e43e47dde0ce\",\"s\":\"75146c96a91ff82146e29e87b5accb95\"},{\"oc\":\"e108bb37379dfda0f0143886d8b97d5813f5decb57cd129b4a3cfe86ba1339f27bee6833a277032ea11fd3cdaea0249e4dfd806fd691c652212db9a671e096a540\",\"s\":\"1c16090f62b45fc9a1404b2135beab94\"},{\"oc\":\"e2847ed5ae112c208a42fb629a590c3da6f55830676a44954cfacabcf6e315666343ea53c93db241fd37c6ba98ac8f703af8286961605cb53c8ca249738e035ca41ac9c92fe8ca38c498b62165de133166c7f9de09cdce5c1c54456b27e990e2d61075c67d683c61e87bcead8a94af1bf1d9c91f88e6dd8f38e76312d2e77c622afc00c6bfbd5bdebe01a36c6e63b205f42dd9798d6befe357093808609fed789160e166fefd9c137a72b2db8795d532d964e2a9ff3df18176\",\"s\":\"25519d3ecf26f1d3833f11d9757135a7\"},{\"oc\":\"e2847ed446d572477e0e74ae828304897b9f568962af078cdd5e9f431c2c05d49d78229e2d75115eee93156538ce6055ce65b627f446147bd3\",\"s\":\"6b769ff71409e303be5ca17b08063375\"},{\"oc\":\"e2847ed445b99b00a005cc452ce307db927ed0c8b81d13e19cbb4c97c25a98a345ce77a106ed1accffff18f5c5a8d521f49164c2570fe0e15944dabc246a97232eed758beac7af182c7c455eb7763c5421a9eec34836c60124\",\"s\":\"b7cb88c99e692f82aa89ac83e6d52a83\"}]}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_1000000 WHERE eql_v3.jsonb_contains(value, $1::jsonb) LIMIT 10", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_1000000", + "Async Capable": false, + "Index Cond": "(eql_v3.eq_term(eql_v3.jsonb_path_query_first((value)::jsonb, '75146c96a91ff82146e29e87b5accb95'::text)) = eql_v3.eq_term(('{\"a\": false, \"c\": \"mBbJ%T#O?hLqA`E(Oz(edIR9ZY@HZ~!poM<8VHyRM^Y>!N3+f4h3PAmRMTaIoe$WB`ON`M4Kyne+%ye{{cPA*_4ri{z#dizy\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_1000000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_1000000_field_eq_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1001642, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.68, + "Total Cost": 222842.41 + } + ], + "Startup Cost": 0.68, + "Total Cost": 2.9 + } + } + ], + "id": "JSON/json/field_eq/bare/1000000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_1000000_field_eq_idx" + ], + "parameters": [ + "{\"a\":false,\"c\":\"mBbJ%T#O?hLqA`E(Oz(edIR9ZY@HZ~!poM<8VHyRM^Y>!N3+f4h3PAmRMTaIoe$WB`ON`M4Kyne+%ye{{cPA*_4ri{z#dizy\",\"hm\":\"98b7664512c8c0125772e43e47dde0ce\",\"i\":{\"c\":\"value\",\"t\":\"json_ste_vec_small_encrypted_v3_1000000\"},\"s\":\"75146c96a91ff82146e29e87b5accb95\",\"v\":3}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_1000000 WHERE eql_v3.jsonb_path_query_first(value, '75146c96a91ff82146e29e87b5accb95') = $1::jsonb::public.jsonb_entry LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_1000000", + "Async Capable": false, + "Filter": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\"}'::jsonb[])", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1001642, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_1000000", + "Startup Cost": 0.0, + "Total Cost": 464757.03 + } + ], + "Startup Cost": 0.0, + "Total Cost": 4.64 + } + } + ], + "id": "JSON/json/field_eq/extractor/1000000", + "indexes_used": [], + "parameters": [ + "{\"sv\":[{\"s\":\"75146c96a91ff82146e29e87b5accb95\",\"hm\":\"98b7664512c8c0125772e43e47dde0ce\"}]}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_1000000 WHERE eql_v3.jsonb_contains(value, $1::jsonb) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_1000000", + "Async Capable": false, + "Index Cond": "(eql_v3.eq_term(eql_v3.jsonb_path_query_first((value)::jsonb, '75146c96a91ff82146e29e87b5accb95'::text)) = eql_v3.eq_term(('{\"a\": false, \"c\": \"mBbJ%T#O?hLqA`E(Oz(edIR9ZY@HZ~!poM<8VHyRM^Y>!N3+f4h3PAmRMTaIoe$WB`ON`M4Kyne+%ye{{cPA*_4ri{z#dizy\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_1000000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_1000000_field_eq_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1001642, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.68, + "Total Cost": 222842.41 + } + ], + "Startup Cost": 0.68, + "Total Cost": 2.9 + } + } + ], + "id": "JSON/json/field_eq/functional/1000000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_1000000_field_eq_idx" + ], + "parameters": [ + "{\"a\":false,\"c\":\"mBbJ%T#O?hLqA`E(Oz(edIR9ZY@HZ~!poM<8VHyRM^Y>!N3+f4h3PAmRMTaIoe$WB`ON`M4Kyne+%ye{{cPA*_4ri{z#dizy\",\"hm\":\"98b7664512c8c0125772e43e47dde0ce\",\"i\":{\"c\":\"value\",\"t\":\"json_ste_vec_small_encrypted_v3_1000000\"},\"s\":\"75146c96a91ff82146e29e87b5accb95\",\"v\":3}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_1000000 WHERE eql_v3.eq_term(eql_v3.jsonb_path_query_first(value, '75146c96a91ff82146e29e87b5accb95')) = eql_v3.eq_term($1::jsonb::public.jsonb_entry) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 36, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_1000000", + "Async Capable": false, + "Index Name": "json_ste_vec_small_encrypted_v3_1000000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1001642, + "Plan Width": 36, + "Relation Name": "json_ste_vec_small_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.55, + "Total Cost": 1378881.81 + } + ], + "Startup Cost": 0.55, + "Total Cost": 14.32 + } + } + ], + "id": "JSON/json/field_order/functional/1000000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_1000000_field_order_idx" + ], + "parameters": [], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_1000000 ORDER BY eql_v3.ore_cllw(eql_v3.jsonb_path_query_first(value, '1c16090f62b45fc9a1404b2135beab94')) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_1000000", + "Async Capable": false, + "Index Cond": "(eql_v3.ore_cllw(eql_v3.jsonb_path_query_first((value)::jsonb, '1c16090f62b45fc9a1404b2135beab94'::text)) > eql_v3.ore_cllw(('{\"a\": false, \"c\": \"mBbJ%T#O?hLqA`E(Oz(edIR9Z6r5ZRt;(F4${{cPA*_4ri{z#dizy\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_1000000\"}, \"s\": \"1c16090f62b45fc9a1404b2135beab94\", \"v\": 3, \"oc\": \"e108bb37379dfda0f0143886d8b97d5813f5decb57cd129b4a3cfe86ba1339f27bee6833a277032ea11fd3cdaea0249e4dfd806fd691c652212db9a671e096a540\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_1000000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 23672, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.8, + "Total Cost": 91165.11 + } + ], + "Startup Cost": 0.8, + "Total Cost": 39.31 + } + } + ], + "id": "JSON/json/field_gt/functional/1000000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_1000000_field_order_idx" + ], + "parameters": [ + "{\"a\":false,\"c\":\"mBbJ%T#O?hLqA`E(Oz(edIR9Z6r5ZRt;(F4${{cPA*_4ri{z#dizy\",\"i\":{\"c\":\"value\",\"t\":\"json_ste_vec_small_encrypted_v3_1000000\"},\"oc\":\"e108bb37379dfda0f0143886d8b97d5813f5decb57cd129b4a3cfe86ba1339f27bee6833a277032ea11fd3cdaea0249e4dfd806fd691c652212db9a671e096a540\",\"s\":\"1c16090f62b45fc9a1404b2135beab94\",\"v\":3}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_1000000 WHERE eql_v3.jsonb_path_query_first(value, '1c16090f62b45fc9a1404b2135beab94') > $1::jsonb::public.jsonb_entry LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "1000000" +} \ No newline at end of file diff --git a/results/query/v3/json_metadata_10000000.json b/results/query/v3/json_metadata_10000000.json new file mode 100644 index 0000000..142fc70 --- /dev/null +++ b/results/query/v3/json_metadata_10000000.json @@ -0,0 +1,256 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_10000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 4, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed445b99b00a005cc452b2f322ff38b63e1fd75ec0c254ef4eab3454d73767587fdd4e961c3d6719c8851f75df976\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d8b88f3dc8ef1dbc11bad17ae69d7bd0c112796ba6416baf0e3b0dc577886a15389fc364d1b3ceb56488adecb738298ff9b47cd306\\\"}\",\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ae112b8eee58a8745ea7dfee54ece27100c9bdd278919b961e699db652bba421a06e89490da16222946fbfb0930425811f6a467a6c47a0fb2a5c1137f336085f4b277c939e2e775adc108ba19fdec36e352996de6a29fe5dd44c35750a4ba83fefcab64f8d5b71ee2d5918284de3e48a14c237e38ba457ae00a5cf594ae52bb6d35fffb84c9b0937a5d35a60a7b4dfeae483a9d4abdbbdc797201cca110864ac480c384077184935682e302ee65f3283118bcf4707\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445baeddc1bf42210e9f10a92d31e6e326398d47cb4f593328e1832b2656e3b102da2deda13\\\"}\"}'::jsonb[])", + "Index Name": "json_ste_vec_small_encrypted_v3_10000000_jsonb_array_index", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 132.79 + } + ], + "Recheck Cond": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"6b769ff71409e303be5ca17b08063375\\\", \\\"oc\\\": \\\"e2847ed445b99b00a005cc452b2f322ff38b63e1fd75ec0c254ef4eab3454d73767587fdd4e961c3d6719c8851f75df976\\\"}\",\"{\\\"s\\\": \\\"1c16090f62b45fc9a1404b2135beab94\\\", \\\"oc\\\": \\\"e108bb37379dfda0f0143886d8b88f3dc8ef1dbc11bad17ae69d7bd0c112796ba6416baf0e3b0dc577886a15389fc364d1b3ceb56488adecb738298ff9b47cd306\\\"}\",\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\",\"{\\\"s\\\": \\\"25519d3ecf26f1d3833f11d9757135a7\\\", \\\"oc\\\": \\\"e2847ed5ae112b8eee58a8745ea7dfee54ece27100c9bdd278919b961e699db652bba421a06e89490da16222946fbfb0930425811f6a467a6c47a0fb2a5c1137f336085f4b277c939e2e775adc108ba19fdec36e352996de6a29fe5dd44c35750a4ba83fefcab64f8d5b71ee2d5918284de3e48a14c237e38ba457ae00a5cf594ae52bb6d35fffb84c9b0937a5d35a60a7b4dfeae483a9d4abdbbdc797201cca110864ac480c384077184935682e302ee65f3283118bcf4707\\\"}\",\"{\\\"s\\\": \\\"b7cb88c99e692f82aa89ac83e6d52a83\\\", \\\"oc\\\": \\\"e2847ed445baeddc1bf42210e9f10a92d31e6e326398d47cb4f593328e1832b2656e3b102da2deda13\\\"}\"}'::jsonb[])", + "Relation Name": "json_ste_vec_small_encrypted_v3_10000000", + "Startup Cost": 132.79, + "Total Cost": 137.05 + } + ], + "Startup Cost": 132.79, + "Total Cost": 137.05 + } + } + ], + "id": "JSON/json/contains/functional/10000000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_10000000_jsonb_array_index" + ], + "parameters": [ + "{\"sv\":[{\"hm\":\"98b7664512c8c0125772e43e47dde0ce\",\"s\":\"75146c96a91ff82146e29e87b5accb95\"},{\"oc\":\"e108bb37379dfda0f0143886d8b88f3dc8ef1dbc11bad17ae69d7bd0c112796ba6416baf0e3b0dc577886a15389fc364d1b3ceb56488adecb738298ff9b47cd306\",\"s\":\"1c16090f62b45fc9a1404b2135beab94\"},{\"oc\":\"e2847ed5ae112b8eee58a8745ea7dfee54ece27100c9bdd278919b961e699db652bba421a06e89490da16222946fbfb0930425811f6a467a6c47a0fb2a5c1137f336085f4b277c939e2e775adc108ba19fdec36e352996de6a29fe5dd44c35750a4ba83fefcab64f8d5b71ee2d5918284de3e48a14c237e38ba457ae00a5cf594ae52bb6d35fffb84c9b0937a5d35a60a7b4dfeae483a9d4abdbbdc797201cca110864ac480c384077184935682e302ee65f3283118bcf4707\",\"s\":\"25519d3ecf26f1d3833f11d9757135a7\"},{\"oc\":\"e2847ed445b99b00a005cc452b2f322ff38b63e1fd75ec0c254ef4eab3454d73767587fdd4e961c3d6719c8851f75df976\",\"s\":\"6b769ff71409e303be5ca17b08063375\"},{\"oc\":\"e2847ed445baeddc1bf42210e9f10a92d31e6e326398d47cb4f593328e1832b2656e3b102da2deda13\",\"s\":\"b7cb88c99e692f82aa89ac83e6d52a83\"}]}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_10000000 WHERE eql_v3.jsonb_contains(value, $1::jsonb) LIMIT 10", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_10000000", + "Async Capable": false, + "Index Cond": "(eql_v3.eq_term(eql_v3.jsonb_path_query_first((value)::jsonb, '75146c96a91ff82146e29e87b5accb95'::text)) = eql_v3.eq_term(('{\"a\": false, \"c\": \"mBbKdL{%RNuK>0?jR{}{TcEhaWm?it8o3@A!B9O_Ve_vbf!P^7`HpOMhg7r=0>?cU1z3gGN?;ss-t|Pc*N4jA6b4XX?4ja(m^ns%IO=0v;tCgV#q5`TSV2hKIfV#*07WP+Ji7W{F$7iY3M9G5^FM;|!vaI5(ygH_cN#w3lA&0TG8q6@l&@FR^NUj6QUOpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_10000000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_10000000_field_eq_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 9998476, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.69, + "Total Cost": 2112453.02 + } + ], + "Startup Cost": 0.69, + "Total Cost": 2.8 + } + } + ], + "id": "JSON/json/field_eq/bare/10000000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_10000000_field_eq_idx" + ], + "parameters": [ + "{\"a\":false,\"c\":\"mBbKdL{%RNuK>0?jR{}{TcEhaWm?it8o3@A!B9O_Ve_vbf!P^7`HpOMhg7r=0>?cU1z3gGN?;ss-t|Pc*N4jA6b4XX?4ja(m^ns%IO=0v;tCgV#q5`TSV2hKIfV#*07WP+Ji7W{F$7iY3M9G5^FM;|!vaI5(ygH_cN#w3lA&0TG8q6@l&@FR^NUj6QUOpuh\",\"hm\":\"98b7664512c8c0125772e43e47dde0ce\",\"i\":{\"c\":\"value\",\"t\":\"json_ste_vec_small_encrypted_v3_10000000\"},\"s\":\"75146c96a91ff82146e29e87b5accb95\",\"v\":3}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_10000000 WHERE eql_v3.jsonb_path_query_first(value, '75146c96a91ff82146e29e87b5accb95') = $1::jsonb::public.jsonb_entry LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_10000000", + "Async Capable": false, + "Filter": "(eql_v3.jsonb_array((value)::jsonb) @> '{\"{\\\"s\\\": \\\"75146c96a91ff82146e29e87b5accb95\\\", \\\"hm\\\": \\\"98b7664512c8c0125772e43e47dde0ce\\\"}\"}'::jsonb[])", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 9998476, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_10000000", + "Startup Cost": 0.0, + "Total Cost": 4527343.95 + } + ], + "Startup Cost": 0.0, + "Total Cost": 4.53 + } + } + ], + "id": "JSON/json/field_eq/extractor/10000000", + "indexes_used": [], + "parameters": [ + "{\"sv\":[{\"s\":\"75146c96a91ff82146e29e87b5accb95\",\"hm\":\"98b7664512c8c0125772e43e47dde0ce\"}]}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_10000000 WHERE eql_v3.jsonb_contains(value, $1::jsonb) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_10000000", + "Async Capable": false, + "Index Cond": "(eql_v3.eq_term(eql_v3.jsonb_path_query_first((value)::jsonb, '75146c96a91ff82146e29e87b5accb95'::text)) = eql_v3.eq_term(('{\"a\": false, \"c\": \"mBbKdL{%RNuK>0?jR{}{TcEhaWm?it8o3@A!B9O_Ve_vbf!P^7`HpOMhg7r=0>?cU1z3gGN?;ss-t|Pc*N4jA6b4XX?4ja(m^ns%IO=0v;tCgV#q5`TSV2hKIfV#*07WP+Ji7W{F$7iY3M9G5^FM;|!vaI5(ygH_cN#w3lA&0TG8q6@l&@FR^NUj6QUOpuh\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_10000000\"}, \"s\": \"75146c96a91ff82146e29e87b5accb95\", \"v\": 3, \"hm\": \"98b7664512c8c0125772e43e47dde0ce\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_10000000_field_eq_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 9998476, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.69, + "Total Cost": 2112453.02 + } + ], + "Startup Cost": 0.69, + "Total Cost": 2.8 + } + } + ], + "id": "JSON/json/field_eq/functional/10000000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_10000000_field_eq_idx" + ], + "parameters": [ + "{\"a\":false,\"c\":\"mBbKdL{%RNuK>0?jR{}{TcEhaWm?it8o3@A!B9O_Ve_vbf!P^7`HpOMhg7r=0>?cU1z3gGN?;ss-t|Pc*N4jA6b4XX?4ja(m^ns%IO=0v;tCgV#q5`TSV2hKIfV#*07WP+Ji7W{F$7iY3M9G5^FM;|!vaI5(ygH_cN#w3lA&0TG8q6@l&@FR^NUj6QUOpuh\",\"hm\":\"98b7664512c8c0125772e43e47dde0ce\",\"i\":{\"c\":\"value\",\"t\":\"json_ste_vec_small_encrypted_v3_10000000\"},\"s\":\"75146c96a91ff82146e29e87b5accb95\",\"v\":3}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_10000000 WHERE eql_v3.eq_term(eql_v3.jsonb_path_query_first(value, '75146c96a91ff82146e29e87b5accb95')) = eql_v3.eq_term($1::jsonb::public.jsonb_entry) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 36, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_10000000", + "Async Capable": false, + "Index Name": "json_ste_vec_small_encrypted_v3_10000000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 9998476, + "Plan Width": 36, + "Relation Name": "json_ste_vec_small_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.56, + "Total Cost": 13318010.53 + } + ], + "Startup Cost": 0.56, + "Total Cost": 13.88 + } + } + ], + "id": "JSON/json/field_order/functional/10000000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_10000000_field_order_idx" + ], + "parameters": [], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_10000000 ORDER BY eql_v3.ore_cllw(eql_v3.jsonb_path_query_first(value, '1c16090f62b45fc9a1404b2135beab94')) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_ste_vec_small_encrypted_v3_10000000", + "Async Capable": false, + "Index Cond": "(eql_v3.ore_cllw(eql_v3.jsonb_path_query_first((value)::jsonb, '1c16090f62b45fc9a1404b2135beab94'::text)) > eql_v3.ore_cllw(('{\"a\": false, \"c\": \"mBbKdL{%RNuK>0?jR{}{TcEha6s0(h*T(hF&eWwwx?&mD6;1%QQN$qQ45E=ZH>MOf%~L$ImtO1v5r;(;f$kkIv1)ycK6Hbizy\", \"i\": {\"c\": \"value\", \"t\": \"json_ste_vec_small_encrypted_v3_10000000\"}, \"s\": \"1c16090f62b45fc9a1404b2135beab94\", \"v\": 3, \"oc\": \"e108bb37379dfda0f0143886d8b88f3dc8ef1dbc11bad17ae69d7bd0c112796ba6416baf0e3b0dc577886a15389fc364d1b3ceb56488adecb738298ff9b47cd306\"}'::jsonb)::jsonb_entry))", + "Index Name": "json_ste_vec_small_encrypted_v3_10000000_field_order_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1190152, + "Plan Width": 4, + "Relation Name": "json_ste_vec_small_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.81, + "Total Cost": 3713359.52 + } + ], + "Startup Cost": 0.81, + "Total Cost": 32.01 + } + } + ], + "id": "JSON/json/field_gt/functional/10000000", + "indexes_used": [ + "json_ste_vec_small_encrypted_v3_10000000_field_order_idx" + ], + "parameters": [ + "{\"a\":false,\"c\":\"mBbKdL{%RNuK>0?jR{}{TcEha6s0(h*T(hF&eWwwx?&mD6;1%QQN$qQ45E=ZH>MOf%~L$ImtO1v5r;(;f$kkIv1)ycK6Hbizy\",\"i\":{\"c\":\"value\",\"t\":\"json_ste_vec_small_encrypted_v3_10000000\"},\"oc\":\"e108bb37379dfda0f0143886d8b88f3dc8ef1dbc11bad17ae69d7bd0c112796ba6416baf0e3b0dc577886a15389fc364d1b3ceb56488adecb738298ff9b47cd306\",\"s\":\"1c16090f62b45fc9a1404b2135beab94\",\"v\":3}" + ], + "query": "SELECT id FROM json_ste_vec_small_encrypted_v3_10000000 WHERE eql_v3.jsonb_path_query_first(value, '1c16090f62b45fc9a1404b2135beab94') > $1::jsonb::public.jsonb_entry LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "10000000" +} \ No newline at end of file diff --git a/results/query/v3/json_rows_10000.json b/results/query/v3/json_rows_10000.json new file mode 100644 index 0000000..76fb48d --- /dev/null +++ b/results/query/v3/json_rows_10000.json @@ -0,0 +1,7 @@ +{"reason":"benchmark-complete","id":"JSON/json/contains/functional/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_contains_functional_10000","iteration_count":[394,788,1182,1576,1970,2364,2758,3152,3546,3940],"measured_values":[86779041.0,170756375.0,293885459.0,392915458.0,451614333.0,514229708.0,699887833.0,733071792.0,851464875.0,908971708.0],"unit":"ns","throughput":[],"typical":{"estimate":235623.6405498055,"lower_bound":228890.4754357785,"upper_bound":243498.28513593474,"unit":"ns"},"mean":{"estimate":233882.75631375395,"lower_bound":225959.4556768189,"upper_bound":242020.89918419145,"unit":"ns"},"median":{"estimate":231638.5086294416,"lower_bound":220251.3730964467,"upper_bound":248634.0600676819,"unit":"ns"},"median_abs_dev":{"estimate":18903.43652617354,"lower_bound":2466.811924784019,"upper_bound":22524.34047536682,"unit":"ns"},"slope":{"estimate":235623.6405498055,"lower_bound":228890.4754357785,"upper_bound":243498.28513593474,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_eq/bare/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_eq_bare_10000","iteration_count":[802,1604,2406,3208,4010,4812,5614,6416,7218,8020],"measured_values":[87899875.0,178450916.0,284103250.0,352501083.0,442380042.0,589051833.0,638167166.0,709530542.0,853206667.0,903079334.0],"unit":"ns","throughput":[],"typical":{"estimate":114345.2888493053,"lower_bound":111678.5305194869,"upper_bound":117408.95671469474,"unit":"ns"},"mean":{"estimate":113662.06121086174,"lower_bound":111274.1183915212,"upper_bound":116385.33995982268,"unit":"ns"},"median":{"estimate":111928.54825436408,"lower_bound":110234.78086034913,"upper_bound":118081.15128844556,"unit":"ns"},"median_abs_dev":{"estimate":2811.2713620912036,"lower_bound":523.2052788658565,"upper_bound":6855.550905222323,"unit":"ns"},"slope":{"estimate":114345.2888493053,"lower_bound":111678.5305194869,"upper_bound":117408.95671469474,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_eq/extractor/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_eq_extractor_10000","iteration_count":[111,222,333,444,555,666,777,888,999,1110],"measured_values":[82756292.0,201526500.0,249201375.0,330391167.0,429082958.0,499877334.0,688486209.0,727121291.0,804274583.0,989222083.0],"unit":"ns","throughput":[],"typical":{"estimate":829922.1422019422,"lower_bound":783142.3283108575,"upper_bound":865692.062509943,"unit":"ns"},"mean":{"estimate":807067.8597250822,"lower_bound":770043.1521975547,"upper_bound":846990.2171253397,"unit":"ns"},"median":{"estimate":789101.0547547548,"lower_bound":748059.3738738738,"upper_bound":886082.637065637,"unit":"ns"},"median_abs_dev":{"estimate":62489.69994836378,"lower_bound":3786.8781281749557,"upper_bound":104244.93866360668,"unit":"ns"},"slope":{"estimate":829922.1422019422,"lower_bound":783142.3283108575,"upper_bound":865692.062509943,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_eq/functional/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_eq_functional_10000","iteration_count":[766,1532,2298,3064,3830,4596,5362,6128,6894,7660],"measured_values":[82872334.0,163059000.0,257886000.0,352369333.0,442406250.0,524982833.0,590948000.0,691361250.0,767282750.0,849341833.0],"unit":"ns","throughput":[],"typical":{"estimate":111968.20383845919,"lower_bound":111073.38261361782,"upper_bound":113409.31339934433,"unit":"ns"},"mean":{"estimate":111679.33125056986,"lower_bound":109915.65805102262,"upper_bound":113335.32153747047,"unit":"ns"},"median":{"estimate":111759.5554105019,"lower_bound":109534.28022193212,"upper_bound":114226.02980852916,"unit":"ns"},"median_abs_dev":{"estimate":2976.809107921311,"lower_bound":805.6518242520887,"upper_bound":5051.678035673786,"unit":"ns"},"slope":{"estimate":111968.20383845919,"lower_bound":111073.38261361782,"upper_bound":113409.31339934433,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_order/functional/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_order_functional_10000","iteration_count":[351,702,1053,1404,1755,2106,2457,2808,3159,3510],"measured_values":[87762167.0,172957250.0,264251000.0,364445541.0,482253083.0,560254375.0,609021792.0,769755583.0,807417916.0,866462875.0],"unit":"ns","throughput":[],"typical":{"estimate":257591.22875642875,"lower_bound":250304.954870885,"upper_bound":267605.71690328553,"unit":"ns"},"mean":{"estimate":257220.55270056077,"lower_bound":251134.89642517976,"upper_bound":263928.60637241666,"unit":"ns"},"median":{"estimate":253271.74992086104,"lower_bound":247872.1172161172,"upper_bound":266853.03863960115,"unit":"ns"},"median_abs_dev":{"estimate":9430.133627667123,"lower_bound":1461.7984684923615,"upper_bound":17861.487753087495,"unit":"ns"},"slope":{"estimate":257591.22875642875,"lower_bound":250304.954870885,"upper_bound":267605.71690328553,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_gt/functional/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_gt_functional_10000","iteration_count":[382,764,1146,1528,1910,2292,2674,3056,3438,3820],"measured_values":[85860875.0,182663125.0,250148250.0,333969209.0,459872792.0,584681000.0,610864333.0,691218208.0,874840292.0,913239917.0],"unit":"ns","throughput":[],"typical":{"estimate":239047.50434486978,"lower_bound":229385.66233030922,"upper_bound":247713.70436780815,"unit":"ns"},"mean":{"estimate":234472.7642298263,"lower_bound":226866.699205674,"upper_bound":242527.89438049527,"unit":"ns"},"median":{"estimate":233756.96987658937,"lower_bound":222375.10242146597,"upper_bound":246774.92066608492,"unit":"ns"},"median_abs_dev":{"estimate":12278.361236491934,"lower_bound":1262.4740475080512,"upper_bound":22793.672037652563,"unit":"ns"},"slope":{"estimate":239047.50434486978,"lower_bound":229385.66233030922,"upper_bound":247713.70436780815,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"JSON","benchmarks":["JSON/json/contains/functional/10000","JSON/json/field_eq/bare/10000","JSON/json/field_eq/extractor/10000","JSON/json/field_eq/functional/10000","JSON/json/field_order/functional/10000","JSON/json/field_gt/functional/10000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON"} diff --git a/results/query/v3/json_rows_100000.json b/results/query/v3/json_rows_100000.json new file mode 100644 index 0000000..c8b5ade --- /dev/null +++ b/results/query/v3/json_rows_100000.json @@ -0,0 +1,7 @@ +{"reason":"benchmark-complete","id":"JSON/json/contains/functional/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_contains_functional_100000","iteration_count":[320,640,960,1280,1600,1920,2240,2560,2880,3200],"measured_values":[79771459.0,156637792.0,235490916.0,314853125.0,480594666.0,474441708.0,579868375.0,635496125.0,744158375.0,840461542.0],"unit":"ns","throughput":[],"typical":{"estimate":258552.3075405844,"lower_bound":251014.43092570754,"upper_bound":267220.1316444175,"unit":"ns"},"mean":{"estimate":256093.41639050096,"lower_bound":248300.40285590276,"upper_bound":267229.3930231802,"unit":"ns"},"median":{"estimate":248763.2416015625,"lower_bound":245979.00390625,"upper_bound":260516.2782638889,"unit":"ns"},"median_abs_dev":{"estimate":5542.622686325352,"lower_bound":913.6180644831707,"upper_bound":18064.409912625953,"unit":"ns"},"slope":{"estimate":258552.3075405844,"lower_bound":251014.43092570754,"upper_bound":267220.1316444175,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_eq/bare/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_eq_bare_100000","iteration_count":[778,1556,2334,3112,3890,4668,5446,6224,7002,7780],"measured_values":[85127417.0,171362417.0,279287833.0,350022334.0,456742041.0,525743041.0,716556792.0,694855291.0,796599042.0,877643000.0],"unit":"ns","throughput":[],"typical":{"estimate":115596.21669615731,"lower_bound":112608.619654342,"upper_bound":121687.5515003955,"unit":"ns"},"mean":{"estimate":115151.65472257926,"lower_bound":111923.03468265319,"upper_bound":119494.45152726005,"unit":"ns"},"median":{"estimate":112717.31373179091,"lower_bound":111302.56555269923,"upper_bound":117414.40642673522,"unit":"ns"},"median_abs_dev":{"estimate":2715.578412216222,"lower_bound":267.66805296001917,"upper_bound":7694.66053824145,"unit":"ns"},"slope":{"estimate":115596.21669615731,"lower_bound":112608.619654342,"upper_bound":121687.5515003955,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_eq/extractor/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_eq_extractor_100000","iteration_count":[15,30,45,60,75,90,105,120,135,150],"measured_values":[91387416.0,180446625.0,271193917.0,365273000.0,469310250.0,560434958.0,644650000.0,751888583.0,813537584.0,923816125.0],"unit":"ns","throughput":[],"typical":{"estimate":6151302.785281385,"lower_bound":6082091.930416881,"upper_bound":6218626.907094017,"unit":"ns"},"mean":{"estimate":6129656.230489416,"lower_bound":6074687.497425927,"upper_bound":6186125.647116403,"unit":"ns"},"median":{"estimate":6116009.104761905,"lower_bound":6026531.488888889,"upper_bound":6227055.088888889,"unit":"ns"},"median_abs_dev":{"estimate":132902.0368382957,"lower_bound":8874.214710228707,"upper_bound":166725.93977252164,"unit":"ns"},"slope":{"estimate":6151302.785281385,"lower_bound":6082091.930416881,"upper_bound":6218626.907094017,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_eq/functional/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_eq_functional_100000","iteration_count":[810,1620,2430,3240,4050,4860,5670,6480,7290,8100],"measured_values":[105129792.0,170460167.0,291461666.0,352342833.0,432475791.0,556800709.0,647071375.0,832149417.0,814978959.0,944001334.0],"unit":"ns","throughput":[],"typical":{"estimate":116063.8402982203,"lower_bound":111597.28980266355,"upper_bound":121215.99681988536,"unit":"ns"},"mean":{"estimate":115593.27713977073,"lower_bound":110937.22090522121,"upper_bound":120698.26462456275,"unit":"ns"},"median":{"estimate":114344.99137272192,"lower_bound":108747.78796296296,"upper_bound":122480.74723765432,"unit":"ns"},"median_abs_dev":{"estimate":8299.064226581913,"lower_bound":1795.0126556877124,"upper_bound":14989.574678104069,"unit":"ns"},"slope":{"estimate":116063.8402982203,"lower_bound":111597.28980266355,"upper_bound":121215.99681988536,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_order/functional/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_order_functional_100000","iteration_count":[338,676,1014,1352,1690,2028,2366,2704,3042,3380],"measured_values":[83599667.0,221027500.0,284408166.0,351152084.0,536507584.0,562237125.0,699352875.0,701616833.0,828439708.0,865584167.0],"unit":"ns","throughput":[],"typical":{"estimate":272494.05980173673,"lower_bound":262192.4984095106,"upper_bound":289210.3872621276,"unit":"ns"},"mean":{"estimate":279268.87430203345,"lower_bound":264548.1310930309,"upper_bound":295619.3650399731,"unit":"ns"},"median":{"estimate":274785.56796515454,"lower_bound":257908.93150887574,"upper_bound":298970.7674556213,"unit":"ns"},"median_abs_dev":{"estimate":25209.733246059604,"lower_bound":2885.194762468377,"upper_bound":43628.70196679662,"unit":"ns"},"slope":{"estimate":272494.05980173673,"lower_bound":262192.4984095106,"upper_bound":289210.3872621276,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_gt/functional/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_gt_functional_100000","iteration_count":[107,214,321,428,535,642,749,856,963,1070],"measured_values":[90218209.0,179273916.0,269854208.0,368008667.0,446786916.0,559285250.0,628297042.0,727445334.0,814958500.0,922833417.0],"unit":"ns","throughput":[],"typical":{"estimate":852060.0084719019,"lower_bound":843446.2133906301,"upper_bound":859734.7375094721,"unit":"ns"},"mean":{"estimate":848506.5431122979,"lower_bound":841783.3807884401,"upper_bound":855955.3957286938,"unit":"ns"},"median":{"estimate":844715.6703011423,"lower_bound":838847.8531375166,"upper_bound":859833.3341121495,"unit":"ns"},"median_abs_dev":{"estimate":9529.343150134979,"lower_bound":2305.2035568938145,"upper_bound":19143.70381947704,"unit":"ns"},"slope":{"estimate":852060.0084719019,"lower_bound":843446.2133906301,"upper_bound":859734.7375094721,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"JSON","benchmarks":["JSON/json/contains/functional/100000","JSON/json/field_eq/bare/100000","JSON/json/field_eq/extractor/100000","JSON/json/field_eq/functional/100000","JSON/json/field_order/functional/100000","JSON/json/field_gt/functional/100000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON"} diff --git a/results/query/v3/json_rows_1000000.json b/results/query/v3/json_rows_1000000.json new file mode 100644 index 0000000..f38da83 --- /dev/null +++ b/results/query/v3/json_rows_1000000.json @@ -0,0 +1,7 @@ +{"reason":"benchmark-complete","id":"JSON/json/contains/functional/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_contains_functional_1000000","iteration_count":[222,444,666,888,1110,1332,1554,1776,1998,2220],"measured_values":[96253334.0,192518166.0,261673208.0,348312917.0,458632542.0,505372416.0,607209916.0,759631416.0,902904208.0,1061792125.0],"unit":"ns","throughput":[],"typical":{"estimate":433561.9284661285,"lower_bound":396990.53128242854,"upper_bound":457212.2204807114,"unit":"ns"},"mean":{"estimate":419356.0343733019,"lower_bound":401708.35777938645,"upper_bound":438294.96424924926,"unit":"ns"},"median":{"estimate":420451.43108108104,"lower_bound":391821.3432003432,"upper_bound":442738.7922922923,"unit":"ns"},"median_abs_dev":{"estimate":41331.826843668285,"lower_bound":2091.3420627587025,"upper_bound":58050.99505891583,"unit":"ns"},"slope":{"estimate":433561.9284661285,"lower_bound":396990.53128242854,"upper_bound":457212.2204807114,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_eq/bare/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_eq_bare_1000000","iteration_count":[845,1690,2535,3380,4225,5070,5915,6760,7605,8450],"measured_values":[89556959.0,194543708.0,317240250.0,389014458.0,437833333.0,531448167.0,632497833.0,756162875.0,869474792.0,946774167.0],"unit":"ns","throughput":[],"typical":{"estimate":111070.71775301622,"lower_bound":108010.3658947895,"upper_bound":113349.57265277978,"unit":"ns"},"mean":{"estimate":111495.08380863155,"lower_bound":107923.31055199234,"upper_bound":115520.22864574174,"unit":"ns"},"median":{"estimate":111951.34678994084,"lower_bound":105876.64366018598,"upper_bound":115093.0349112426,"unit":"ns"},"median_abs_dev":{"estimate":6066.396170998162,"lower_bound":598.1135323596679,"upper_bound":12201.538303958132,"unit":"ns"},"slope":{"estimate":111070.71775301622,"lower_bound":108010.3658947895,"upper_bound":113349.57265277978,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_eq/extractor/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_eq_extractor_1000000","iteration_count":[2,4,6,8,10,12,14,16,18,20],"measured_values":[138513875.0,287452959.0,444195625.0,587516000.0,692076959.0,878620583.0,1008122667.0,1218350500.0,1256332541.0,1428430916.0],"unit":"ns","throughput":[],"typical":{"estimate":72107978.77792208,"lower_bound":70636135.0625,"upper_bound":74110953.84050055,"unit":"ns"},"mean":{"estimate":72039182.54896826,"lower_bound":70739437.95723411,"upper_bound":73380174.27998215,"unit":"ns"},"median":{"estimate":71936000.83928572,"lower_bound":69796252.27777778,"upper_bound":73625493.04166667,"unit":"ns"},"median_abs_dev":{"estimate":2668755.9270451115,"lower_bound":435303.3083818268,"upper_bound":4014000.434987247,"unit":"ns"},"slope":{"estimate":72107978.77792208,"lower_bound":70636135.0625,"upper_bound":74110953.84050055,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_eq/functional/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_eq_functional_1000000","iteration_count":[804,1608,2412,3216,4020,4824,5628,6432,7236,8040],"measured_values":[137138458.0,188566292.0,317783708.0,349968458.0,459037291.0,523630417.0,632539000.0,700946625.0,768208125.0,948072375.0],"unit":"ns","throughput":[],"typical":{"estimate":112212.98646378497,"lower_bound":108496.64535909836,"upper_bound":116414.63254223071,"unit":"ns"},"mean":{"estimate":119659.89474843047,"lower_bound":110816.8291388926,"upper_bound":132542.3149683687,"unit":"ns"},"median":{"estimate":113289.90826226013,"lower_bound":108762.47779332504,"upper_bound":124509.35862354893,"unit":"ns"},"median_abs_dev":{"estimate":6744.652467198774,"lower_bound":435.93379689370215,"upper_bound":16944.29841006165,"unit":"ns"},"slope":{"estimate":112212.98646378497,"lower_bound":108496.64535909836,"upper_bound":116414.63254223071,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_order/functional/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_order_functional_1000000","iteration_count":[310,620,930,1240,1550,1860,2170,2480,2790,3100],"measured_values":[80796458.0,208663208.0,344544750.0,355690042.0,402095958.0,480309583.0,542898166.0,674846416.0,735954542.0,936882250.0],"unit":"ns","throughput":[],"typical":{"estimate":276818.8223544198,"lower_bound":261556.53467161756,"upper_bound":293826.5172427035,"unit":"ns"},"mean":{"estimate":286046.208391193,"lower_bound":265261.1481592422,"upper_bound":311152.7091398106,"unit":"ns"},"median":{"estimate":267949.2401433692,"lower_bound":259416.7470967742,"upper_bound":311700.18467741937,"unit":"ns"},"median_abs_dev":{"estimate":20373.914819849877,"lower_bound":2334.542304790145,"upper_bound":59164.14792204573,"unit":"ns"},"slope":{"estimate":276818.8223544198,"lower_bound":261556.53467161756,"upper_bound":293826.5172427035,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_gt/functional/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_gt_functional_1000000","iteration_count":[342,684,1026,1368,1710,2052,2394,2736,3078,3420],"measured_values":[84402875.0,167655416.0,253123958.0,396237916.0,429906291.0,522129291.0,618522542.0,740009791.0,811947750.0,899579084.0],"unit":"ns","throughput":[],"typical":{"estimate":262773.60946305154,"lower_bound":257518.30693790247,"upper_bound":267364.15001863317,"unit":"ns"},"mean":{"estimate":258977.61212023115,"lower_bound":251683.58370648845,"upper_bound":267689.33061890834,"unit":"ns"},"median":{"estimate":256406.30357142858,"lower_bound":246792.0321637427,"upper_bound":266753.1173611111,"unit":"ns"},"median_abs_dev":{"estimate":12601.10631868328,"lower_bound":1307.8728212250787,"upper_bound":21301.48157854824,"unit":"ns"},"slope":{"estimate":262773.60946305154,"lower_bound":257518.30693790247,"upper_bound":267364.15001863317,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"JSON","benchmarks":["JSON/json/contains/functional/1000000","JSON/json/field_eq/bare/1000000","JSON/json/field_eq/extractor/1000000","JSON/json/field_eq/functional/1000000","JSON/json/field_order/functional/1000000","JSON/json/field_gt/functional/1000000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON"} diff --git a/results/query/v3/json_rows_10000000.json b/results/query/v3/json_rows_10000000.json new file mode 100644 index 0000000..4071f10 --- /dev/null +++ b/results/query/v3/json_rows_10000000.json @@ -0,0 +1,7 @@ +{"reason":"benchmark-complete","id":"JSON/json/contains/functional/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_contains_functional_10000000","iteration_count":[82,164,246,328,410,492,574,656,738,820],"measured_values":[84166166.0,188932750.0,265148542.0,357404083.0,457701166.0,500997417.0,604056417.0,681595500.0,750687791.0,803561750.0],"unit":"ns","throughput":[],"typical":{"estimate":1028018.7042762116,"lower_bound":1003702.487833846,"upper_bound":1065742.659126672,"unit":"ns"},"mean":{"estimate":1056908.9667024778,"lower_bound":1027427.3491047715,"upper_bound":1088431.4968433506,"unit":"ns"},"median":{"estimate":1045690.3131533101,"lower_bound":1018287.4329268293,"upper_bound":1097091.9544715448,"unit":"ns"},"median_abs_dev":{"estimate":44957.97086240551,"lower_bound":7650.092816419514,"upper_bound":85865.87646789331,"unit":"ns"},"slope":{"estimate":1028018.7042762116,"lower_bound":1003702.487833846,"upper_bound":1065742.659126672,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_eq/bare/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_eq_bare_10000000","iteration_count":[957,1914,2871,3828,4785,5742,6699,7656,8613,9570],"measured_values":[96859834.0,159953875.0,282041917.0,366613333.0,422892125.0,556736542.0,646564750.0,713250125.0,946966875.0,976998417.0],"unit":"ns","throughput":[],"typical":{"estimate":99631.8767767238,"lower_bound":93545.15966562173,"upper_bound":104474.55583986422,"unit":"ns"},"mean":{"estimate":96584.42712631237,"lower_bound":92229.37770289098,"upper_bound":100842.88354612938,"unit":"ns"},"median":{"estimate":96737.62618798827,"lower_bound":92075.10880355276,"upper_bound":101211.94775339603,"unit":"ns"},"median_abs_dev":{"estimate":5967.246745039816,"lower_bound":948.5453610073863,"upper_bound":12608.980813998493,"unit":"ns"},"slope":{"estimate":99631.8767767238,"lower_bound":93545.15966562173,"upper_bound":104474.55583986422,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_eq/extractor/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_eq_extractor_10000000","iteration_count":[143,286,429,572,715,858,1001,1144,1287,1430],"measured_values":[83382583.0,195244458.0,265768250.0,355616041.0,461989875.0,540218875.0,648361916.0,703937291.0,837498750.0,950654417.0],"unit":"ns","throughput":[],"typical":{"estimate":644064.4391608392,"lower_bound":626489.433362666,"upper_bound":656285.5512721309,"unit":"ns"},"mean":{"estimate":636132.058518981,"lower_bound":619416.0031885407,"upper_bound":652554.5644900723,"unit":"ns"},"median":{"estimate":637882.706876457,"lower_bound":618518.0826048951,"upper_bound":656253.7501998001,"unit":"ns"},"median_abs_dev":{"estimate":25613.87017760571,"lower_bound":3408.1223695636536,"upper_bound":47902.22381040464,"unit":"ns"},"slope":{"estimate":644064.4391608392,"lower_bound":626489.433362666,"upper_bound":656285.5512721309,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_eq/functional/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_eq_functional_10000000","iteration_count":[917,1834,2751,3668,4585,5502,6419,7336,8253,9170],"measured_values":[89138541.0,194530416.0,263364417.0,348056750.0,453194625.0,522512791.0,631869542.0,693574625.0,799338000.0,896162250.0],"unit":"ns","throughput":[],"typical":{"estimate":96840.11326884675,"lower_bound":95606.16536975768,"upper_bound":97901.07712801742,"unit":"ns"},"mean":{"estimate":97527.36418250506,"lower_bound":95875.12081778704,"upper_bound":99747.07469788584,"unit":"ns"},"median":{"estimate":97030.46583060705,"lower_bound":94967.79189385677,"upper_bound":98437.37996572675,"unit":"ns"},"median_abs_dev":{"estimate":2386.4912956902,"lower_bound":371.79363929628084,"upper_bound":4077.3523299980084,"unit":"ns"},"slope":{"estimate":96840.11326884675,"lower_bound":95606.16536975768,"upper_bound":97901.07712801742,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_order/functional/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_order_functional_10000000","iteration_count":[291,582,873,1164,1455,1746,2037,2328,2619,2910],"measured_values":[107749750.0,211692250.0,325178875.0,394209083.0,485165250.0,518364458.0,633938250.0,729381292.0,1027653500.0,991082541.0],"unit":"ns","throughput":[],"typical":{"estimate":339642.4795911992,"lower_bound":314896.72466025065,"upper_bound":366271.8741549828,"unit":"ns"},"mean":{"estimate":343297.4142205313,"lower_bound":325213.625203731,"upper_bound":361539.32502672775,"unit":"ns"},"median":{"estimate":339622.89493127144,"lower_bound":313308.1151202749,"upper_bound":370274.05498281785,"unit":"ns"},"median_abs_dev":{"estimate":40568.35813322123,"lower_bound":5286.421896971976,"upper_bound":53862.46565045118,"unit":"ns"},"slope":{"estimate":339642.4795911992,"lower_bound":314896.72466025065,"upper_bound":366271.8741549828,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"JSON/json/field_gt/functional/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON/json_field_gt_functional_10000000","iteration_count":[233,466,699,932,1165,1398,1631,1864,2097,2330],"measured_values":[97268500.0,172727917.0,271257042.0,353188167.0,480522250.0,528089667.0,639333750.0,719453417.0,811597625.0,972968041.0],"unit":"ns","throughput":[],"typical":{"estimate":395802.0177359122,"lower_bound":384470.3772551609,"upper_bound":407928.16077659203,"unit":"ns"},"mean":{"estimate":392792.8312107432,"lower_bound":383277.647775734,"upper_bound":403164.3037531294,"unit":"ns"},"median":{"estimate":387546.1971864569,"lower_bound":378957.2607296137,"upper_bound":412465.4506437768,"unit":"ns"},"median_abs_dev":{"estimate":13631.462062320863,"lower_bound":1550.4842018189229,"upper_bound":27045.909658197495,"unit":"ns"},"slope":{"estimate":395802.0177359122,"lower_bound":384470.3772551609,"upper_bound":407928.16077659203,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"JSON","benchmarks":["JSON/json/contains/functional/10000000","JSON/json/field_eq/bare/10000000","JSON/json/field_eq/extractor/10000000","JSON/json/field_eq/functional/10000000","JSON/json/field_order/functional/10000000","JSON/json/field_gt/functional/10000000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/JSON"} diff --git a/results/query/v3/match_metadata_10000.json b/results/query/v3/match_metadata_10000.json new file mode 100644 index 0000000..4c20c0f --- /dev/null +++ b/results/query/v3/match_metadata_10000.json @@ -0,0 +1,485 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 649, + "Plans": [ + { + "Alias": "string_encrypted_v3_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 649, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbMCHrS1~w;M;JIX$Z1@!3Db6&P7}cvVmd|7A998N!x%-FoK9K{3Q2oR3{jJqZ1`ZahL+C>^;yuL!X7naxfl1#8xZ7DGP_rFLO#b!Eg5 (eql_v3_internal.bloom_filter((('{\"c\": \"mBbMCHrS1~w;M;JIX$Z1@!3Db6&P7}cvVmd|7A998N!x%-FoK9K{3Q2oR3{jJqZ1`ZahL+C>^;yuL!X7naxfl1#8xZ7DGP_rFLO#b!Eg5^;yuL!X7naxfl1#8xZ7DGP_rFLO#b!Eg5 $1 LIMIT 10", + "rows_returned": 4 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 649, + "Plans": [ + { + "Alias": "string_encrypted_v3_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 649, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK@RHT_YQgengq0NT#Vn-ds8Nco=9U0`fwxj!r22fFSMo^acQ=8LbIMKu){Zb2|wb~7RQV8hZEg-4Ab(Ns{<6e>NueN@ETJDB{rFLO#b!Eg5 (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK@RHT_YQgengq0NT#Vn-ds8Nco=9U0`fwxj!r22fFSMo^acQ=8LbIMKu){Zb2|wb~7RQV8hZEg-4Ab(Ns{<6e>NueN@ETJDB{rFLO#b!Eg5NueN@ETJDB{rFLO#b!Eg5 $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 649, + "Plans": [ + { + "Alias": "string_encrypted_v3_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 649, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK6geIMV!9#{o-M(hFFN~VR8PwMuWMt~Cw`xiU (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK6geIMV!9#{o-M(hFFN~VR8PwMuWMt~Cw`xiU eql_v3.match_term($1::eql_v3.text_search) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 649, + "Plans": [ + { + "Alias": "string_encrypted_v3_10000", + "Async Capable": false, + "Filter": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbMCHrS1~w;M;JIX$Z1@!3Db6&P7}cvVmd|7A998N!x%-FoK9K{3Q2oR3{jJqZ1`ZahL+C>^;yuL!X7naxfl1#8xZ7DGP_rFLO#b!Eg5^;yuL!X7naxfl1#8xZ7DGP_rFLO#b!Eg5 $1 LIMIT 10", + "rows_returned": 4 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 649, + "Plans": [ + { + "Alias": "string_encrypted_v3_10000", + "Async Capable": false, + "Filter": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK@RHT_YQgengq0NT#Vn-ds8Nco=9U0`fwxj!r22fFSMo^acQ=8LbIMKu){Zb2|wb~7RQV8hZEg-4Ab(Ns{<6e>NueN@ETJDB{rFLO#b!Eg5NueN@ETJDB{rFLO#b!Eg5 $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 649, + "Plans": [ + { + "Alias": "string_encrypted_v3_10000", + "Async Capable": false, + "Filter": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK6geIMV!9#{o-M(hFFN~VR8PwMuWMt~Cw`xiU eql_v3.match_term($1::eql_v3.text_search) LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "10000" +} \ No newline at end of file diff --git a/results/query/v3/match_metadata_100000.json b/results/query/v3/match_metadata_100000.json new file mode 100644 index 0000000..261648c --- /dev/null +++ b/results/query/v3/match_metadata_100000.json @@ -0,0 +1,269 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 635, + "Plans": [ + { + "Alias": "string_encrypted_v3_100000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 635, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbMLz~2cP@FT7`S21vuMQ&ci6~9jRjYwz<^4*v?e~*vfjs2_eCcMNTm06{}Y6Vr$M4t10C_aUbyg1XU@>B70@|IMkxe?&2rFLO#b!Eg5 (eql_v3_internal.bloom_filter((('{\"c\": \"mBbMLz~2cP@FT7`S21vuMQ&ci6~9jRjYwz<^4*v?e~*vfjs2_eCcMNTm06{}Y6Vr$M4t10C_aUbyg1XU@>B70@|IMkxe?&2rFLO#b!Eg5B70@|IMkxe?&2rFLO#b!Eg5 $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 635, + "Plans": [ + { + "Alias": "string_encrypted_v3_100000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 635, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK3c9YZ~YabiHj6ChG6PoPA86?R^#FT36G&YMDin={;E^5p$n{Rny;MEEKCbRP=$(U^*rFLO#b!Eg5 (eql_v3_internal.bloom_filter((('{\"c\": \"mBbK3c9YZ~YabiHj6ChG6PoPA86?R^#FT36G&YMDin={;E^5p$n{Rny;MEEKCbRP=$(U^*rFLO#b!Eg5{Rny;MEEKCbRP=$(U^*rFLO#b!Eg5 $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 635, + "Plans": [ + { + "Alias": "string_encrypted_v3_100000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 635, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLE9E2f5{Z(7DX-`9~7F5*48R1ytR5Agx`ktr4Az!6uI~#kR6qwhp?$E>_AXr6YO@n@(5^dBRDN3J$dKi~^RA5Rx1Ea!IRTW-rrFLO#b!Eg5 (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLE9E2f5{Z(7DX-`9~7F5*48R1ytR5Agx`ktr4Az!6uI~#kR6qwhp?$E>_AXr6YO@n@(5^dBRDN3J$dKi~^RA5Rx1Ea!IRTW-rrFLO#b!Eg5_AXr6YO@n@(5^dBRDN3J$dKi~^RA5Rx1Ea!IRTW-rrFLO#b!Eg5 eql_v3.match_term($1::eql_v3.text_search) LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "100000" +} \ No newline at end of file diff --git a/results/query/v3/match_metadata_1000000.json b/results/query/v3/match_metadata_1000000.json new file mode 100644 index 0000000..23f207e --- /dev/null +++ b/results/query/v3/match_metadata_1000000.json @@ -0,0 +1,269 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 640, + "Plans": [ + { + "Alias": "string_encrypted_v3_1000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 640, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJ_X{{~BP#>&#D7Y>RXZF*?6>C%&G83QGc|dYrvBqP`>Ll5pn|H(@aXk=W91Dul)AD0BwsiOFUeqs<(o@qL45|qKKu{3mrFLO#b!Eg5 (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJ_X{{~BP#>&#D7Y>RXZF*?6>C%&G83QGc|dYrvBqP`>Ll5pn|H(@aXk=W91Dul)AD0BwsiOFUeqs<(o@qL45|qKKu{3mrFLO#b!Eg5&#D7Y>RXZF*?6>C%&G83QGc|dYrvBqP`>Ll5pn|H(@aXk=W91Dul)AD0BwsiOFUeqs<(o@qL45|qKKu{3mrFLO#b!Eg5 $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 640, + "Plans": [ + { + "Alias": "string_encrypted_v3_1000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 640, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJprUR4NIxndC;^h8FmqQK286&V4b (eql_v3_internal.bloom_filter((('{\"c\": \"mBbJprUR4NIxndC;^h8FmqQK286&V4b $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 640, + "Plans": [ + { + "Alias": "string_encrypted_v3_1000000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 640, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "((eql_v3_internal.bloom_filter((value)::jsonb))::smallint[] @> (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLtxJ*y)8G7e;FlzQ)wP)Pb4ESN&ek;C_ScK0!jl9Gl%f}S5o@rpaMNn4jp{G`01PtKKvz);2c!lu5IuJhKrFLO#b!Eg5 (eql_v3_internal.bloom_filter((('{\"c\": \"mBbLtxJ*y)8G7e;FlzQ)wP)Pb4ESN&ek;C_ScK0!jl9Gl%f}S5o@rpaMNn4jp{G`01PtKKvz);2c!lu5IuJhKrFLO#b!Eg5*y)8G7e;FlzQ)wP)Pb4ESN&ek;C_ScK0!jl9Gl%f}S5o@rpaMNn4jp{G`01PtKKvz);2c!lu5IuJhKrFLO#b!Eg5 eql_v3.match_term($1::eql_v3.text_search) LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "1000000" +} \ No newline at end of file diff --git a/results/query/v3/match_rows_10000.json b/results/query/v3/match_rows_10000.json new file mode 100644 index 0000000..55c1b36 --- /dev/null +++ b/results/query/v3/match_rows_10000.json @@ -0,0 +1,10 @@ +{"reason":"benchmark-complete","id":"MATCH/match/eql_cast_firstname/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_eql_cast_firstname_10000","iteration_count":[432,864,1296,1728,2160,2592,3024,3456,3888,4320],"measured_values":[81945083.0,161741292.0,264833667.0,368400375.0,388868041.0,460793250.0,620009042.0,663958667.0,719627208.0,822719833.0],"unit":"ns","throughput":[],"typical":{"estimate":190826.15262746514,"lower_bound":185430.95818166537,"upper_bound":197691.14729019997,"unit":"ns"},"mean":{"estimate":192491.73855957895,"lower_bound":186004.22650462962,"upper_bound":199448.88848379627,"unit":"ns"},"median":{"estimate":190066.04895833333,"lower_bound":183616.0349537037,"upper_bound":204346.96527777778,"unit":"ns"},"median_abs_dev":{"estimate":11127.872774500936,"lower_bound":1801.3424517871463,"upper_bound":19269.420067795254,"unit":"ns"},"slope":{"estimate":190826.15262746514,"lower_bound":185430.95818166537,"upper_bound":197691.14729019997,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match_decrypt/eql_cast_firstname/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_decrypt_eql_cast_firstname_10000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[109394292.0,199292875.0,305897958.0,401360125.0,490700875.0,591757083.0,721786083.0,780091708.0,905163875.0,1021326583.0],"unit":"ns","throughput":[],"typical":{"estimate":25122167.687662337,"lower_bound":24680182.671251938,"upper_bound":25463283.91193584,"unit":"ns"},"mean":{"estimate":25286082.137757935,"lower_bound":24844822.37940972,"upper_bound":25842481.16623016,"unit":"ns"},"median":{"estimate":25114224.392361112,"lower_bound":24656545.125,"upper_bound":25634785.44642857,"unit":"ns"},"median_abs_dev":{"estimate":649837.986748069,"lower_bound":171856.75996976718,"upper_bound":1160023.2638138048,"unit":"ns"},"slope":{"estimate":25122167.687662337,"lower_bound":24680182.671251938,"upper_bound":25463283.91193584,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match/eql_cast_lastname/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_eql_cast_lastname_10000","iteration_count":[189,378,567,756,945,1134,1323,1512,1701,1890],"measured_values":[89127750.0,175665417.0,257260625.0,392732625.0,450002458.0,581233083.0,657773584.0,797285000.0,937414250.0,1156567125.0],"unit":"ns","throughput":[],"typical":{"estimate":542921.4091252662,"lower_bound":499411.7898027898,"upper_bound":577232.9588997702,"unit":"ns"},"mean":{"estimate":508577.7564882003,"lower_bound":483023.24596119934,"upper_bound":538643.8095767195,"unit":"ns"},"median":{"estimate":504867.2893046107,"lower_bound":470458.20132275135,"upper_bound":535291.7860817167,"unit":"ns"},"median_abs_dev":{"estimate":45935.47247638705,"lower_bound":10158.880919643798,"upper_bound":76114.07044870518,"unit":"ns"},"slope":{"estimate":542921.4091252662,"lower_bound":499411.7898027898,"upper_bound":577232.9588997702,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match_decrypt/eql_cast_lastname/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_decrypt_eql_cast_lastname_10000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[122409208.0,205485792.0,316737250.0,413229125.0,518700417.0,619520208.0,726225417.0,830173583.0,953289125.0,1047771541.0],"unit":"ns","throughput":[],"typical":{"estimate":26122997.722727273,"lower_bound":25921171.995002545,"upper_bound":26303509.21437555,"unit":"ns"},"mean":{"estimate":26481206.849751987,"lower_bound":25906316.36284722,"upper_bound":27446992.72435863,"unit":"ns"},"median":{"estimate":25939773.25223214,"lower_bound":25826820.3125,"upper_bound":26394770.833333332,"unit":"ns"},"median_abs_dev":{"estimate":282050.1929519815,"lower_bound":7045.911424281279,"upper_bound":675766.360713371,"unit":"ns"},"slope":{"estimate":26122997.722727273,"lower_bound":25921171.995002545,"upper_bound":26303509.21437555,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match/eql_bloom/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_eql_bloom_10000","iteration_count":[192,384,576,768,960,1152,1344,1536,1728,1920],"measured_values":[83986875.0,161635375.0,248326833.0,415916625.0,417875916.0,543792667.0,582723625.0,693618584.0,795172750.0,818916500.0],"unit":"ns","throughput":[],"typical":{"estimate":448346.50978084415,"lower_bound":434499.8167522352,"upper_bound":467188.24999494874,"unit":"ns"},"mean":{"estimate":451020.49845692795,"lower_bound":433812.44332589285,"upper_bound":474483.6386920572,"unit":"ns"},"median":{"estimate":436359.5265625,"lower_bound":430046.56808035716,"upper_bound":461808.42230902775,"unit":"ns"},"median_abs_dev":{"estimate":18573.707456188247,"lower_bound":2859.5757304823724,"upper_bound":39430.175905877215,"unit":"ns"},"slope":{"estimate":448346.50978084415,"lower_bound":434499.8167522352,"upper_bound":467188.24999494874,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match_decrypt/eql_bloom/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_decrypt_eql_bloom_10000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[101535833.0,225611791.0,323873458.0,408516458.0,517539166.0,629200083.0,719958292.0,813962375.0,958938458.0,1043606875.0],"unit":"ns","throughput":[],"typical":{"estimate":26064457.055194806,"lower_bound":25715513.091274254,"upper_bound":26407763.376185898,"unit":"ns"},"mean":{"estimate":26207726.563382935,"lower_bound":25748844.977321427,"upper_bound":26764379.089708336,"unit":"ns"},"median":{"estimate":25983565.0875,"lower_bound":25532278.625,"upper_bound":26637179.388888888,"unit":"ns"},"median_abs_dev":{"estimate":740208.2975142986,"lower_bound":148768.78398070112,"upper_bound":1273029.1090798408,"unit":"ns"},"slope":{"estimate":26064457.055194806,"lower_bound":25715513.091274254,"upper_bound":26407763.376185898,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match/eql_cast_firstname_noindex/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_eql_cast_firstname_noindex_10000","iteration_count":[3,3,3,3,3,3,3,3,3,3],"measured_values":[579475417.0,555946791.0,561540208.0,559010083.0,555048250.0,565362959.0,560923708.0,558342166.0,583607625.0,584543208.0],"unit":"ns","throughput":[],"typical":{"estimate":188793347.1666667,"lower_bound":186669529.2675,"upper_bound":191185318.765,"unit":"ns"},"mean":{"estimate":188793347.1666667,"lower_bound":186669529.2675,"upper_bound":191185318.765,"unit":"ns"},"median":{"estimate":187077319.33333334,"lower_bound":185826145.6666667,"upper_bound":193158472.33333334,"unit":"ns"},"median_abs_dev":{"estimate":2326735.0714921877,"lower_bound":462365.1103913784,"upper_bound":5991690.577626228,"unit":"ns"},"slope":null,"change":null} +{"reason":"benchmark-complete","id":"MATCH/match/eql_cast_lastname_noindex/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_eql_cast_lastname_noindex_10000","iteration_count":[2,4,6,8,10,12,14,16,18,20],"measured_values":[108612958.0,216444166.0,343550542.0,436763500.0,553571042.0,639855166.0,769527083.0,965299667.0,1013941666.0,1107650542.0],"unit":"ns","throughput":[],"typical":{"estimate":56152286.3025974,"lower_bound":54724531.548628606,"upper_bound":57902810.881489284,"unit":"ns"},"mean":{"estimate":55595981.87573413,"lower_bound":54555801.51555556,"upper_bound":56885329.278789684,"unit":"ns"},"median":{"estimate":55161662.20714286,"lower_bound":54306479.0,"upper_bound":56330092.55555555,"unit":"ns"},"median_abs_dev":{"estimate":1412772.4165782796,"lower_bound":308608.28890110715,"upper_bound":2771746.05267167,"unit":"ns"},"slope":{"estimate":56152286.3025974,"lower_bound":54724531.548628606,"upper_bound":57902810.881489284,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match/eql_bloom_noindex/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_eql_bloom_noindex_10000","iteration_count":[2,4,6,8,10,12,14,16,18,20],"measured_values":[111157250.0,220770834.0,332760417.0,457152292.0,553315292.0,702236833.0,917867000.0,926327125.0,1040215459.0,1128889875.0],"unit":"ns","throughput":[],"typical":{"estimate":58241702.176623374,"lower_bound":56624041.991365604,"upper_bound":60915022.231773436,"unit":"ns"},"mean":{"estimate":57491832.01394842,"lower_bound":56041560.55136806,"upper_bound":59552334.79470636,"unit":"ns"},"median":{"estimate":56794265.125,"lower_bound":55455077.1,"upper_bound":58154741.902777776,"unit":"ns"},"median_abs_dev":{"estimate":1890193.2079173625,"lower_bound":190573.8453966335,"upper_bound":3366095.680356525,"unit":"ns"},"slope":{"estimate":58241702.176623374,"lower_bound":56624041.991365604,"upper_bound":60915022.231773436,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"MATCH","benchmarks":["MATCH/match/eql_cast_firstname/10000","MATCH/match_decrypt/eql_cast_firstname/10000","MATCH/match/eql_cast_lastname/10000","MATCH/match_decrypt/eql_cast_lastname/10000","MATCH/match/eql_bloom/10000","MATCH/match_decrypt/eql_bloom/10000","MATCH/match/eql_cast_firstname_noindex/10000","MATCH/match/eql_cast_lastname_noindex/10000","MATCH/match/eql_bloom_noindex/10000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH"} diff --git a/results/query/v3/match_rows_100000.json b/results/query/v3/match_rows_100000.json new file mode 100644 index 0000000..411210c --- /dev/null +++ b/results/query/v3/match_rows_100000.json @@ -0,0 +1,7 @@ +{"reason":"benchmark-complete","id":"MATCH/match/eql_cast_firstname/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_eql_cast_firstname_100000","iteration_count":[149,298,447,596,745,894,1043,1192,1341,1490],"measured_values":[103030416.0,213555708.0,267571583.0,355241750.0,478057375.0,603744583.0,677277250.0,765567625.0,803964166.0,983910750.0],"unit":"ns","throughput":[],"typical":{"estimate":639882.2400069729,"lower_bound":617035.963533983,"upper_bound":657994.2211067296,"unit":"ns"},"mean":{"estimate":647124.2148276872,"lower_bound":623380.0323594132,"upper_bound":671314.3073985298,"unit":"ns"},"median":{"estimate":645804.8522890699,"lower_bound":599525.850857569,"upper_bound":675911.043624161,"unit":"ns"},"median_abs_dev":{"estimate":55745.098231048316,"lower_bound":3272.3587854163857,"upper_bound":72341.60417373345,"unit":"ns"},"slope":{"estimate":639882.2400069729,"lower_bound":617035.963533983,"upper_bound":657994.2211067296,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match_decrypt/eql_cast_firstname/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_decrypt_eql_cast_firstname_100000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[108453959.0,213945500.0,329517625.0,443948834.0,509308750.0,639567166.0,755561625.0,851846958.0,974109416.0,1046039916.0],"unit":"ns","throughput":[],"typical":{"estimate":26633591.466883115,"lower_bound":26283156.657210402,"upper_bound":27018950.01686508,"unit":"ns"},"mean":{"estimate":26799150.485138886,"lower_bound":26397352.644961808,"upper_bound":27161844.27258334,"unit":"ns"},"median":{"estimate":26863765.625,"lower_bound":26399814.90833333,"upper_bound":27259198.486111112,"unit":"ns"},"median_abs_dev":{"estimate":365662.75876443833,"lower_bound":91157.70571287721,"upper_bound":1056749.4103239498,"unit":"ns"},"slope":{"estimate":26633591.466883115,"lower_bound":26283156.657210402,"upper_bound":27018950.01686508,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match/eql_cast_lastname/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_eql_cast_lastname_100000","iteration_count":[47,94,141,188,235,282,329,376,423,470],"measured_values":[115294709.0,176882916.0,263984791.0,349662958.0,487880708.0,523066916.0,716738334.0,811221458.0,880779583.0,900044541.0],"unit":"ns","throughput":[],"typical":{"estimate":2026630.1984526112,"lower_bound":1932789.7431359363,"upper_bound":2115560.365236685,"unit":"ns"},"mean":{"estimate":2033113.878296184,"lower_bound":1927348.4407548127,"upper_bound":2154381.4635089496,"unit":"ns"},"median":{"estimate":1995538.2521276595,"lower_bound":1870821.25,"upper_bound":2157503.8776595746,"unit":"ns"},"median_abs_dev":{"estimate":191948.21031479115,"lower_bound":15591.089482245347,"upper_bound":360093.4404196522,"unit":"ns"},"slope":{"estimate":2026630.1984526112,"lower_bound":1932789.7431359363,"upper_bound":2115560.365236685,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match_decrypt/eql_cast_lastname/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_decrypt_eql_cast_lastname_100000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[113522125.0,213167833.0,341475833.0,449450542.0,546431917.0,647992584.0,736900416.0,886045416.0,1001020708.0,1073203500.0],"unit":"ns","throughput":[],"typical":{"estimate":27253305.29805195,"lower_bound":26836652.247619048,"upper_bound":27712837.62218834,"unit":"ns"},"mean":{"estimate":27453778.504444443,"lower_bound":27012494.003541667,"upper_bound":27887470.918333333,"unit":"ns"},"median":{"estimate":27505257.55,"lower_bound":26822835.0625,"upper_bound":28093331.013888888,"unit":"ns"},"median_abs_dev":{"estimate":934461.5436974913,"lower_bound":251454.14463579655,"upper_bound":1259583.1158254296,"unit":"ns"},"slope":{"estimate":27253305.29805195,"lower_bound":26836652.247619048,"upper_bound":27712837.62218834,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match/eql_bloom/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_eql_bloom_100000","iteration_count":[45,90,135,180,225,270,315,360,405,450],"measured_values":[85264417.0,166921792.0,251321000.0,368983542.0,421386250.0,539050750.0,652496666.0,708396333.0,788256417.0,854888875.0],"unit":"ns","throughput":[],"typical":{"estimate":1954867.8065223666,"lower_bound":1915902.5428707355,"upper_bound":2007243.3549536383,"unit":"ns"},"mean":{"estimate":1941555.981600529,"lower_bound":1897518.8532407407,"upper_bound":1988741.8362566135,"unit":"ns"},"median":{"estimate":1923032.598148148,"lower_bound":1872827.7777777778,"upper_bound":2008838.0791666666,"unit":"ns"},"median_abs_dev":{"estimate":82729.36132348228,"lower_bound":16591.39192766603,"upper_bound":132344.40078708364,"unit":"ns"},"slope":{"estimate":1954867.8065223666,"lower_bound":1915902.5428707355,"upper_bound":2007243.3549536383,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match_decrypt/eql_bloom/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_decrypt_eql_bloom_100000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[104108291.0,209013958.0,322892625.0,425400541.0,539605333.0,664189333.0,809720375.0,903372083.0,986159250.0,1094164541.0],"unit":"ns","throughput":[],"typical":{"estimate":27654335.622077923,"lower_bound":27224402.625718653,"upper_bound":28144385.250165507,"unit":"ns"},"mean":{"estimate":27220028.069434524,"lower_bound":26712663.39692708,"upper_bound":27765644.76127902,"unit":"ns"},"median":{"estimate":27167190.0875,"lower_bound":26517231.75,"upper_bound":27811845.046875,"unit":"ns"},"median_abs_dev":{"estimate":805809.193525278,"lower_bound":237543.662737759,"upper_bound":1559422.9993865825,"unit":"ns"},"slope":{"estimate":27654335.622077923,"lower_bound":27224402.625718653,"upper_bound":28144385.250165507,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"MATCH","benchmarks":["MATCH/match/eql_cast_firstname/100000","MATCH/match_decrypt/eql_cast_firstname/100000","MATCH/match/eql_cast_lastname/100000","MATCH/match_decrypt/eql_cast_lastname/100000","MATCH/match/eql_bloom/100000","MATCH/match_decrypt/eql_bloom/100000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH"} diff --git a/results/query/v3/match_rows_1000000.json b/results/query/v3/match_rows_1000000.json new file mode 100644 index 0000000..5dca032 --- /dev/null +++ b/results/query/v3/match_rows_1000000.json @@ -0,0 +1,7 @@ +{"reason":"benchmark-complete","id":"MATCH/match/eql_cast_firstname/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_eql_cast_firstname_1000000","iteration_count":[28,56,84,112,140,168,196,224,252,280],"measured_values":[89289875.0,199581375.0,273609958.0,365806458.0,476876250.0,539404333.0,652525292.0,715644125.0,822167542.0,921565709.0],"unit":"ns","throughput":[],"typical":{"estimate":3274704.1364564006,"lower_bound":3235474.145512474,"upper_bound":3318034.5854533594,"unit":"ns"},"mean":{"estimate":3297119.2964044786,"lower_bound":3238296.8025694443,"upper_bound":3371023.7319434523,"unit":"ns"},"median":{"estimate":3264349.3501984123,"lower_bound":3210740.0773809524,"upper_bound":3348782.5160714285,"unit":"ns"},"median_abs_dev":{"estimate":87822.2513212006,"lower_bound":7869.946593613567,"upper_bound":156724.9647957007,"unit":"ns"},"slope":{"estimate":3274704.1364564006,"lower_bound":3235474.145512474,"upper_bound":3318034.5854533594,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match_decrypt/eql_cast_firstname/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_decrypt_eql_cast_firstname_1000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[108635084.0,220344583.0,343539333.0,486541167.0,577875958.0,743354916.0,819950333.0,916737083.0,1085228084.0,1203631500.0],"unit":"ns","throughput":[],"typical":{"estimate":29709436.983116884,"lower_bound":29077667.86555374,"upper_bound":30174916.57350849,"unit":"ns"},"mean":{"estimate":29177385.032609127,"lower_bound":28432514.60135913,"upper_bound":29895425.99965278,"unit":"ns"},"median":{"estimate":29088869.182142854,"lower_bound":28095553.359375,"upper_bound":30249805.21875,"unit":"ns"},"median_abs_dev":{"estimate":1525798.2602500047,"lower_bound":196830.08370056638,"upper_bound":2173503.792862594,"unit":"ns"},"slope":{"estimate":29709436.983116884,"lower_bound":29077667.86555374,"upper_bound":30174916.57350849,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match/eql_cast_lastname/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_eql_cast_lastname_1000000","iteration_count":[6,12,18,24,30,36,42,48,54,60],"measured_values":[93271708.0,185014208.0,276302917.0,395681500.0,500847958.0,585698917.0,655363792.0,754663666.0,851967625.0,943922833.0],"unit":"ns","throughput":[],"typical":{"estimate":15855048.04935065,"lower_bound":15711733.715107428,"upper_bound":16121333.552053487,"unit":"ns"},"mean":{"estimate":15859965.782526454,"lower_bound":15606505.757275134,"upper_bound":16143679.188216269,"unit":"ns"},"median":{"estimate":15727103.4625,"lower_bound":15510875.238095239,"upper_bound":16269414.361111112,"unit":"ns"},"median_abs_dev":{"estimate":364031.3644396528,"lower_bound":48114.84714690094,"upper_bound":705222.4052572992,"unit":"ns"},"slope":{"estimate":15855048.04935065,"lower_bound":15711733.715107428,"upper_bound":16121333.552053487,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match_decrypt/eql_cast_lastname/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_decrypt_eql_cast_lastname_1000000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[110566542.0,231488959.0,344749000.0,460394667.0,583902541.0,680506917.0,816019417.0,962108250.0,1013929542.0,1142017375.0],"unit":"ns","throughput":[],"typical":{"estimate":38447156.607792206,"lower_bound":37871507.02437696,"upper_bound":39261932.782204516,"unit":"ns"},"mean":{"estimate":38340755.28206349,"lower_bound":37838794.05111112,"upper_bound":38869161.391333334,"unit":"ns"},"median":{"estimate":38335833.347222224,"lower_bound":37805939.833333336,"upper_bound":38858067.47619048,"unit":"ns"},"median_abs_dev":{"estimate":779942.207803257,"lower_bound":204634.9141503331,"upper_bound":1497869.209032504,"unit":"ns"},"slope":{"estimate":38447156.607792206,"lower_bound":37871507.02437696,"upper_bound":39261932.782204516,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match/eql_bloom/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_eql_bloom_1000000","iteration_count":[6,12,18,24,30,36,42,48,54,60],"measured_values":[93427833.0,187855416.0,280529333.0,407327167.0,465681542.0,608218291.0,647600667.0,756364875.0,855069000.0,953049875.0],"unit":"ns","throughput":[],"typical":{"estimate":15899565.457575757,"lower_bound":15667357.745939676,"upper_bound":16231995.407344632,"unit":"ns"},"mean":{"estimate":15909596.30875,"lower_bound":15617053.179999998,"upper_bound":16273297.74652778,"unit":"ns"},"median":{"estimate":15706109.78125,"lower_bound":15553840.505555555,"upper_bound":16364781.819444444,"unit":"ns"},"median_abs_dev":{"estimate":231922.4343575542,"lower_bound":56266.39046440479,"upper_bound":786031.078220157,"unit":"ns"},"slope":{"estimate":15899565.457575757,"lower_bound":15667357.745939676,"upper_bound":16231995.407344632,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"MATCH/match_decrypt/eql_bloom/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH/match_decrypt_eql_bloom_1000000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[117844334.0,224891083.0,332293333.0,466637833.0,564028375.0,751284583.0,790022250.0,925506000.0,1016486709.0,1168179625.0],"unit":"ns","throughput":[],"typical":{"estimate":38548300.93939394,"lower_bound":37786977.03525641,"upper_bound":39482241.32660581,"unit":"ns"},"mean":{"estimate":38468101.728174604,"lower_bound":37745166.83650794,"upper_bound":39358794.47261904,"unit":"ns"},"median":{"estimate":38105202.94444445,"lower_bound":37550977.1547619,"upper_bound":39083965.375,"unit":"ns"},"median_abs_dev":{"estimate":1041258.8104389645,"lower_bound":39166.39947965741,"upper_bound":1993528.6346077994,"unit":"ns"},"slope":{"estimate":38548300.93939394,"lower_bound":37786977.03525641,"upper_bound":39482241.32660581,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"MATCH","benchmarks":["MATCH/match/eql_cast_firstname/1000000","MATCH/match_decrypt/eql_cast_firstname/1000000","MATCH/match/eql_cast_lastname/1000000","MATCH/match_decrypt/eql_cast_lastname/1000000","MATCH/match/eql_bloom/1000000","MATCH/match_decrypt/eql_bloom/1000000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/MATCH"} diff --git a/results/query/v3/ope_metadata_10000.json b/results/query/v3/ope_metadata_10000.json new file mode 100644 index 0000000..6522caa --- /dev/null +++ b/results/query/v3/ope_metadata_10000.json @@ -0,0 +1,234 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbKOi_ajD8RR*KEc<~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4900, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000", + "Startup Cost": 0.0, + "Total Cost": 667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.36 + } + } + ], + "id": "OPE/ope/range_gt_10/10000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbKOi_ajD8RR*KEc<~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_10000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_10000 WHERE value > $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbLs&G5#%sfy7<#%LR^)WDR)7I7n!?B?=f;uf!T&BfL$Wmx_~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4900, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000", + "Startup Cost": 0.0, + "Total Cost": 667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.61 + } + } + ], + "id": "OPE/ope/range_gt_100/10000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbLs&G5#%sfy7<#%LR^)WDR)7I7n!?B?=f;uf!T&BfL$Wmx_~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_10000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_10000 WHERE value > $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbK`7(rQMY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5099, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000", + "Startup Cost": 0.0, + "Total Cost": 667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.31 + } + } + ], + "id": "OPE/ope/range_lt_10/10000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbK`7(rQMY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_10000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_10000 WHERE value < $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbLvE10t2Akl*opobYXOeVm@7TEpdcklge_K7Q?YL@CQMc_!rl84X4AWgv~tAx-BN9<(tIQKV1-U7S^~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5099, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000", + "Startup Cost": 0.0, + "Total Cost": 667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.08 + } + } + ], + "id": "OPE/ope/range_lt_100/10000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbLvE10t2Akl*opobYXOeVm@7TEpdcklge_K7Q?YL@CQMc_!rl84X4AWgv~tAx-BN9<(tIQKV1-U7S^~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_10000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_10000 WHERE value < $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 342, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000", + "Async Capable": false, + "Index Cond": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbL#Nr!vV5d4dUCz}Rt{Cm#C7A4r&Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Index Name": "integer_encrypted_ope_v3_10000_ope_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5099, + "Plan Width": 342, + "Relation Name": "integer_encrypted_ope_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.29, + "Total Cost": 1935.0 + } + ], + "Startup Cost": 0.29, + "Total Cost": 4.09 + } + } + ], + "id": "OPE/ope/range_lt_ordered_10/10000", + "indexes_used": [ + "integer_encrypted_ope_v3_10000_ope_index" + ], + "parameters": [ + { + "c": "mBbL#Nr!vV5d4dUCz}Rt{Cm#C7A4r&Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_10000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_10000 WHERE value < $1 ORDER BY eql_v3.ord_ope_term(value) LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "10000" +} \ No newline at end of file diff --git a/results/query/v3/ope_metadata_100000.json b/results/query/v3/ope_metadata_100000.json new file mode 100644 index 0000000..13c2d62 --- /dev/null +++ b/results/query/v3/ope_metadata_100000.json @@ -0,0 +1,234 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_100000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbJ}&XUD-x*pRImY=ziRm6wH7O8AtCGbtfs8RoE%qq?3vU?k$8NbfNAjF`?&j}TIg>yV(L?1L>$PCIfktJsGc%(32jW4JYLZx~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_100000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 49000, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_100000", + "Startup Cost": 0.0, + "Total Cost": 6667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.36 + } + } + ], + "id": "OPE/ope/range_gt_10/100000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbJ}&XUD-x*pRImY=ziRm6wH7O8AtCGbtfs8RoE%qq?3vU?k$8NbfNAjF`?&j}TIg>yV(L?1L>$PCIfktJsGc%(32jW4JYLZx~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_100000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_100000 WHERE value > $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_100000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbJg#7PiKl7cIG3~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_100000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 49000, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_100000", + "Startup Cost": 0.0, + "Total Cost": 6667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.61 + } + } + ], + "id": "OPE/ope/range_gt_100/100000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbJg#7PiKl7cIG3~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_100000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_100000 WHERE value > $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_100000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbLTg=v9e4Yqyi9>ceKXo|DM7E3f^I%tzHtfr1Wua~@>kaKMk~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_100000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50999, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_100000", + "Startup Cost": 0.0, + "Total Cost": 6667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.31 + } + } + ], + "id": "OPE/ope/range_lt_10/100000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbLTg=v9e4Yqyi9>ceKXo|DM7E3f^I%tzHtfr1Wua~@>kaKMk~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_100000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_100000 WHERE value < $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_100000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbJ%R0?+PM(81m9WxGq#ia(s77qsA;%~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_100000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50999, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_100000", + "Startup Cost": 0.0, + "Total Cost": 6667.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.07 + } + } + ], + "id": "OPE/ope/range_lt_100/100000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbJ%R0?+PM(81m9WxGq#ia(s77qsA;%~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_100000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_100000 WHERE value < $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 342, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_100000", + "Async Capable": false, + "Index Cond": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbK7g!PJwK8UTvfXl!6v2XRn7Bj_VXw=|129ohRluho~2X@7`qRY+1ARo+^qDvRPLhyfvLG6yt_g@7}_fTgfr>|yg`HVRVNu_pSY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_100000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Index Name": "integer_encrypted_ope_v3_100000_ope_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50999, + "Plan Width": 342, + "Relation Name": "integer_encrypted_ope_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.42, + "Total Cost": 19293.98 + } + ], + "Startup Cost": 0.42, + "Total Cost": 4.21 + } + } + ], + "id": "OPE/ope/range_lt_ordered_10/100000", + "indexes_used": [ + "integer_encrypted_ope_v3_100000_ope_index" + ], + "parameters": [ + { + "c": "mBbK7g!PJwK8UTvfXl!6v2XRn7Bj_VXw=|129ohRluho~2X@7`qRY+1ARo+^qDvRPLhyfvLG6yt_g@7}_fTgfr>|yg`HVRVNu_pSY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_100000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_100000 WHERE value < $1 ORDER BY eql_v3.ord_ope_term(value) LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "100000" +} \ No newline at end of file diff --git a/results/query/v3/ope_metadata_1000000.json b/results/query/v3/ope_metadata_1000000.json new file mode 100644 index 0000000..51a482c --- /dev/null +++ b/results/query/v3/ope_metadata_1000000.json @@ -0,0 +1,234 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_1000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbK+?~T_j#`TM@qnj*iH=a(!7LZxN6ukdL0nx1oml)*as3z!Jf2qpEAlsgc6z|IH`yBH)%q-Xzec<;TJAyT-&H#&y#-9D5>7{mIY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_1000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 489999, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_1000000", + "Startup Cost": 0.0, + "Total Cost": 66666.93 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.36 + } + } + ], + "id": "OPE/ope/range_gt_10/1000000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbK+?~T_j#`TM@qnj*iH=a(!7LZxN6ukdL0nx1oml)*as3z!Jf2qpEAlsgc6z|IH`yBH)%q-Xzec<;TJAyT-&H#&y#-9D5>7{mIY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_1000000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_1000000 WHERE value > $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_1000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbK^x+*{V9>s0@xqq8!@$@Ie7Hv#zmfs$2NNA)Arr0hEUddlL8e(9?Ai6MMMq+lgn2l=wZ$yw%`=a`HGHb9I67$@@1%pEHLZx~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_1000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 489999, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_1000000", + "Startup Cost": 0.0, + "Total Cost": 66666.93 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.61 + } + } + ], + "id": "OPE/ope/range_gt_100/1000000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbK^x+*{V9>s0@xqq8!@$@Ie7Hv#zmfs$2NNA)Arr0hEUddlL8e(9?Ai6MMMq+lgn2l=wZ$yw%`=a`HGHb9I67$@@1%pEHLZx~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_1000000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_1000000 WHERE value > $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_1000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbLD8ij=<0B8ZygjgKfi6+d%76P1S=XL=`QPQLx;~t`H5PtZ*_i**ZAQ$JwRw%cxS!o=@!`yPKjBvotbFvcM7y~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_1000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 509997, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_1000000", + "Startup Cost": 0.0, + "Total Cost": 66666.93 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.31 + } + } + ], + "id": "OPE/ope/range_lt_10/1000000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbLD8ij=<0B8ZygjgKfi6+d%76P1S=XL=`QPQLx;~t`H5PtZ*_i**ZAQ$JwRw%cxS!o=@!`yPKjBvotbFvcM7y~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_1000000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_1000000 WHERE value < $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_1000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbL*TdMC>F-tFWYV>tK-6fR77Gb5r_O}cXX52nQ{mHERx3mOd5A^TEAfu38=XVTgldQz&@P#7ScrGgG!7$tJGX|G6D(&_RwxxDqY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_1000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 509997, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_1000000", + "Startup Cost": 0.0, + "Total Cost": 66666.93 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.07 + } + } + ], + "id": "OPE/ope/range_lt_100/1000000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbL*TdMC>F-tFWYV>tK-6fR77Gb5r_O}cXX52nQ{mHERx3mOd5A^TEAfu38=XVTgldQz&@P#7ScrGgG!7$tJGX|G6D(&_RwxxDqY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_1000000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_1000000 WHERE value < $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 342, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_1000000", + "Async Capable": false, + "Index Cond": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbKezDw|;`?yAXfWc`e9n|Z@77X~ROK@ra?bIjs@5QIeh?qk&>OD-vAY5O%d`OQ>VG;rYwUr3prv+UY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_1000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Index Name": "integer_encrypted_ope_v3_1000000_ope_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 509997, + "Plan Width": 342, + "Relation Name": "integer_encrypted_ope_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.43, + "Total Cost": 192851.31 + } + ], + "Startup Cost": 0.43, + "Total Cost": 4.21 + } + } + ], + "id": "OPE/ope/range_lt_ordered_10/1000000", + "indexes_used": [ + "integer_encrypted_ope_v3_1000000_ope_index" + ], + "parameters": [ + { + "c": "mBbKezDw|;`?yAXfWc`e9n|Z@77X~ROK@ra?bIjs@5QIeh?qk&>OD-vAY5O%d`OQ>VG;rYwUr3prv+UY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_1000000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_1000000 WHERE value < $1 ORDER BY eql_v3.ord_ope_term(value) LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "1000000" +} \ No newline at end of file diff --git a/results/query/v3/ope_metadata_10000000.json b/results/query/v3/ope_metadata_10000000.json new file mode 100644 index 0000000..b92c497 --- /dev/null +++ b/results/query/v3/ope_metadata_10000000.json @@ -0,0 +1,234 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbJ*D^%CH^pK*8eNzy+PiQd27MH8AXOFm^1`Y~3T6iZaN9zPUOl+XUAdm(#CHXW6rcMcPu2+gn3!Pn*r1z?aTD3E|d|Ja6rKNUZY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4900004, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000000", + "Startup Cost": 0.0, + "Total Cost": 666667.2 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.36 + } + } + ], + "id": "OPE/ope/range_gt_10/10000000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbJ*D^%CH^pK*8eNzy+PiQd27MH8AXOFm^1`Y~3T6iZaN9zPUOl+XUAdm(#CHXW6rcMcPu2+gn3!Pn*r1z?aTD3E|d|Ja6rKNUZY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_10000000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_10000000 WHERE value > $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) > decode(((('{\"c\": \"mBbLe4)1Uyz>(pXT)IoJmmYk?7GN?It1|j3GB}iQ(^@JTi*pzCuQEf#Adnq%>{7!fs*)%11%*B#nrpq4T!4k^0_9J})dwFJ5T$luY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4900004, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000000", + "Startup Cost": 0.0, + "Total Cost": 666667.2 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.61 + } + } + ], + "id": "OPE/ope/range_gt_100/10000000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbLe4)1Uyz>(pXT)IoJmmYk?7GN?It1|j3GB}iQ(^@JTi*pzCuQEf#Adnq%>{7!fs*)%11%*B#nrpq4T!4k^0_9J})dwFJ5T$luY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_10000000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_10000000 WHERE value > $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbJ}KN@m0Vt!q?H|+?q@!Gb;7OHRNfZTiRlhr}j(ldytUg~02ZMfCMAR}Q8>jjQ^*dZ^EXLiGP5&Q3~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5100003, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000000", + "Startup Cost": 0.0, + "Total Cost": 666667.2 + } + ], + "Startup Cost": 0.0, + "Total Cost": 1.31 + } + } + ], + "id": "OPE/ope/range_lt_10/10000000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbJ}KN@m0Vt!q?H|+?q@!Gb;7OHRNfZTiRlhr}j(ldytUg~02ZMfCMAR}Q8>jjQ^*dZ^EXLiGP5&Q3~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_10000000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_10000000 WHERE value < $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 310, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000000", + "Async Capable": false, + "Filter": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbLdM+5GJke|qCGORG`xKKvK7F?Mgu)3q~=x~dENpA(a;icNDTXy8cAYTp~cDv-iprp`767t1j2lop6k1&OJU(wGg2@nCGZKZZ$Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5100003, + "Plan Width": 310, + "Relation Name": "integer_encrypted_ope_v3_10000000", + "Startup Cost": 0.0, + "Total Cost": 666667.2 + } + ], + "Startup Cost": 0.0, + "Total Cost": 13.07 + } + } + ], + "id": "OPE/ope/range_lt_100/10000000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbLdM+5GJke|qCGORG`xKKvK7F?Mgu)3q~=x~dENpA(a;icNDTXy8cAYTp~cDv-iprp`767t1j2lop6k1&OJU(wGg2@nCGZKZZ$Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_10000000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_10000000 WHERE value < $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 342, + "Plans": [ + { + "Alias": "integer_encrypted_ope_v3_10000000", + "Async Capable": false, + "Index Cond": "(decode(((value)::jsonb ->> 'op'::text), 'hex'::text) < decode(((('{\"c\": \"mBbL@j+;gjy@US)2m|md_5%dO7DrC@GK|Q=mXk-9KR0{>9EY9Fq>9MIAP;L)BNx=z^r}7cpPwMkOC9ix!@;H$cp(jY4`+CpVx@LrY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_ope_v3_10000000\"}, \"v\": 3, \"op\": \"00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93\"}'::jsonb)::eql_v3.integer_ord_ope)::jsonb ->> 'op'::text), 'hex'::text))", + "Index Name": "integer_encrypted_ope_v3_10000000_ope_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5100003, + "Plan Width": 342, + "Relation Name": "integer_encrypted_ope_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.57, + "Total Cost": 1928102.41 + } + ], + "Startup Cost": 0.57, + "Total Cost": 4.35 + } + } + ], + "id": "OPE/ope/range_lt_ordered_10/10000000", + "indexes_used": [ + "integer_encrypted_ope_v3_10000000_ope_index" + ], + "parameters": [ + { + "c": "mBbL@j+;gjy@US)2m|md_5%dO7DrC@GK|Q=mXk-9KR0{>9EY9Fq>9MIAP;L)BNx=z^r}7cpPwMkOC9ix!@;H$cp(jY4`+CpVx@LrY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_ope_v3_10000000" + }, + "op": "00b6e0adc426b1981b4d97c99b6e1fb1299fdf7dd20768335b46da223ac660dd93", + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_ope_v3_10000000 WHERE value < $1 ORDER BY eql_v3.ord_ope_term(value) LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "10000000" +} \ No newline at end of file diff --git a/results/query/v3/ope_rows_10000.json b/results/query/v3/ope_rows_10000.json new file mode 100644 index 0000000..8c4a8b6 --- /dev/null +++ b/results/query/v3/ope_rows_10000.json @@ -0,0 +1,11 @@ +{"reason":"benchmark-complete","id":"OPE/ope/range_gt_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_gt_10_10000","iteration_count":[758,1516,2274,3032,3790,4548,5306,6064,6822,7580],"measured_values":[86597542.0,237563334.0,262237375.0,355255334.0,480735916.0,556146000.0,665180583.0,744534292.0,807460333.0,936258042.0],"unit":"ns","throughput":[],"typical":{"estimate":122510.62291402528,"lower_bound":120252.45504949069,"upper_bound":124862.66376169828,"unit":"ns"},"mean":{"estimate":124258.5603011266,"lower_bound":118685.67709762533,"upper_bound":132388.16669583178,"unit":"ns"},"median":{"estimate":122531.52143799473,"lower_bound":116840.5495455878,"upper_bound":125363.84903882397,"unit":"ns"},"median_abs_dev":{"estimate":6287.718636910701,"lower_bound":914.2088933474035,"upper_bound":11121.455413240701,"unit":"ns"},"slope":{"estimate":122510.62291402528,"lower_bound":120252.45504949069,"upper_bound":124862.66376169828,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_gt_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_gt_10_10000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[97571458.0,201040791.0,300769083.0,406533375.0,543407709.0,613714166.0,711942917.0,803237792.0,919904250.0,1006546833.0],"unit":"ns","throughput":[],"typical":{"estimate":25442549.782467533,"lower_bound":25209429.20842572,"upper_bound":25849119.92528808,"unit":"ns"},"mean":{"estimate":25398147.900416665,"lower_bound":25037127.297083333,"upper_bound":25862096.58217708,"unit":"ns"},"median":{"estimate":25286003.38125,"lower_bound":25097094.5625,"upper_bound":25552895.833333332,"unit":"ns"},"median_abs_dev":{"estimate":301513.0300633259,"lower_bound":46323.70645008926,"upper_bound":859931.2121331682,"unit":"ns"},"slope":{"estimate":25442549.782467533,"lower_bound":25209429.20842572,"upper_bound":25849119.92528808,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_gt_100/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_gt_100_10000","iteration_count":[247,494,741,988,1235,1482,1729,1976,2223,2470],"measured_values":[86062459.0,171161334.0,251522167.0,400559542.0,442498917.0,558650416.0,595339750.0,731232417.0,799828958.0,849756375.0],"unit":"ns","throughput":[],"typical":{"estimate":358198.1054208949,"lower_bound":348952.81342780025,"upper_bound":370491.96365335834,"unit":"ns"},"mean":{"estimate":359323.89856741216,"lower_bound":348621.86573709914,"upper_bound":372203.10545644164,"unit":"ns"},"median":{"estimate":353364.86315789475,"lower_bound":344326.05552342394,"upper_bound":370056.891194332,"unit":"ns"},"median_abs_dev":{"estimate":13619.719140266458,"lower_bound":2034.6065007205907,"upper_bound":30761.73795769928,"unit":"ns"},"slope":{"estimate":358198.1054208949,"lower_bound":348952.81342780025,"upper_bound":370491.96365335834,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_gt_100/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_gt_100_10000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[113697750.0,251883167.0,354012750.0,469710375.0,544099083.0,712949208.0,848399625.0,811792291.0,1100763500.0,1187928417.0],"unit":"ns","throughput":[],"typical":{"estimate":38766948.8051948,"lower_bound":36417132.948732734,"upper_bound":40255488.259119496,"unit":"ns"},"mean":{"estimate":38882991.396970905,"lower_bound":37406698.96416666,"upper_bound":40153279.89280423,"unit":"ns"},"median":{"estimate":39466181.95,"lower_bound":37707901.725,"upper_bound":40399982.14285714,"unit":"ns"},"median_abs_dev":{"estimate":1658018.801772052,"lower_bound":202774.7042000312,"upper_bound":3707585.4091771995,"unit":"ns"},"slope":{"estimate":38766948.8051948,"lower_bound":36417132.948732734,"upper_bound":40255488.259119496,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_lt_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_lt_10_10000","iteration_count":[768,1536,2304,3072,3840,4608,5376,6144,6912,7680],"measured_values":[88373875.0,176936084.0,314055084.0,359714375.0,448222375.0,576790125.0,661117542.0,732485041.0,841084333.0,935137208.0],"unit":"ns","throughput":[],"typical":{"estimate":121529.88236945347,"lower_bound":119875.27125167336,"upper_bound":123281.15761434115,"unit":"ns"},"mean":{"estimate":121120.47266870245,"lower_bound":117845.63676432292,"upper_bound":125208.52702676246,"unit":"ns"},"median":{"estimate":120452.11256691262,"lower_bound":116143.64306640625,"upper_bound":123467.06269531249,"unit":"ns"},"median_abs_dev":{"estimate":5252.203216721115,"lower_bound":957.0765494581408,"upper_bound":8845.481271818744,"unit":"ns"},"slope":{"estimate":121529.88236945347,"lower_bound":119875.27125167336,"upper_bound":123281.15761434115,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_lt_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_lt_10_10000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[96912541.0,208035708.0,305834583.0,400567375.0,517418208.0,602567709.0,696198125.0,799682250.0,909377500.0,1037142333.0],"unit":"ns","throughput":[],"typical":{"estimate":25364883.25,"lower_bound":25039502.045992088,"upper_bound":25700178.151859503,"unit":"ns"},"mean":{"estimate":25277550.67111111,"lower_bound":24945905.984239586,"upper_bound":25596465.47625,"unit":"ns"},"median":{"estimate":25183736.993055556,"lower_bound":24949839.84375,"upper_bound":25870910.4,"unit":"ns"},"median_abs_dev":{"estimate":461085.9972640872,"lower_bound":86670.98754253238,"upper_bound":1104272.087136083,"unit":"ns"},"slope":{"estimate":25364883.25,"lower_bound":25039502.045992088,"upper_bound":25700178.151859503,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_lt_100/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_lt_100_10000","iteration_count":[251,502,753,1004,1255,1506,1757,2008,2259,2510],"measured_values":[128979875.0,177025042.0,262214541.0,348216166.0,498848459.0,521144916.0,652068500.0,732909208.0,796142167.0,918995875.0],"unit":"ns","throughput":[],"typical":{"estimate":362877.233445439,"lower_bound":354777.5949803093,"upper_bound":371777.36167311197,"unit":"ns"},"mean":{"estimate":375977.9220856257,"lower_bound":353812.88216143363,"upper_bound":409904.5740776576,"unit":"ns"},"median":{"estimate":358817.0756972112,"lower_bound":348226.48207171314,"upper_bound":381811.31334661355,"unit":"ns"},"median_abs_dev":{"estimate":16737.678023763245,"lower_bound":2072.1283867183706,"upper_bound":36603.556976651016,"unit":"ns"},"slope":{"estimate":362877.233445439,"lower_bound":354777.5949803093,"upper_bound":371777.36167311197,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_lt_100/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_lt_100_10000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[102520125.0,198418250.0,319099458.0,430639042.0,528496625.0,644885125.0,671344750.0,1149579833.0,933237834.0,1091428750.0],"unit":"ns","throughput":[],"typical":{"estimate":37143277.02337662,"lower_bound":33962586.918564685,"upper_bound":41733601.45095223,"unit":"ns"},"mean":{"estimate":36045850.51051587,"lower_bound":34081320.76349206,"upper_bound":38976351.63583334,"unit":"ns"},"median":{"estimate":35344301.833333336,"lower_bound":33817036.277777776,"upper_bound":36103954.86111111,"unit":"ns"},"median_abs_dev":{"estimate":1346641.190659007,"lower_bound":319568.1232765317,"upper_bound":3372312.263229495,"unit":"ns"},"slope":{"estimate":37143277.02337662,"lower_bound":33962586.918564685,"upper_bound":41733601.45095223,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_lt_ordered_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_lt_ordered_10_10000","iteration_count":[773,1546,2319,3092,3865,4638,5411,6184,6957,7730],"measured_values":[87675000.0,225934875.0,271707375.0,359635375.0,489245709.0,539606708.0,687849542.0,721311916.0,793915708.0,925114458.0],"unit":"ns","throughput":[],"typical":{"estimate":119147.5453772618,"lower_bound":116203.72412561958,"upper_bound":123187.33606840426,"unit":"ns"},"mean":{"estimate":121352.7181647467,"lower_bound":116500.71740189222,"upper_bound":127859.12134083349,"unit":"ns"},"median":{"estimate":116903.69631306597,"lower_bound":115231.11757941642,"upper_bound":126583.62457956016,"unit":"ns"},"median_abs_dev":{"estimate":4122.308192368516,"lower_bound":269.2398994891226,"upper_bound":12733.475827318545,"unit":"ns"},"slope":{"estimate":119147.5453772618,"lower_bound":116203.72412561958,"upper_bound":123187.33606840426,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_lt_ordered_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_lt_ordered_10_10000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[98468791.0,194966208.0,297326292.0,404182458.0,507552041.0,604665375.0,719123958.0,821500250.0,917831333.0,1021601792.0],"unit":"ns","throughput":[],"typical":{"estimate":25483916.87857143,"lower_bound":25312615.244396903,"upper_bound":25574871.62592758,"unit":"ns"},"mean":{"estimate":25198880.19680556,"lower_bound":24915429.096718747,"upper_bound":25453025.476805557,"unit":"ns"},"median":{"estimate":25319502.8375,"lower_bound":24777191.0,"upper_bound":25583598.809027776,"unit":"ns"},"median_abs_dev":{"estimate":424707.0247286958,"lower_bound":99353.47203612328,"upper_bound":724410.0226141512,"unit":"ns"},"slope":{"estimate":25483916.87857143,"lower_bound":25312615.244396903,"upper_bound":25574871.62592758,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"OPE","benchmarks":["OPE/ope/range_gt_10/10000","OPE/ope_decrypt/range_gt_10/10000","OPE/ope/range_gt_100/10000","OPE/ope_decrypt/range_gt_100/10000","OPE/ope/range_lt_10/10000","OPE/ope_decrypt/range_lt_10/10000","OPE/ope/range_lt_100/10000","OPE/ope_decrypt/range_lt_100/10000","OPE/ope/range_lt_ordered_10/10000","OPE/ope_decrypt/range_lt_ordered_10/10000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE"} diff --git a/results/query/v3/ope_rows_100000.json b/results/query/v3/ope_rows_100000.json new file mode 100644 index 0000000..e4f720b --- /dev/null +++ b/results/query/v3/ope_rows_100000.json @@ -0,0 +1,11 @@ +{"reason":"benchmark-complete","id":"OPE/ope/range_gt_10/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_gt_10_100000","iteration_count":[683,1366,2049,2732,3415,4098,4781,5464,6147,6830],"measured_values":[82494666.0,162345292.0,249448458.0,321604333.0,442912292.0,499121500.0,606030250.0,819242833.0,785146375.0,855426834.0],"unit":"ns","throughput":[],"typical":{"estimate":129558.20784925178,"lower_bound":123906.28944343647,"upper_bound":138046.08268961,"unit":"ns"},"mean":{"estimate":126024.82136936719,"lower_bound":121570.05317374328,"upper_bound":132065.86500870343,"unit":"ns"},"median":{"estimate":123520.93709126403,"lower_bound":120294.38653001464,"upper_bound":128227.0925329429,"unit":"ns"},"median_abs_dev":{"estimate":5518.653928007721,"lower_bound":791.9659777406694,"upper_bound":10187.884773916601,"unit":"ns"},"slope":{"estimate":129558.20784925178,"lower_bound":123906.28944343647,"upper_bound":138046.08268961,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_gt_10/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_gt_10_100000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[121662583.0,212514083.0,340191084.0,426740458.0,620067208.0,776282041.0,684245041.0,811764875.0,913582625.0,1015436750.0],"unit":"ns","throughput":[],"typical":{"estimate":26423830.864285715,"lower_bound":25299364.88104449,"upper_bound":28756565.661904763,"unit":"ns"},"mean":{"estimate":27591707.63171627,"lower_bound":26045243.64569072,"upper_bound":29299879.184563488,"unit":"ns"},"median":{"estimate":26617769.5,"lower_bound":25376785.546875,"upper_bound":30415645.75,"unit":"ns"},"median_abs_dev":{"estimate":2210263.492438104,"lower_bound":19933.56951590068,"upper_bound":4406230.577057105,"unit":"ns"},"slope":{"estimate":26423830.864285715,"lower_bound":25299364.88104449,"upper_bound":28756565.661904763,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_gt_100/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_gt_100_100000","iteration_count":[160,320,480,640,800,960,1120,1280,1440,1600],"measured_values":[59904375.0,118559584.0,189199750.0,273775375.0,493379750.0,1084993666.0,3501787625.0,2827629875.0,1663158167.0,1099840708.0],"unit":"ns","throughput":[],"typical":{"estimate":1364236.493457792,"lower_bound":755490.4824225155,"upper_bound":2096023.6022183641,"unit":"ns"},"mean":{"estimate":1049182.0961336805,"lower_bound":568839.4417395835,"upper_bound":1644122.3639502604,"unit":"ns"},"median":{"estimate":652062.565,"lower_bound":394166.1458333333,"upper_bound":1669643.7876302083,"unit":"ns"},"median_abs_dev":{"estimate":414552.8077773414,"lower_bound":24913.519225665383,"upper_bound":1180417.3012758256,"unit":"ns"},"slope":{"estimate":1364236.493457792,"lower_bound":755490.4824225155,"upper_bound":2096023.6022183641,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_gt_100/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_gt_100_100000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[88638292.0,179369500.0,285856292.0,421241833.0,490961000.0,699084834.0,726242292.0,1004485125.0,990485625.0,1014703375.0],"unit":"ns","throughput":[],"typical":{"estimate":36207973.09350649,"lower_bound":34027828.636920385,"upper_bound":38763290.251928024,"unit":"ns"},"mean":{"estimate":34481970.17440476,"lower_bound":32312492.210188493,"upper_bound":36814743.03938987,"unit":"ns"},"median":{"estimate":34203206.059523806,"lower_bound":31312825.0,"upper_bound":36970766.208333336,"unit":"ns"},"median_abs_dev":{"estimate":3649303.1216452494,"lower_bound":948893.8204787672,"upper_bound":6629541.904202105,"unit":"ns"},"slope":{"estimate":36207973.09350649,"lower_bound":34027828.636920385,"upper_bound":38763290.251928024,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_lt_10/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_lt_10_100000","iteration_count":[379,758,1137,1516,1895,2274,2653,3032,3411,3790],"measured_values":[50632500.0,88494584.0,149534875.0,328909666.0,203678625.0,373497625.0,297345209.0,368398334.0,478590834.0,450401708.0],"unit":"ns","throughput":[],"typical":{"estimate":130837.69011410752,"lower_bound":118984.74659914443,"upper_bound":148698.73185695623,"unit":"ns"},"mean":{"estimate":136327.73215919084,"lower_bound":120034.99959377751,"upper_bound":157967.85757695689,"unit":"ns"},"median":{"estimate":126510.22438434476,"lower_bound":115459.17915567281,"upper_bound":148920.9817502199,"unit":"ns"},"median_abs_dev":{"estimate":17465.472339530093,"lower_bound":3525.5753059441445,"upper_bound":39075.33514453269,"unit":"ns"},"slope":{"estimate":130837.69011410752,"lower_bound":118984.74659914443,"upper_bound":148698.73185695623,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_lt_10/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_lt_10_100000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[110318125.0,198872541.0,295296500.0,416647708.0,509165834.0,625987375.0,717728791.0,827524583.0,1149228292.0,1521490625.0],"unit":"ns","throughput":[],"typical":{"estimate":30236724.7,"lower_bound":25667969.873992942,"upper_bound":34217547.55088715,"unit":"ns"},"mean":{"estimate":27608180.934533726,"lower_bound":25564276.548845235,"upper_bound":30423261.76194965,"unit":"ns"},"median":{"estimate":25950312.484375,"lower_bound":25246119.36607143,"upper_bound":29002907.701388888,"unit":"ns"},"median_abs_dev":{"estimate":1173674.8008749825,"lower_bound":165060.8743227124,"upper_bound":4628086.615757955,"unit":"ns"},"slope":{"estimate":30236724.7,"lower_bound":25667969.873992942,"upper_bound":34217547.55088715,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_lt_100/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_lt_100_100000","iteration_count":[27,54,81,108,135,162,189,216,243,270],"measured_values":[41379042.0,72926125.0,155842208.0,272995041.0,778907000.0,670926083.0,753636500.0,576173292.0,999454583.0,1068210000.0],"unit":"ns","throughput":[],"typical":{"estimate":3773820.3618085617,"lower_bound":3163596.676781199,"upper_bound":4257952.947823985,"unit":"ns"},"mean":{"estimate":3197022.996722516,"lower_bound":2377910.953600823,"upper_bound":4042705.6648581713,"unit":"ns"},"median":{"estimate":3311901.138888889,"lower_bound":1923977.87654321,"upper_bound":4112981.8230452673,"unit":"ns"},"median_abs_dev":{"estimate":1208836.8330252757,"lower_bound":114178.22777478365,"upper_bound":2464018.7238468984,"unit":"ns"},"slope":{"estimate":3773820.3618085617,"lower_bound":3163596.676781199,"upper_bound":4257952.947823985,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_lt_100/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_lt_100_100000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[90903958.0,181134583.0,280681541.0,406881208.0,463306459.0,594774667.0,650916083.0,754065042.0,883473334.0,977985125.0],"unit":"ns","throughput":[],"typical":{"estimate":32145426.016450215,"lower_bound":31441861.927801188,"upper_bound":32664468.65435743,"unit":"ns"},"mean":{"estimate":31725027.550608467,"lower_bound":31012124.184497356,"upper_bound":32480403.078439157,"unit":"ns"},"median":{"estimate":31303107.319444444,"lower_bound":30648661.64285714,"upper_bound":32821270.611111112,"unit":"ns"},"median_abs_dev":{"estimate":1568441.1325129364,"lower_bound":222197.7193085354,"upper_bound":1938148.3364909906,"unit":"ns"},"slope":{"estimate":32145426.016450215,"lower_bound":31441861.927801188,"upper_bound":32664468.65435743,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_lt_ordered_10/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_lt_ordered_10_100000","iteration_count":[726,1452,2178,2904,3630,4356,5082,5808,6534,7260],"measured_values":[82568292.0,167396000.0,240315750.0,395043500.0,428664959.0,554987834.0,556817666.0,746159000.0,830650459.0,889920750.0],"unit":"ns","throughput":[],"typical":{"estimate":123193.41216414439,"lower_bound":117619.37059251683,"upper_bound":127213.34759165173,"unit":"ns"},"mean":{"estimate":120862.97623070532,"lower_bound":115799.76282056498,"upper_bound":126073.51653198656,"unit":"ns"},"median":{"estimate":120334.06804407714,"lower_bound":112812.15564738293,"upper_bound":127799.15319865319,"unit":"ns"},"median_abs_dev":{"estimate":10279.565030761109,"lower_bound":1203.700091945021,"upper_bound":15051.421448486326,"unit":"ns"},"slope":{"estimate":123193.41216414439,"lower_bound":117619.37059251683,"upper_bound":127213.34759165173,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_lt_ordered_10/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_lt_ordered_10_100000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[100799417.0,223016500.0,310607834.0,442118250.0,511460625.0,657158666.0,748307125.0,810603583.0,927056292.0,1034568625.0],"unit":"ns","throughput":[],"typical":{"estimate":26077633.413636364,"lower_bound":25702508.079450604,"upper_bound":26696211.726370737,"unit":"ns"},"mean":{"estimate":26322033.159970235,"lower_bound":25762521.53364583,"upper_bound":26930487.252678566,"unit":"ns"},"median":{"estimate":25874100.895833336,"lower_bound":25541462.817708336,"upper_bound":27381611.083333332,"unit":"ns"},"median_abs_dev":{"estimate":902151.3891867399,"lower_bound":112820.69978453034,"upper_bound":1580159.8703965545,"unit":"ns"},"slope":{"estimate":26077633.413636364,"lower_bound":25702508.079450604,"upper_bound":26696211.726370737,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"OPE","benchmarks":["OPE/ope/range_gt_10/100000","OPE/ope_decrypt/range_gt_10/100000","OPE/ope/range_gt_100/100000","OPE/ope_decrypt/range_gt_100/100000","OPE/ope/range_lt_10/100000","OPE/ope_decrypt/range_lt_10/100000","OPE/ope/range_lt_100/100000","OPE/ope_decrypt/range_lt_100/100000","OPE/ope/range_lt_ordered_10/100000","OPE/ope_decrypt/range_lt_ordered_10/100000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE"} diff --git a/results/query/v3/ope_rows_1000000.json b/results/query/v3/ope_rows_1000000.json new file mode 100644 index 0000000..467e11c --- /dev/null +++ b/results/query/v3/ope_rows_1000000.json @@ -0,0 +1,11 @@ +{"reason":"benchmark-complete","id":"OPE/ope/range_gt_10/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_gt_10_1000000","iteration_count":[736,1472,2208,2944,3680,4416,5152,5888,6624,7360],"measured_values":[85860167.0,161562458.0,255777333.0,386192333.0,436328667.0,543687333.0,597686584.0,736934250.0,806933292.0,841143292.0],"unit":"ns","throughput":[],"typical":{"estimate":119699.20377964427,"lower_bound":116283.8221681467,"upper_bound":123556.05910911731,"unit":"ns"},"mean":{"estimate":119239.543747412,"lower_bound":115743.13811417898,"upper_bound":122966.9945519054,"unit":"ns"},"median":{"estimate":117612.70407608696,"lower_bound":115148.18404503106,"upper_bound":123489.15483469202,"unit":"ns"},"median_abs_dev":{"estimate":5584.854857968569,"lower_bound":730.9688377020486,"upper_bound":10439.467604981704,"unit":"ns"},"slope":{"estimate":119699.20377964427,"lower_bound":116283.8221681467,"upper_bound":123556.05910911731,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_gt_10/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_gt_10_1000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[100209875.0,206146208.0,331352084.0,427882042.0,538981333.0,627480625.0,706408292.0,838847375.0,872595208.0,1013601708.0],"unit":"ns","throughput":[],"typical":{"estimate":25534342.936363637,"lower_bound":24942158.99704142,"upper_bound":26343823.886565406,"unit":"ns"},"mean":{"estimate":25929178.525128968,"lower_bound":25340247.248888142,"upper_bound":26523305.507151786,"unit":"ns"},"median":{"estimate":25956651.020833336,"lower_bound":25196255.725,"upper_bound":26742627.625,"unit":"ns"},"median_abs_dev":{"estimate":1122150.30779035,"lower_bound":261528.8880069333,"upper_bound":1718185.6001661064,"unit":"ns"},"slope":{"estimate":25534342.936363637,"lower_bound":24942158.99704142,"upper_bound":26343823.886565406,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_gt_100/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_gt_100_1000000","iteration_count":[255,510,765,1020,1275,1530,1785,2040,2295,2550],"measured_values":[86644000.0,171613583.0,256797042.0,383474458.0,429703791.0,556916584.0,665129834.0,726973541.0,810038333.0,890797209.0],"unit":"ns","throughput":[],"typical":{"estimate":355428.49845683726,"lower_bound":349450.37572220474,"upper_bound":363414.0532951289,"unit":"ns"},"mean":{"estimate":352020.71738359786,"lower_bound":343544.1942991285,"upper_bound":361166.2769743541,"unit":"ns"},"median":{"estimate":351145.0590631808,"lower_bound":337022.5811764706,"upper_bound":364490.6673319328,"unit":"ns"},"median_abs_dev":{"estimate":19996.705133379666,"lower_bound":1597.4918783446826,"upper_bound":26389.66763713679,"unit":"ns"},"slope":{"estimate":355428.49845683726,"lower_bound":349450.37572220474,"upper_bound":363414.0532951289,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_gt_100/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_gt_100_1000000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[110636333.0,213551125.0,317463208.0,435016041.0,517884000.0,642610916.0,697812167.0,831434709.0,952363750.0,1062154375.0],"unit":"ns","throughput":[],"typical":{"estimate":34982041.73852814,"lower_bound":34306452.08939846,"upper_bound":35457443.15873016,"unit":"ns"},"mean":{"estimate":35277200.58048942,"lower_bound":34664874.56230159,"upper_bound":35842475.549444444,"unit":"ns"},"median":{"estimate":35339417.80555555,"lower_bound":34643112.875,"upper_bound":35921595.45833333,"unit":"ns"},"median_abs_dev":{"estimate":783919.9691118076,"lower_bound":98158.75728511067,"upper_bound":1657298.280639572,"unit":"ns"},"slope":{"estimate":34982041.73852814,"lower_bound":34306452.08939846,"upper_bound":35457443.15873016,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_lt_10/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_lt_10_1000000","iteration_count":[741,1482,2223,2964,3705,4446,5187,5928,6669,7410],"measured_values":[96013333.0,200908417.0,294685334.0,399267500.0,447261084.0,580855666.0,551397250.0,723510625.0,842744875.0,886587500.0],"unit":"ns","throughput":[],"typical":{"estimate":121979.21450479345,"lower_bound":116570.9253919643,"upper_bound":127397.57261302295,"unit":"ns"},"mean":{"estimate":125813.93912510978,"lower_bound":120206.41999063363,"upper_bound":130592.7087869246,"unit":"ns"},"median":{"estimate":127970.0758734443,"lower_bound":120718.24129554656,"upper_bound":132676.216374269,"unit":"ns"},"median_abs_dev":{"estimate":9381.843488550312,"lower_bound":1592.5337946688405,"upper_bound":15152.80939737725,"unit":"ns"},"slope":{"estimate":121979.21450479345,"lower_bound":116570.9253919643,"upper_bound":127397.57261302295,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_lt_10/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_lt_10_1000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[103659500.0,191187250.0,316170750.0,408560209.0,511163083.0,621009250.0,713116791.0,841319042.0,912477667.0,1031310291.0],"unit":"ns","throughput":[],"typical":{"estimate":25713266.095454544,"lower_bound":25452450.31989604,"upper_bound":25987932.08998612,"unit":"ns"},"mean":{"estimate":25601843.239920635,"lower_bound":25152835.29046677,"upper_bound":25947415.767896824,"unit":"ns"},"median":{"estimate":25670455.7125,"lower_bound":25440807.461805556,"upper_bound":26083302.739583336,"unit":"ns"},"median_abs_dev":{"estimate":333102.40160875337,"lower_bound":66492.62848952191,"upper_bound":868834.4566313513,"unit":"ns"},"slope":{"estimate":25713266.095454544,"lower_bound":25452450.31989604,"upper_bound":25987932.08998612,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_lt_100/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_lt_100_1000000","iteration_count":[246,492,738,984,1230,1476,1722,1968,2214,2460],"measured_values":[90641000.0,210492333.0,262844333.0,351023250.0,486717208.0,537523917.0,656673708.0,690670208.0,812699125.0,962326375.0],"unit":"ns","throughput":[],"typical":{"estimate":374011.3472917327,"lower_bound":361040.4803853053,"upper_bound":386024.4779468666,"unit":"ns"},"mean":{"estimate":375961.5299832237,"lower_bound":363327.20057475154,"upper_bound":390921.271984127,"unit":"ns"},"median":{"estimate":367766.06255645887,"lower_bound":356730.9451219512,"upper_bound":391189.5833333333,"unit":"ns"},"median_abs_dev":{"estimate":18670.369558372095,"lower_bound":3175.1761820440056,"upper_bound":38270.47128946574,"unit":"ns"},"slope":{"estimate":374011.3472917327,"lower_bound":361040.4803853053,"upper_bound":386024.4779468666,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_lt_100/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_lt_100_1000000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[117356584.0,203597625.0,310182667.0,399397584.0,509866041.0,597124125.0,706821125.0,761069250.0,904269333.0,1004835000.0],"unit":"ns","throughput":[],"typical":{"estimate":33253541.98961039,"lower_bound":32619763.77147016,"upper_bound":33698213.86663619,"unit":"ns"},"mean":{"estimate":34031962.78484127,"lower_bound":33108583.286027778,"upper_bound":35314331.95428571,"unit":"ns"},"median":{"estimate":33576324.4047619,"lower_bound":33283132.0,"upper_bound":34198839.13888889,"unit":"ns"},"median_abs_dev":{"estimate":562924.6775060892,"lower_bound":123568.80093954717,"upper_bound":1690053.2568405557,"unit":"ns"},"slope":{"estimate":33253541.98961039,"lower_bound":32619763.77147016,"upper_bound":33698213.86663619,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_lt_ordered_10/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_lt_ordered_10_1000000","iteration_count":[742,1484,2226,2968,3710,4452,5194,5936,6678,7420],"measured_values":[86457833.0,174462834.0,265248625.0,390545583.0,431411667.0,592113208.0,608344916.0,750566750.0,823980458.0,860193292.0],"unit":"ns","throughput":[],"typical":{"estimate":121762.01471978157,"lower_bound":117827.31764797165,"upper_bound":126618.57156002897,"unit":"ns"},"mean":{"estimate":121699.41993175886,"lower_bound":118156.59953493348,"upper_bound":125763.42950552184,"unit":"ns"},"median":{"estimate":118360.93351302785,"lower_bound":116519.99056603774,"upper_bound":127486.3746443546,"unit":"ns"},"median_abs_dev":{"estimate":3342.8061053702972,"lower_bound":613.4241406189793,"upper_bound":10719.856366389364,"unit":"ns"},"slope":{"estimate":121762.01471978157,"lower_bound":117827.31764797165,"upper_bound":126618.57156002897,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_lt_ordered_10/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_lt_ordered_10_1000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[98870834.0,206124250.0,318220833.0,425753542.0,507106417.0,628453708.0,708033042.0,840106084.0,917974125.0,1049414833.0],"unit":"ns","throughput":[],"typical":{"estimate":25914315.425324675,"lower_bound":25563946.300758738,"upper_bound":26232190.969505716,"unit":"ns"},"mean":{"estimate":25842699.244880952,"lower_bound":25472070.060657736,"upper_bound":26192381.111041665,"unit":"ns"},"median":{"estimate":25975551.208333336,"lower_bound":25355320.85,"upper_bound":26376886.7875,"unit":"ns"},"median_abs_dev":{"estimate":755474.754537642,"lower_bound":50724.55825445939,"upper_bound":1052041.895952524,"unit":"ns"},"slope":{"estimate":25914315.425324675,"lower_bound":25563946.300758738,"upper_bound":26232190.969505716,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"OPE","benchmarks":["OPE/ope/range_gt_10/1000000","OPE/ope_decrypt/range_gt_10/1000000","OPE/ope/range_gt_100/1000000","OPE/ope_decrypt/range_gt_100/1000000","OPE/ope/range_lt_10/1000000","OPE/ope_decrypt/range_lt_10/1000000","OPE/ope/range_lt_100/1000000","OPE/ope_decrypt/range_lt_100/1000000","OPE/ope/range_lt_ordered_10/1000000","OPE/ope_decrypt/range_lt_ordered_10/1000000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE"} diff --git a/results/query/v3/ope_rows_10000000.json b/results/query/v3/ope_rows_10000000.json new file mode 100644 index 0000000..d8e425a --- /dev/null +++ b/results/query/v3/ope_rows_10000000.json @@ -0,0 +1,11 @@ +{"reason":"benchmark-complete","id":"OPE/ope/range_gt_10/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_gt_10_10000000","iteration_count":[735,1470,2205,2940,3675,4410,5145,5880,6615,7350],"measured_values":[88069458.0,173445416.0,279374458.0,419781542.0,485038500.0,589253750.0,630711416.0,750954708.0,831584209.0,926661916.0],"unit":"ns","throughput":[],"typical":{"estimate":127525.11511264247,"lower_bound":125458.90470409127,"upper_bound":131040.40997244776,"unit":"ns"},"mean":{"estimate":127498.56266234748,"lower_bound":123539.70203500162,"upper_bound":131959.53814058958,"unit":"ns"},"median":{"estimate":126388.44281179138,"lower_bound":122587.25286686103,"upper_bound":131983.26530612246,"unit":"ns"},"median_abs_dev":{"estimate":6965.26389756634,"lower_bound":750.9007461926561,"upper_bound":11584.70370194943,"unit":"ns"},"slope":{"estimate":127525.11511264247,"lower_bound":125458.90470409127,"upper_bound":131040.40997244776,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_gt_10/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_gt_10_10000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[101478208.0,212543917.0,318645042.0,408801917.0,519187542.0,634626291.0,717539667.0,826262833.0,977625916.0,1039770791.0],"unit":"ns","throughput":[],"typical":{"estimate":26201705.0512987,"lower_bound":25821519.738584474,"upper_bound":26683948.265395757,"unit":"ns"},"mean":{"estimate":26104122.95917659,"lower_bound":25789004.320763394,"upper_bound":26441722.885251738,"unit":"ns"},"median":{"estimate":25976823.4375,"lower_bound":25626416.67857143,"upper_bound":26553753.5,"unit":"ns"},"median_abs_dev":{"estimate":661715.7345084473,"lower_bound":92831.14410191774,"upper_bound":939602.9058718384,"unit":"ns"},"slope":{"estimate":26201705.0512987,"lower_bound":25821519.738584474,"upper_bound":26683948.265395757,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_gt_100/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_gt_100_10000000","iteration_count":[259,518,777,1036,1295,1554,1813,2072,2331,2590],"measured_values":[86097542.0,183999375.0,292966750.0,344588041.0,445272584.0,551941625.0,649182042.0,692442209.0,819355375.0,915555625.0],"unit":"ns","throughput":[],"typical":{"estimate":349625.71295191295,"lower_bound":342123.64001792227,"upper_bound":355163.19264558004,"unit":"ns"},"mean":{"estimate":349357.2305664338,"lower_bound":341402.44282604026,"upper_bound":357701.15522338665,"unit":"ns"},"median":{"estimate":352500.09384384385,"lower_bound":334190.2553088803,"upper_bound":356622.7076208862,"unit":"ns"},"median_abs_dev":{"estimate":10549.285310627814,"lower_bound":1271.1577477027115,"upper_bound":29558.89496993193,"unit":"ns"},"slope":{"estimate":349625.71295191295,"lower_bound":342123.64001792227,"upper_bound":355163.19264558004,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_gt_100/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_gt_100_10000000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[110346166.0,214370375.0,324109917.0,441682792.0,549636333.0,649611583.0,751812042.0,896600750.0,928700834.0,1081892167.0],"unit":"ns","throughput":[],"typical":{"estimate":35962526.81212121,"lower_bound":35168668.54533333,"upper_bound":36775395.54210478,"unit":"ns"},"mean":{"estimate":36167985.55193122,"lower_bound":35664192.23730159,"upper_bound":36613902.20973611,"unit":"ns"},"median":{"estimate":36076302.31111111,"lower_bound":35800573.428571425,"upper_bound":36782055.333333336,"unit":"ns"},"median_abs_dev":{"estimate":677567.7335807685,"lower_bound":57316.86196575501,"upper_bound":1278971.542523727,"unit":"ns"},"slope":{"estimate":35962526.81212121,"lower_bound":35168668.54533333,"upper_bound":36775395.54210478,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_lt_10/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_lt_10_10000000","iteration_count":[726,1452,2178,2904,3630,4356,5082,5808,6534,7260],"measured_values":[85252708.0,178177166.0,302465167.0,344546458.0,434939208.0,538965875.0,632322000.0,680161750.0,822242959.0,913471709.0],"unit":"ns","throughput":[],"typical":{"estimate":123566.71097277378,"lower_bound":120250.146592675,"upper_bound":125831.40661516256,"unit":"ns"},"mean":{"estimate":123440.02038294198,"lower_bound":120190.97074390552,"upper_bound":127529.96408894137,"unit":"ns"},"median":{"estimate":123220.54327364554,"lower_bound":118622.96804407713,"upper_bound":125822.54944903581,"unit":"ns"},"median_abs_dev":{"estimate":4464.634555567013,"lower_bound":1029.382746876323,"upper_bound":9102.756721451615,"unit":"ns"},"slope":{"estimate":123566.71097277378,"lower_bound":120250.146592675,"upper_bound":125831.40661516256,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_lt_10/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_lt_10_10000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[102486791.0,203647209.0,310485041.0,446711917.0,506811250.0,617053791.0,722944625.0,835159000.0,943539750.0,1053568500.0],"unit":"ns","throughput":[],"typical":{"estimate":26125902.675974026,"lower_bound":25832948.302163858,"upper_bound":26381833.217451524,"unit":"ns"},"mean":{"estimate":26038880.387202382,"lower_bound":25681906.909017853,"upper_bound":26521081.06041667,"unit":"ns"},"median":{"estimate":25846602.154761903,"lower_bound":25583237.875,"upper_bound":26218965.625,"unit":"ns"},"median_abs_dev":{"estimate":455863.8653818012,"lower_bound":120964.43611495288,"upper_bound":801393.1128599274,"unit":"ns"},"slope":{"estimate":26125902.675974026,"lower_bound":25832948.302163858,"upper_bound":26381833.217451524,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_lt_100/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_lt_100_10000000","iteration_count":[246,492,738,984,1230,1476,1722,1968,2214,2460],"measured_values":[87206625.0,174835917.0,261821125.0,391225084.0,437801083.0,584346666.0,610451958.0,735878583.0,809177500.0,943074292.0],"unit":"ns","throughput":[],"typical":{"estimate":373306.51854080876,"lower_bound":362995.59730352304,"upper_bound":382579.3975533445,"unit":"ns"},"mean":{"estimate":369131.77893937926,"lower_bound":359379.1935178571,"upper_bound":379902.48818882275,"unit":"ns"},"median":{"estimate":360708.9994128274,"lower_bound":354771.1720867209,"upper_bound":384910.43470528454,"unit":"ns"},"median_abs_dev":{"estimate":9205.319013591845,"lower_bound":399.49296282628126,"upper_bound":28592.828983331055,"unit":"ns"},"slope":{"estimate":373306.51854080876,"lower_bound":362995.59730352304,"upper_bound":382579.3975533445,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_lt_100/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_lt_100_10000000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[113599750.0,229761375.0,298419708.0,423594125.0,529736916.0,647065583.0,770542750.0,890367875.0,976726750.0,1128829750.0],"unit":"ns","throughput":[],"typical":{"estimate":36614213.594805196,"lower_bound":35831317.40410101,"upper_bound":37154003.46825035,"unit":"ns"},"mean":{"estimate":36347518.043902114,"lower_bound":35400218.348449394,"upper_bound":37191776.02843915,"unit":"ns"},"median":{"estimate":36433788.35978836,"lower_bound":35315794.4,"upper_bound":37627658.333333336,"unit":"ns"},"median_abs_dev":{"estimate":1669609.1319857354,"lower_bound":383583.52096780867,"upper_bound":2620322.4128799774,"unit":"ns"},"slope":{"estimate":36614213.594805196,"lower_bound":35831317.40410101,"upper_bound":37154003.46825035,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope/range_lt_ordered_10/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_range_lt_ordered_10_10000000","iteration_count":[757,1514,2271,3028,3785,4542,5299,6056,6813,7570],"measured_values":[87232875.0,172461708.0,260543458.0,398022292.0,436086125.0,555543541.0,605337000.0,741720208.0,818184458.0,762262916.0],"unit":"ns","throughput":[],"typical":{"estimate":114865.5068709362,"lower_bound":107232.52302182977,"upper_bound":121858.23227393995,"unit":"ns"},"mean":{"estimate":117034.65688347905,"lower_bound":112260.92073153215,"upper_bound":121684.23855863791,"unit":"ns"},"median":{"estimate":115224.63672391017,"lower_bound":114236.08227967541,"upper_bound":122312.53654777631,"unit":"ns"},"median_abs_dev":{"estimate":4581.49853653973,"lower_bound":377.0696970044842,"upper_bound":12458.622206027901,"unit":"ns"},"slope":{"estimate":114865.5068709362,"lower_bound":107232.52302182977,"upper_bound":121858.23227393995,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"OPE/ope_decrypt/range_lt_ordered_10/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE/ope_decrypt_range_lt_ordered_10_10000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[106308667.0,208377959.0,314321833.0,412375291.0,522555125.0,609976667.0,730528542.0,817837875.0,927862000.0,1070755000.0],"unit":"ns","throughput":[],"typical":{"estimate":26040829.655194804,"lower_bound":25660733.38357843,"upper_bound":26450299.2785576,"unit":"ns"},"mean":{"estimate":26032536.221378967,"lower_bound":25791430.652109377,"upper_bound":26287351.680208333,"unit":"ns"},"median":{"estimate":26068774.973214284,"lower_bound":25665689.019097224,"upper_bound":26352461.5,"unit":"ns"},"median_abs_dev":{"estimate":437478.04971029254,"lower_bound":59683.0812279135,"upper_bound":755928.1753077172,"unit":"ns"},"slope":{"estimate":26040829.655194804,"lower_bound":25660733.38357843,"upper_bound":26450299.2785576,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"OPE","benchmarks":["OPE/ope/range_gt_10/10000000","OPE/ope_decrypt/range_gt_10/10000000","OPE/ope/range_gt_100/10000000","OPE/ope_decrypt/range_gt_100/10000000","OPE/ope/range_lt_10/10000000","OPE/ope_decrypt/range_lt_10/10000000","OPE/ope/range_lt_100/10000000","OPE/ope_decrypt/range_lt_100/10000000","OPE/ope/range_lt_ordered_10/10000000","OPE/ope_decrypt/range_lt_ordered_10/10000000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/OPE"} diff --git a/results/query/v3/ore_metadata_10000.json b/results/query/v3/ore_metadata_10000.json new file mode 100644 index 0000000..54fb4a1 --- /dev/null +++ b/results/query/v3/ore_metadata_10000.json @@ -0,0 +1,260 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_10000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbLWBsRb)6eQXj+CUGLmauNb7J=5#Ijbu(MfY$S*X$T)tFQsFESJ|`4Gvy~+(%0~u-L8W$KY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22490886344f6e1d4cddadfb8776875fcf3c3e0abe2e76343ec6e50141fd235f9c9ee19780966731ee39b0b511d16e8bb36edee7dce9b67b0b6a4a38a49a1eae5d1e0bb93557f581daff17ecc75f9f2f9c17eccf907e6a38a8d409ae85f82542a420c88259d8565b0f1d4b813bd65dd1f0022d0f0826b18d7b3cfe226c5c6d47de8ebe6ffc4f235c645adeb69f6a6eee70b7cfd659a480ae4913ea1b3102db337a702401a344c7ef95836dce6d4cc3bb02f291ac164dac8a208fd0584e4d2574908de61026f54a98f534f85c85664d0b28518e3a52e39c88b8cc5eb124e1ff85b3f332a633b03b0541fbf45e07b67e1c5b96b63fcc4820f888b86a188b44c481aad4a47b515547b7fcde919d2163c57757\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4850, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.79, + "Total Cost": 7321.57 + } + ], + "Startup Cost": 0.79, + "Total Cost": 15.88 + } + } + ], + "id": "ORE/ore/range_gt_10/10000", + "indexes_used": [ + "integer_encrypted_v3_10000_ord_index" + ], + "parameters": [ + { + "c": "mBbLWBsRb)6eQXj+CUGLmauNb7J=5#Ijbu(MfY$S*X$T)tFQsFESJ|`4Gvy~+(%0~u-L8W$KY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_10000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22490886344f6e1d4cddadfb8776875fcf3c3e0abe2e76343ec6e50141fd235f9c9ee19780966731ee39b0b511d16e8bb36edee7dce9b67b0b6a4a38a49a1eae5d1e0bb93557f581daff17ecc75f9f2f9c17eccf907e6a38a8d409ae85f82542a420c88259d8565b0f1d4b813bd65dd1f0022d0f0826b18d7b3cfe226c5c6d47de8ebe6ffc4f235c645adeb69f6a6eee70b7cfd659a480ae4913ea1b3102db337a702401a344c7ef95836dce6d4cc3bb02f291ac164dac8a208fd0584e4d2574908de61026f54a98f534f85c85664d0b28518e3a52e39c88b8cc5eb124e1ff85b3f332a633b03b0541fbf45e07b67e1c5b96b63fcc4820f888b86a188b44c481aad4a47b515547b7fcde919d2163c57757" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_10000 WHERE value > $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_10000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbKU56O`Yy;m%(Dx9`_dev3L7Ufb$9A@2;5Kibtu6{_?$YJib)~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22f7940434ba5d8bd58e8012390a42164589e167363538df78ab9fe9fb7a378cab07a6534c6dff35c861f28333799c5ad21d84f5b40a6958bd229511ba57f0eece264ff386bfb6b05b1a834119b7a9086cd8f746b3376124ec58b137caea8bf427c238a49dde1ad7c983f5adf1acd84a8354c3480c9fcb5e7dd2a90e9ebc730faf80a83d279cdf6e7d064ba83bab30f7e9199e46b87dd235dd029450a878a33247724fc340886d9510d285e5bab097735b2cf2c6f92566da2c75d919af14c6eab5f7e7f62bc2e9324af2fa2203a082e15526501a5c945e07bf8859c93597e63d49119d63a14303505d65b9917b92aa03d54bbebf74bd1d1e2891d20675e292fec863bf1d14093ff9c5052a0a1afbcb8d93\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4850, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.79, + "Total Cost": 7321.57 + } + ], + "Startup Cost": 0.79, + "Total Cost": 151.73 + } + } + ], + "id": "ORE/ore/range_gt_100/10000", + "indexes_used": [ + "integer_encrypted_v3_10000_ord_index" + ], + "parameters": [ + { + "c": "mBbKU56O`Yy;m%(Dx9`_dev3L7Ufb$9A@2;5Kibtu6{_?$YJib)~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_10000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22f7940434ba5d8bd58e8012390a42164589e167363538df78ab9fe9fb7a378cab07a6534c6dff35c861f28333799c5ad21d84f5b40a6958bd229511ba57f0eece264ff386bfb6b05b1a834119b7a9086cd8f746b3376124ec58b137caea8bf427c238a49dde1ad7c983f5adf1acd84a8354c3480c9fcb5e7dd2a90e9ebc730faf80a83d279cdf6e7d064ba83bab30f7e9199e46b87dd235dd029450a878a33247724fc340886d9510d285e5bab097735b2cf2c6f92566da2c75d919af14c6eab5f7e7f62bc2e9324af2fa2203a082e15526501a5c945e07bf8859c93597e63d49119d63a14303505d65b9917b92aa03d54bbebf74bd1d1e2891d20675e292fec863bf1d14093ff9c5052a0a1afbcb8d93" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_10000 WHERE value > $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_10000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbLl{C%Ofl0~-A-(IfQl0o0Z7TILl#*xnD^%i>Yz!Km6L-a=g&)uxVAhnj6unq99%|*}#SxN~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a228a2443aca787f0fb57be71172c456978a43b8a5b775baf4830ae4e374c2351d8e3ded9ac485f5dbe9599ddc2bed03a2e44ba12bc2e5e2c82790bdb96b3e13b4141a0f3dc497958fb679b5d8063b72f903e577640446e5fd25c572ab64a5a0ef6697cad7017fd06421facb751a5572c4c0357519d4a629c7311eecf341e6de0ee55b84c6bfd20dbe3778d4e22412dac66532ff6de23b2451a0f49da3b97513fcab360994e62883f02f860799e6954f70dae27ace2887d7f42f698a481bc62de663332c06d7a6a3abb6a11d71ad827dda203b92695883a2043c2e0a0996bb71429c42a70c80d25904af5441ebb808adecd349bb24aacf15eee3861486f41aaae6558aad6baaa206a9f0af6a6c09e95ac1a\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5149, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.79, + "Total Cost": 7418.8 + } + ], + "Startup Cost": 0.79, + "Total Cost": 15.19 + } + } + ], + "id": "ORE/ore/range_lt_10/10000", + "indexes_used": [ + "integer_encrypted_v3_10000_ord_index" + ], + "parameters": [ + { + "c": "mBbLl{C%Ofl0~-A-(IfQl0o0Z7TILl#*xnD^%i>Yz!Km6L-a=g&)uxVAhnj6unq99%|*}#SxN~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_10000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a228a2443aca787f0fb57be71172c456978a43b8a5b775baf4830ae4e374c2351d8e3ded9ac485f5dbe9599ddc2bed03a2e44ba12bc2e5e2c82790bdb96b3e13b4141a0f3dc497958fb679b5d8063b72f903e577640446e5fd25c572ab64a5a0ef6697cad7017fd06421facb751a5572c4c0357519d4a629c7311eecf341e6de0ee55b84c6bfd20dbe3778d4e22412dac66532ff6de23b2451a0f49da3b97513fcab360994e62883f02f860799e6954f70dae27ace2887d7f42f698a481bc62de663332c06d7a6a3abb6a11d71ad827dda203b92695883a2043c2e0a0996bb71429c42a70c80d25904af5441ebb808adecd349bb24aacf15eee3861486f41aaae6558aad6baaa206a9f0af6a6c09e95ac1a" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_10000 WHERE value < $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_10000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbK)I?FpYxps3J?f(PG%{>If7PpY{-*4+!p?MHJKsJhNkZ_gMl`{s!AdG}a-(vN7Mf~u}Cm$k-M=GK89Q;$7KeK&;jKXY552bctY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2200151d9d8f251f9a8450cb7f8965238f6bb402c5a8912c063f8daefbccccc742bb890860e7df922f3d97fd797c481026337b5ff190ca8ed5db4ff2dc8b0831adab25ed5f366ed6985ba40b14db3d9efcbd2025949decabebe172a6bc0e3de33ea373c0f01020ebea7b4789385cdcbe2eb8a1bfb8c4a60540ee584c91ba5dd15f237d62304abcb81620a7ae713c1bb881c548b82615244149082f42ab897df38741fc8ed64b86b7c4d1c9706b9bc64efe80581f7f4200f4a5f3d776bb0ef661806b8737f0d2719b663109d228fcbf5b4c682319b3f1bf0d3eddea3f3855c2397a7373e2fb46c93129eb8a9fd62370526d142110b7761da40bf3b9a6968d2a77d4b9fc908854497b2418db64b4675da1d9\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5149, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.79, + "Total Cost": 7418.8 + } + ], + "Startup Cost": 0.79, + "Total Cost": 144.85 + } + } + ], + "id": "ORE/ore/range_lt_100/10000", + "indexes_used": [ + "integer_encrypted_v3_10000_ord_index" + ], + "parameters": [ + { + "c": "mBbK)I?FpYxps3J?f(PG%{>If7PpY{-*4+!p?MHJKsJhNkZ_gMl`{s!AdG}a-(vN7Mf~u}Cm$k-M=GK89Q;$7KeK&;jKXY552bctY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_10000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2200151d9d8f251f9a8450cb7f8965238f6bb402c5a8912c063f8daefbccccc742bb890860e7df922f3d97fd797c481026337b5ff190ca8ed5db4ff2dc8b0831adab25ed5f366ed6985ba40b14db3d9efcbd2025949decabebe172a6bc0e3de33ea373c0f01020ebea7b4789385cdcbe2eb8a1bfb8c4a60540ee584c91ba5dd15f237d62304abcb81620a7ae713c1bb881c548b82615244149082f42ab897df38741fc8ed64b86b7c4d1c9706b9bc64efe80581f7f4200f4a5f3d776bb0ef661806b8737f0d2719b663109d228fcbf5b4c682319b3f1bf0d3eddea3f3855c2397a7373e2fb46c93129eb8a9fd62370526d142110b7761da40bf3b9a6968d2a77d4b9fc908854497b2418db64b4675da1d9" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_10000 WHERE value < $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1096, + "Plans": [ + { + "Alias": "integer_encrypted_v3_10000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbK-he;~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2200d8f72210923597a171ad266453b215e6473ab07a8e310ed7feb75e4ac69926402cc1248fca4f0819cf05fec3ef69433b550dac8f5993adc66b4820e630ac999c50617e3638ddebb8532dea97bc1e1215fa185340c6c2c14c9b1854dfda8eef328fad65dfaeab686add3b9ebd07fbbf90aa32f8fb596878e07d801979d1c34a3563720fedcf17855aca308e8341b5e37e41b2c8cb4624c18a747c91b038a116e6c3a07a326d0353af401f2aa9564ac66c19f87925f16085126490a27c16bb0b34eda3ce201b34827d4157d92fed075f3665fafe085a3971171c1bd3d5e0dd9b5bf4cdb655cd4faae80c0dff33b019f6c613838d9453980e2458b0b3ea45db71bc74d4340896927fe4d1ef40639fc025\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5149, + "Plan Width": 1096, + "Relation Name": "integer_encrypted_v3_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.79, + "Total Cost": 8706.05 + } + ], + "Startup Cost": 0.79, + "Total Cost": 17.69 + } + } + ], + "id": "ORE/ore/range_lt_ordered_10/10000", + "indexes_used": [ + "integer_encrypted_v3_10000_ord_index" + ], + "parameters": [ + { + "c": "mBbK-he;~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_10000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2200d8f72210923597a171ad266453b215e6473ab07a8e310ed7feb75e4ac69926402cc1248fca4f0819cf05fec3ef69433b550dac8f5993adc66b4820e630ac999c50617e3638ddebb8532dea97bc1e1215fa185340c6c2c14c9b1854dfda8eef328fad65dfaeab686add3b9ebd07fbbf90aa32f8fb596878e07d801979d1c34a3563720fedcf17855aca308e8341b5e37e41b2c8cb4624c18a747c91b038a116e6c3a07a326d0353af401f2aa9564ac66c19f87925f16085126490a27c16bb0b34eda3ce201b34827d4157d92fed075f3665fafe085a3971171c1bd3d5e0dd9b5bf4cdb655cd4faae80c0dff33b019f6c613838d9453980e2458b0b3ea45db71bc74d4340896927fe4d1ef40639fc025" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_10000 WHERE value < $1 ORDER BY eql_v3.ord_term(value) LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "10000" +} \ No newline at end of file diff --git a/results/query/v3/ore_metadata_100000.json b/results/query/v3/ore_metadata_100000.json new file mode 100644 index 0000000..4407c31 --- /dev/null +++ b/results/query/v3/ore_metadata_100000.json @@ -0,0 +1,260 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_100000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbM7>vz?)OlK0@C8sAWl#gx17Gc|N!NlqitFJr$Tj%C!2JHMAXiB%lAlQHv^j3n!Upn$Ih$!;%{yCqgfO1vQ%cXW~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_100000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a224d70c5ea374cca13c04aaed3707721fe675e47b0fd068818959436da37ff1646c9c8e3fb17c006b23834b591f29bc5459622027791bfcbb080e9693c4c132dbeef804e87f52b24950fffe745a206dd6712f10cee0427ad228e3a61039afc59b0e6d82848f5c189a1328f9b9e9b8e5410af593917ff9f371c7f6d354b9ea47a16df425b34404c29e3d23b6049bf25fe8bd67c1f095171907a69ed1f9608aa1e2e424020526692f76d77e05771a91e0d7ca1de6ea87b061169deb3d797d7f43bf8dea32d21ff12e4aabdb2956c225defe9c17379d7e69b042353c5239a8673e11890048c4a1ecfa0a54fac43b4e5791ad2db7b8d56b1b24d3ef80a8e47e59909aac4c6a147403ae29cbbad6ceae9065ad4\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_100000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 49500, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.92, + "Total Cost": 73448.67 + } + ], + "Startup Cost": 0.92, + "Total Cost": 15.76 + } + } + ], + "id": "ORE/ore/range_gt_10/100000", + "indexes_used": [ + "integer_encrypted_v3_100000_ord_index" + ], + "parameters": [ + { + "c": "mBbM7>vz?)OlK0@C8sAWl#gx17Gc|N!NlqitFJr$Tj%C!2JHMAXiB%lAlQHv^j3n!Upn$Ih$!;%{yCqgfO1vQ%cXW~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_100000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a224d70c5ea374cca13c04aaed3707721fe675e47b0fd068818959436da37ff1646c9c8e3fb17c006b23834b591f29bc5459622027791bfcbb080e9693c4c132dbeef804e87f52b24950fffe745a206dd6712f10cee0427ad228e3a61039afc59b0e6d82848f5c189a1328f9b9e9b8e5410af593917ff9f371c7f6d354b9ea47a16df425b34404c29e3d23b6049bf25fe8bd67c1f095171907a69ed1f9608aa1e2e424020526692f76d77e05771a91e0d7ca1de6ea87b061169deb3d797d7f43bf8dea32d21ff12e4aabdb2956c225defe9c17379d7e69b042353c5239a8673e11890048c4a1ecfa0a54fac43b4e5791ad2db7b8d56b1b24d3ef80a8e47e59909aac4c6a147403ae29cbbad6ceae9065ad4" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_100000 WHERE value > $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_100000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbK#i|jR0mIE6R#Vn9^v*k_176|=1zfZjEt{rEpMy*}GbhPXwt~FW2Ah@YpZ(4)~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_100000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a229befb2abf146a7b30e21e3e247c39b3a20af8bfc5fb5ff1f5bc9638fe19d3b793e9a2c623eb3e4647a72cc8cf24f5290e8c8f4c4b28518aebb48b56b74d35db66a4f09d7aa7bb1ff88da81ae5e48d56292d219fa4f52e21c151a073c66debaaeea91f181e1faddb6568ef19cd4baf5e47d34bbaaf1603d137d60f36d1529f69946d7d3fcbdaec09f018958356e59ee39cd6c23476429a5e1c81cab96b4033d50bf4559505de93c207bee3fa62e5e8c8832346b5787ad5a8cca98cfe989f5d5c80611bfb87fcf92f79e1528b77bb9b4b5b4311afd90773349d70677517c7c316470d28a475ce4dd2043af0f2e786b8ad5652194ea0c829248f3b38db8178319e900b6973b5bd4c351c119d9226e684232\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_100000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 49500, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.92, + "Total Cost": 73448.67 + } + ], + "Startup Cost": 0.92, + "Total Cost": 149.3 + } + } + ], + "id": "ORE/ore/range_gt_100/100000", + "indexes_used": [ + "integer_encrypted_v3_100000_ord_index" + ], + "parameters": [ + { + "c": "mBbK#i|jR0mIE6R#Vn9^v*k_176|=1zfZjEt{rEpMy*}GbhPXwt~FW2Ah@YpZ(4)~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_100000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a229befb2abf146a7b30e21e3e247c39b3a20af8bfc5fb5ff1f5bc9638fe19d3b793e9a2c623eb3e4647a72cc8cf24f5290e8c8f4c4b28518aebb48b56b74d35db66a4f09d7aa7bb1ff88da81ae5e48d56292d219fa4f52e21c151a073c66debaaeea91f181e1faddb6568ef19cd4baf5e47d34bbaaf1603d137d60f36d1529f69946d7d3fcbdaec09f018958356e59ee39cd6c23476429a5e1c81cab96b4033d50bf4559505de93c207bee3fa62e5e8c8832346b5787ad5a8cca98cfe989f5d5c80611bfb87fcf92f79e1528b77bb9b4b5b4311afd90773349d70677517c7c316470d28a475ce4dd2043af0f2e786b8ad5652194ea0c829248f3b38db8178319e900b6973b5bd4c351c119d9226e684232" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_100000 WHERE value > $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_100000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbKFTD{B2qpFwEUS!1SXX~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_100000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22c88c465fd65d2916b9ff115fe0cecc3ebefe1e965e1679461b1999d48c334982310fc4af06ed982586b1175159c160ef63859e5ea14e4dda15a488e29f78594c84ae95a1f82140f4e5c90d60a5a6c57be60faeaa4282bef523e469219b5fcf8df1b97d56128592c48d66a6b617645e999e0fbed42a1da276fac8cb4b04f158b1afed5aa27940fb92f2ffc0085a45bcd60ed05cb1f35f1c07102b19fb57ae85f789a1a6562e261ba3df1571a4e76a5ddaee311599814c9e014f30800049b05dbe42438bf7ccaa41f77266e6bea8bd9e9cb6ed92c66c799bc80d78b4ba9952fffb4e00f0ef3fe3ea51a39022bc4043d948985f0b2d5aa317dd2176575f4adb2fc089b455892fcdafe625c4aa35b7480432\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_100000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50499, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.92, + "Total Cost": 73774.16 + } + ], + "Startup Cost": 0.92, + "Total Cost": 15.53 + } + } + ], + "id": "ORE/ore/range_lt_10/100000", + "indexes_used": [ + "integer_encrypted_v3_100000_ord_index" + ], + "parameters": [ + { + "c": "mBbKFTD{B2qpFwEUS!1SXX~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_100000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22c88c465fd65d2916b9ff115fe0cecc3ebefe1e965e1679461b1999d48c334982310fc4af06ed982586b1175159c160ef63859e5ea14e4dda15a488e29f78594c84ae95a1f82140f4e5c90d60a5a6c57be60faeaa4282bef523e469219b5fcf8df1b97d56128592c48d66a6b617645e999e0fbed42a1da276fac8cb4b04f158b1afed5aa27940fb92f2ffc0085a45bcd60ed05cb1f35f1c07102b19fb57ae85f789a1a6562e261ba3df1571a4e76a5ddaee311599814c9e014f30800049b05dbe42438bf7ccaa41f77266e6bea8bd9e9cb6ed92c66c799bc80d78b4ba9952fffb4e00f0ef3fe3ea51a39022bc4043d948985f0b2d5aa317dd2176575f4adb2fc089b455892fcdafe625c4aa35b7480432" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_100000 WHERE value < $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_100000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbKLXPjZ0wxB0~Y%m_Z{ihzp7M{lm2_~<2I!E2$C5n@KhCpvy95oljAbyP01^Sf*)8~r^ajk%0>WLZ1cp1!I2WS_jyjns>rKNUZY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_100000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22b63b960c2bc150eb18cf73aee22c17bbdbecc429c0a90997726b60a0d6127b83fab39e26bd8c9c6049babfe679ad1a5cffd0fa1f413526365cf252549dc1b9bed29d5ba969c24e2abd76cb8e9be4e98c718ed94a5417f4227dccc946e0f1d95f09719de46ef9383c6ed870cb1c9b2a70a8fbae841071aaa856f6b78fb230e8551aee998702d5baa038147a2621b440d5c1aea4df11474e33ed9e0420d6f885d8a5ee381a5fef942a4f930245b0f8845c26dfc4b71023cc357c197a7ce7f37f6b4283e400195a830d73568da2311fcb4eff4b788ae5343c0fde034249a15feec02a5c1b99256a2a77e00e9878275c15a20ef2e091c2a7611d92d267a5f785e1a9f6de9a9a362bb09d660ee996eeeec625\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_100000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50499, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.92, + "Total Cost": 73774.16 + } + ], + "Startup Cost": 0.92, + "Total Cost": 147.01 + } + } + ], + "id": "ORE/ore/range_lt_100/100000", + "indexes_used": [ + "integer_encrypted_v3_100000_ord_index" + ], + "parameters": [ + { + "c": "mBbKLXPjZ0wxB0~Y%m_Z{ihzp7M{lm2_~<2I!E2$C5n@KhCpvy95oljAbyP01^Sf*)8~r^ajk%0>WLZ1cp1!I2WS_jyjns>rKNUZY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_100000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22b63b960c2bc150eb18cf73aee22c17bbdbecc429c0a90997726b60a0d6127b83fab39e26bd8c9c6049babfe679ad1a5cffd0fa1f413526365cf252549dc1b9bed29d5ba969c24e2abd76cb8e9be4e98c718ed94a5417f4227dccc946e0f1d95f09719de46ef9383c6ed870cb1c9b2a70a8fbae841071aaa856f6b78fb230e8551aee998702d5baa038147a2621b440d5c1aea4df11474e33ed9e0420d6f885d8a5ee381a5fef942a4f930245b0f8845c26dfc4b71023cc357c197a7ce7f37f6b4283e400195a830d73568da2311fcb4eff4b788ae5343c0fde034249a15feec02a5c1b99256a2a77e00e9878275c15a20ef2e091c2a7611d92d267a5f785e1a9f6de9a9a362bb09d660ee996eeeec625" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_100000 WHERE value < $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1096, + "Plans": [ + { + "Alias": "integer_encrypted_v3_100000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbKMtz)X5AXWDA>)Ze{a9;?-7IUKW56CpW=hm!Q4<`~#)?1fbp6Oo1AR~9V??kFoo|kb;*$Kj@VH?U~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_100000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2208a4f2ea6045fd0227fd35672c13ed2b06acf3b1ff8e3ca02b607723f1fa9d102847fa67cf5bde64f39e76043d1c9462c541dc21a4584200bb99d9a4e1a66ff6c39eafb837e502f74b34f8038b1480b183d1caf36e67e1711f8c62a177685ed2ebb12be39b0f1a8838894e145efce628f13702a7e17f3d476f01caa87c53471528d3e031f700f4a5b3904b0599731316863164a746541cd8cba08be6ed4b3b44f6fe7e99f9e46ed77d512b27962fa0d284057f71e5ce25eac4f6b32beda95cd9acb3e33190af25d5b0d495429926a0a6095843e39012889c729c6bf98eefd8a14689b1a8d1f845e85aafddd9ce317ecdd93c359bc3c0f993f39d8eb9d1a0a885f29db45f9f2b28dfb1b8688843a15eb1\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_100000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50499, + "Plan Width": 1096, + "Relation Name": "integer_encrypted_v3_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.92, + "Total Cost": 86398.91 + } + ], + "Startup Cost": 0.92, + "Total Cost": 18.03 + } + } + ], + "id": "ORE/ore/range_lt_ordered_10/100000", + "indexes_used": [ + "integer_encrypted_v3_100000_ord_index" + ], + "parameters": [ + { + "c": "mBbKMtz)X5AXWDA>)Ze{a9;?-7IUKW56CpW=hm!Q4<`~#)?1fbp6Oo1AR~9V??kFoo|kb;*$Kj@VH?U~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_100000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2208a4f2ea6045fd0227fd35672c13ed2b06acf3b1ff8e3ca02b607723f1fa9d102847fa67cf5bde64f39e76043d1c9462c541dc21a4584200bb99d9a4e1a66ff6c39eafb837e502f74b34f8038b1480b183d1caf36e67e1711f8c62a177685ed2ebb12be39b0f1a8838894e145efce628f13702a7e17f3d476f01caa87c53471528d3e031f700f4a5b3904b0599731316863164a746541cd8cba08be6ed4b3b44f6fe7e99f9e46ed77d512b27962fa0d284057f71e5ce25eac4f6b32beda95cd9acb3e33190af25d5b0d495429926a0a6095843e39012889c729c6bf98eefd8a14689b1a8d1f845e85aafddd9ce317ecdd93c359bc3c0f993f39d8eb9d1a0a885f29db45f9f2b28dfb1b8688843a15eb1" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_100000 WHERE value < $1 ORDER BY eql_v3.ord_term(value) LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "100000" +} \ No newline at end of file diff --git a/results/query/v3/ore_metadata_1000000.json b/results/query/v3/ore_metadata_1000000.json new file mode 100644 index 0000000..3d89c14 --- /dev/null +++ b/results/query/v3/ore_metadata_1000000.json @@ -0,0 +1,260 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_1000000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbLmQ9%&7tznj=CG@e~bhK5(7L>6%{yVA%!jbf*8KAiiF~piFmi0BnAXzKt+KSI#^4ieD+h6Cz5E<*V_e%AWn%0hE17B_Wtfh8gY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_1000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a225cd2430565ba1a784083ff052802607d00cb7d7e94883d348720cb39e670c30fe11a955210cf6309c20887f0d02efac0806cbde21d80f3965bdb17c9cd42382e52d9d97d1017784e7b3f1e1dcfe15c224966ce98b12913cf9b4a0dc643ad00862d3868cd9e6e73b189b7be4ed120b51fa95d425a6c4222656b73726cc9a6e634315437b04a978949e948690d6efb3328493f6819bebffbc178bdc345a84481c2faa7ef50ce83c15c69a91aa4c7beef189211dd12c6ad83842b928a403171bef4aac1da9bfa84583a955108b85076ee2a8f2415813fec8d712531a24648e3450942f015bc12b79154b51dabd1502ff4dc999662015a348a93db7b46deddc37fd5649b5869208c225ffd72b8a5bb448521\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_1000000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 495003, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 1.05, + "Total Cost": 734361.89 + } + ], + "Startup Cost": 1.05, + "Total Cost": 15.89 + } + } + ], + "id": "ORE/ore/range_gt_10/1000000", + "indexes_used": [ + "integer_encrypted_v3_1000000_ord_index" + ], + "parameters": [ + { + "c": "mBbLmQ9%&7tznj=CG@e~bhK5(7L>6%{yVA%!jbf*8KAiiF~piFmi0BnAXzKt+KSI#^4ieD+h6Cz5E<*V_e%AWn%0hE17B_Wtfh8gY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_1000000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a225cd2430565ba1a784083ff052802607d00cb7d7e94883d348720cb39e670c30fe11a955210cf6309c20887f0d02efac0806cbde21d80f3965bdb17c9cd42382e52d9d97d1017784e7b3f1e1dcfe15c224966ce98b12913cf9b4a0dc643ad00862d3868cd9e6e73b189b7be4ed120b51fa95d425a6c4222656b73726cc9a6e634315437b04a978949e948690d6efb3328493f6819bebffbc178bdc345a84481c2faa7ef50ce83c15c69a91aa4c7beef189211dd12c6ad83842b928a403171bef4aac1da9bfa84583a955108b85076ee2a8f2415813fec8d712531a24648e3450942f015bc12b79154b51dabd1502ff4dc999662015a348a93db7b46deddc37fd5649b5869208c225ffd72b8a5bb448521" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_1000000 WHERE value > $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_1000000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbK2YcyBewbxQPWU}V@%St1}7Qzqlz}9)a$Ml_>v4_uxcrOf@r);gnAfoJNLqP7KH!)wfuPw1DdMBws&RD7UEU(=;M&(kcfTea}Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_1000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22e1cd5d41661cb22e5b2385b8b97e1a9f317d623b4bab1f6d4528b82da90b25ff919d14d7bec2bdaef50adc8c7e4951676f362392a11633a0986dfac9755d53509737858ad643fcd0b2fbb1b2be383fa693e33394ff427ac2592f63ee7cffecb58a916253bf9f55bd00a5fdeb73e037949477ef2458af2aff0106164139462075279af880b889e3045b66560012de8e1457d4a47d110dccf889f37f966b10a67907bc369a9f37195d17d9c9f4ba5b6170835fa1c15827b00a21ee00772448b0068244346a4acd273443577ec2404e1dd257799ad9fda26714c006f0968b24ef25a2b16b04b6f10e2ffb3fd87e52c57d7e131c76aba1efbd0dd997dcfda1fdaa7321e4cc1d15259472f6595680c965f56e\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_1000000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 495003, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 1.05, + "Total Cost": 734361.89 + } + ], + "Startup Cost": 1.05, + "Total Cost": 149.41 + } + } + ], + "id": "ORE/ore/range_gt_100/1000000", + "indexes_used": [ + "integer_encrypted_v3_1000000_ord_index" + ], + "parameters": [ + { + "c": "mBbK2YcyBewbxQPWU}V@%St1}7Qzqlz}9)a$Ml_>v4_uxcrOf@r);gnAfoJNLqP7KH!)wfuPw1DdMBws&RD7UEU(=;M&(kcfTea}Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_1000000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22e1cd5d41661cb22e5b2385b8b97e1a9f317d623b4bab1f6d4528b82da90b25ff919d14d7bec2bdaef50adc8c7e4951676f362392a11633a0986dfac9755d53509737858ad643fcd0b2fbb1b2be383fa693e33394ff427ac2592f63ee7cffecb58a916253bf9f55bd00a5fdeb73e037949477ef2458af2aff0106164139462075279af880b889e3045b66560012de8e1457d4a47d110dccf889f37f966b10a67907bc369a9f37195d17d9c9f4ba5b6170835fa1c15827b00a21ee00772448b0068244346a4acd273443577ec2404e1dd257799ad9fda26714c006f0968b24ef25a2b16b04b6f10e2ffb3fd87e52c57d7e131c76aba1efbd0dd997dcfda1fdaa7321e4cc1d15259472f6595680c965f56e" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_1000000 WHERE value > $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_1000000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbKXO((pb&-TKHzogfx6Th{@7JJGi@x~wAt5vp+M86W|kW9++Y$a;MAPDcUn`+#~$*tzvqFn?nAbMI@dhBP6=BAH}DSv3-zom9zY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_1000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22ead7035b93898b22b6be67d1fb64aca6f2caede02374ac8c6a1cbc6eb472121a86e1d001c89ec9c70d69c0542eb9761829d9e500050d2e8f3820878165c30c7326f717c2e803e21f01f27b42951963ee0998348cb3639ccd316c0bf71f2b30eb0a8473661604cfe0eb298de6b5d926ed306715bd34e5d97478616eac80e414ef32b7b5382a5aca4bfb9ca8dfea00e29af9ab50296c6e474ea61730c54ea0ff77274cc042dff2bbf92219228663fa9e29d8dd4d606883f92c3b0afaa071e381e9e811a6b4100744f7b818de57da629d1acac2a5c28eb1a93d6d64f22264e964eaa521bc724f5ad3a4ce651e54c334bc265be6dab56524fd1b438ef1697a76e85cb7cdce7134d5af04970e9ec0a0496eb9\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_1000000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 505002, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 1.05, + "Total Cost": 737652.95 + } + ], + "Startup Cost": 1.05, + "Total Cost": 15.66 + } + } + ], + "id": "ORE/ore/range_lt_10/1000000", + "indexes_used": [ + "integer_encrypted_v3_1000000_ord_index" + ], + "parameters": [ + { + "c": "mBbKXO((pb&-TKHzogfx6Th{@7JJGi@x~wAt5vp+M86W|kW9++Y$a;MAPDcUn`+#~$*tzvqFn?nAbMI@dhBP6=BAH}DSv3-zom9zY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_1000000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22ead7035b93898b22b6be67d1fb64aca6f2caede02374ac8c6a1cbc6eb472121a86e1d001c89ec9c70d69c0542eb9761829d9e500050d2e8f3820878165c30c7326f717c2e803e21f01f27b42951963ee0998348cb3639ccd316c0bf71f2b30eb0a8473661604cfe0eb298de6b5d926ed306715bd34e5d97478616eac80e414ef32b7b5382a5aca4bfb9ca8dfea00e29af9ab50296c6e474ea61730c54ea0ff77274cc042dff2bbf92219228663fa9e29d8dd4d606883f92c3b0afaa071e381e9e811a6b4100744f7b818de57da629d1acac2a5c28eb1a93d6d64f22264e964eaa521bc724f5ad3a4ce651e54c334bc265be6dab56524fd1b438ef1697a76e85cb7cdce7134d5af04970e9ec0a0496eb9" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_1000000 WHERE value < $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_1000000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbK1?UWs05B(c}lWsY?n>Dh;7M3x~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_1000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22525d6862ef1d96f693d80c1778bfc5f12fb17cd78c0abd7a5c66eaf97961b0fbccb2facb9a8b20764743ab536d3768686465a00d736cb03e605cad68f45064a4f5e0bc50d1c2512874928f746b8fb819da186cea14fa0f4f69e0bc32430239ee50b5fb928f937ef6058b84185dd0cb10584ed2ccb2221b5b9a5e1b8910e81846a2a5795b17b3f4659c34a30e6ac187ccdeab77588ace709d3f66094aca19470f9e98132123075d2fdc27f0edfb99314366ee59b912374161e3186118d1182a775f7a4c112b447ee0d9e67181a0bff4937087bd829d7c34bdcc0d7ce4e89b2e9cef8ab9e6a81c17d6198c3babf199ab7846c2117234541b7d32d9beb5051c4e37b8e56b3959193843e450de4f8178deef\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_1000000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 505002, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 1.05, + "Total Cost": 737652.95 + } + ], + "Startup Cost": 1.05, + "Total Cost": 147.12 + } + } + ], + "id": "ORE/ore/range_lt_100/1000000", + "indexes_used": [ + "integer_encrypted_v3_1000000_ord_index" + ], + "parameters": [ + { + "c": "mBbK1?UWs05B(c}lWsY?n>Dh;7M3x~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_1000000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22525d6862ef1d96f693d80c1778bfc5f12fb17cd78c0abd7a5c66eaf97961b0fbccb2facb9a8b20764743ab536d3768686465a00d736cb03e605cad68f45064a4f5e0bc50d1c2512874928f746b8fb819da186cea14fa0f4f69e0bc32430239ee50b5fb928f937ef6058b84185dd0cb10584ed2ccb2221b5b9a5e1b8910e81846a2a5795b17b3f4659c34a30e6ac187ccdeab77588ace709d3f66094aca19470f9e98132123075d2fdc27f0edfb99314366ee59b912374161e3186118d1182a775f7a4c112b447ee0d9e67181a0bff4937087bd829d7c34bdcc0d7ce4e89b2e9cef8ab9e6a81c17d6198c3babf199ab7846c2117234541b7d32d9beb5051c4e37b8e56b3959193843e450de4f8178deef" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_1000000 WHERE value < $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1096, + "Plans": [ + { + "Alias": "integer_encrypted_v3_1000000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbKu&>F~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_1000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2201ac5855cc2df164043fb66b64b9870102bf83134a98c3d38125ec4a49c055afb2b22a0d5f21141f5394467d53147beef7e4a32d34dd3f0c4baaf2782374ab1b6351ff48477b49bdf4eeaaec2abf0eff153c247a5693e277e3af8293f89272bbcf3fb9d25229dcac6207143cb565cecac64726265b78a8834f22c248afad6174f0a1b050569a227baada68744b40e20a7fa976694eeabd8cb534f5fb746d70cff8d995847e85a8ad8bc09fb66c3d7be22722a306c933bfb927f0d1ca314f7e3b58fed5084f39039f7d298c857e60ca5cfc7048ab2adfed30181d53b21a148841e011fc24d33394150a237a2781435e07fdc38a2737f779c7999be5f88da07d4a9c62c9c14d3227d27832ea78b06d0593\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_1000000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 505002, + "Plan Width": 1096, + "Relation Name": "integer_encrypted_v3_1000000", + "Scan Direction": "Forward", + "Startup Cost": 1.05, + "Total Cost": 863903.45 + } + ], + "Startup Cost": 1.05, + "Total Cost": 18.16 + } + } + ], + "id": "ORE/ore/range_lt_ordered_10/1000000", + "indexes_used": [ + "integer_encrypted_v3_1000000_ord_index" + ], + "parameters": [ + { + "c": "mBbKu&>F~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_1000000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2201ac5855cc2df164043fb66b64b9870102bf83134a98c3d38125ec4a49c055afb2b22a0d5f21141f5394467d53147beef7e4a32d34dd3f0c4baaf2782374ab1b6351ff48477b49bdf4eeaaec2abf0eff153c247a5693e277e3af8293f89272bbcf3fb9d25229dcac6207143cb565cecac64726265b78a8834f22c248afad6174f0a1b050569a227baada68744b40e20a7fa976694eeabd8cb534f5fb746d70cff8d995847e85a8ad8bc09fb66c3d7be22722a306c933bfb927f0d1ca314f7e3b58fed5084f39039f7d298c857e60ca5cfc7048ab2adfed30181d53b21a148841e011fc24d33394150a237a2781435e07fdc38a2737f779c7999be5f88da07d4a9c62c9c14d3227d27832ea78b06d0593" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_1000000 WHERE value < $1 ORDER BY eql_v3.ord_term(value) LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "1000000" +} \ No newline at end of file diff --git a/results/query/v3/ore_metadata_10000000.json b/results/query/v3/ore_metadata_10000000.json new file mode 100644 index 0000000..e24426b --- /dev/null +++ b/results/query/v3/ore_metadata_10000000.json @@ -0,0 +1,260 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_10000000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbLPsC~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a226aa4c7f033219508c87aafbb5d35ac5e55474798d0c0a4ad729691cdadbbfafb2d9ccbe3fab97a5c0ab07fc6c807de0cae7900f000cfb3cc09fb33996117d5b10eda8defd7533f233431030c6afe1b311e3685e493b26dae96452712d2da99d5e0c40f46e3813c84d883dd679ee03bb06322bf406c4625103e6e81c5c5ce351e4fcf8549ec05b2ec041708d73d3509ce5b537618b251502c8919138010dce9928fa9cb5e69185c52e4734a30b1dc2a44f73579b4c06f26a803f8e00e10d820aad10669b675796c4979906b8fa070780fba8fe01ef68b861512e52a8ce287691aefdf26c343cb59beccbde14b3db602a9cccfb1cf2d0a0f39a9f568882c6bfd9a93de2fdf945cc53e969581b00dd11d81\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5050002, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 1.19, + "Total Cost": 7376457.78 + } + ], + "Startup Cost": 1.19, + "Total Cost": 15.79 + } + } + ], + "id": "ORE/ore/range_gt_10/10000000", + "indexes_used": [ + "integer_encrypted_v3_10000000_ord_index" + ], + "parameters": [ + { + "c": "mBbLPsC~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_10000000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a226aa4c7f033219508c87aafbb5d35ac5e55474798d0c0a4ad729691cdadbbfafb2d9ccbe3fab97a5c0ab07fc6c807de0cae7900f000cfb3cc09fb33996117d5b10eda8defd7533f233431030c6afe1b311e3685e493b26dae96452712d2da99d5e0c40f46e3813c84d883dd679ee03bb06322bf406c4625103e6e81c5c5ce351e4fcf8549ec05b2ec041708d73d3509ce5b537618b251502c8919138010dce9928fa9cb5e69185c52e4734a30b1dc2a44f73579b4c06f26a803f8e00e10d820aad10669b675796c4979906b8fa070780fba8fe01ef68b861512e52a8ce287691aefdf26c343cb59beccbde14b3db602a9cccfb1cf2d0a0f39a9f568882c6bfd9a93de2fdf945cc53e969581b00dd11d81" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_10000000 WHERE value > $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_10000000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbL}UZVLggZ2PgHzVLUw9uQx7S$IQ{eMo*Jdj@d$_PAfiVqCvKeA}VAONW+@M$?#cOZn_9w9#KG~mY~%Ah`77lQj&l{H{8_oa4WY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2287e1ec8ee908056d639839e3ad5f07a78213def4d88544e05668bf927ebca7d36432b9044e4d898a0917da9f4bb6bfa716e059f123b7aac2d6214959e435ee36249a1a0a7a496d092a98d59f6a7dd30044ccddfb9c749c1bf888d0a311e193968b604e15a56bf3fd33c508bd0b28d5c8016bcc1d495036a87b5f2329fd57d2447a095a3b3c7a9a485386451add7815f96ff733be3f565e9aa0a41fd29f56ca2cb6f2e7d29b25d4775006e5c5da5f07a7ee28bccceeb145ea7e5b6022eada5ef31d1cdfb9d7b49a8da68b8ecc9b2d85b31e895b0e7e8c60df2f8947f11c9ede1fb2d091fda1c1c009292f0faf0592b7651514a67ab9bff6003651c5a885757d2c5c40b582eed3792645563a0bb2c1acf0\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5050002, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 1.19, + "Total Cost": 7376457.78 + } + ], + "Startup Cost": 1.19, + "Total Cost": 147.26 + } + } + ], + "id": "ORE/ore/range_gt_100/10000000", + "indexes_used": [ + "integer_encrypted_v3_10000000_ord_index" + ], + "parameters": [ + { + "c": "mBbL}UZVLggZ2PgHzVLUw9uQx7S$IQ{eMo*Jdj@d$_PAfiVqCvKeA}VAONW+@M$?#cOZn_9w9#KG~mY~%Ah`77lQj&l{H{8_oa4WY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_10000000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2287e1ec8ee908056d639839e3ad5f07a78213def4d88544e05668bf927ebca7d36432b9044e4d898a0917da9f4bb6bfa716e059f123b7aac2d6214959e435ee36249a1a0a7a496d092a98d59f6a7dd30044ccddfb9c749c1bf888d0a311e193968b604e15a56bf3fd33c508bd0b28d5c8016bcc1d495036a87b5f2329fd57d2447a095a3b3c7a9a485386451add7815f96ff733be3f565e9aa0a41fd29f56ca2cb6f2e7d29b25d4775006e5c5da5f07a7ee28bccceeb145ea7e5b6022eada5ef31d1cdfb9d7b49a8da68b8ecc9b2d85b31e895b0e7e8c60df2f8947f11c9ede1fb2d091fda1c1c009292f0faf0592b7651514a67ab9bff6003651c5a885757d2c5c40b582eed3792645563a0bb2c1acf0" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_10000000 WHERE value > $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_10000000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbLd@jaGvOfiXZh6S2Kt>Ht&7Gn>yay5es2-X+@8~q*d&W)-0_A$c5AQxYuS-dW93T%B+$3kDPh{Y|K-DWhu3obrMC^4{BwxxDqY;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22c64e22de1875dbc1aa91b3918bdf16eda0eb462640a7a718dbcac6d51970b717b9f3a882d5b7ea24d6ae323f6766b239a6c08dcd7c31fab33f4e2e8fed569b0813d0d4915f0bfd0542c1fd57357c06b338df05d167b3fe2afcbd4adc50edf32bb0abb3dfa46664e22bfc90a150e9de133510098754506b2ebcc3787a999aa89773a1bcafa354cc0f90472a14c0a6af39d946162aec5622b10f246f0a24dc3fde6bbdc5fe5110e19fe6f0856135077c8293a38b8df9a6d6dc1a6b5049f22381d8edfff5db644320384bfa8fe3752a2ccaa82c4d32e0a69ffbb6a5fbaa43d875c8754fb7b0421accd1d3a7325bce897ac88f16f92b8c84aa859392632231b1221088005830210e3b03c97150d36eed201a\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4950001, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 1.19, + "Total Cost": 7343539.07 + } + ], + "Startup Cost": 1.19, + "Total Cost": 16.02 + } + } + ], + "id": "ORE/ore/range_lt_10/10000000", + "indexes_used": [ + "integer_encrypted_v3_10000000_ord_index" + ], + "parameters": [ + { + "c": "mBbLd@jaGvOfiXZh6S2Kt>Ht&7Gn>yay5es2-X+@8~q*d&W)-0_A$c5AQxYuS-dW93T%B+$3kDPh{Y|K-DWhu3obrMC^4{BwxxDqY;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_10000000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a22c64e22de1875dbc1aa91b3918bdf16eda0eb462640a7a718dbcac6d51970b717b9f3a882d5b7ea24d6ae323f6766b239a6c08dcd7c31fab33f4e2e8fed569b0813d0d4915f0bfd0542c1fd57357c06b338df05d167b3fe2afcbd4adc50edf32bb0abb3dfa46664e22bfc90a150e9de133510098754506b2ebcc3787a999aa89773a1bcafa354cc0f90472a14c0a6af39d946162aec5622b10f246f0a24dc3fde6bbdc5fe5110e19fe6f0856135077c8293a38b8df9a6d6dc1a6b5049f22381d8edfff5db644320384bfa8fe3752a2ccaa82c4d32e0a69ffbb6a5fbaa43d875c8754fb7b0421accd1d3a7325bce897ac88f16f92b8c84aa859392632231b1221088005830210e3b03c97150d36eed201a" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_10000000 WHERE value < $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 100, + "Plan Width": 1064, + "Plans": [ + { + "Alias": "integer_encrypted_v3_10000000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbJ*qyP~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a220cbbfdd194506cd9d450d97af4846b14a16c993321bd4655404405d5180bdae7aa718f21ff459f7d4c98195a46ddd0841fcb2ee8db127774f5960efb80d26458ce40d96ffb2c1caedb96521595a2c3e83867c8c665da06f57f28e1ee60d9e883b058838f0e810f185951a325480644e7f384c2b2e08f59b0b57ca41e2e333554b92b76579f75662e439f3d0468aba6f2967a888df221bef3f0b9f49e2c6a16ac48d9b1e6869492d006caf44bef6bd5c4ed69fa19057bdf1bfb8cd2fc027371159846a2e45696bea01fa234b4197c7d90c18da79ca2a4bdcbf8f6c69e0e72053a272a7c3e7ed853a6d455c1bc806484746f9b2a09f32fe2a5413d3ae9c747695fb1e547a435ed266fd1af081ba1e32015\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4950001, + "Plan Width": 1064, + "Relation Name": "integer_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 1.19, + "Total Cost": 7343539.07 + } + ], + "Startup Cost": 1.19, + "Total Cost": 149.54 + } + } + ], + "id": "ORE/ore/range_lt_100/10000000", + "indexes_used": [ + "integer_encrypted_v3_10000000_ord_index" + ], + "parameters": [ + { + "c": "mBbJ*qyP~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_10000000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a220cbbfdd194506cd9d450d97af4846b14a16c993321bd4655404405d5180bdae7aa718f21ff459f7d4c98195a46ddd0841fcb2ee8db127774f5960efb80d26458ce40d96ffb2c1caedb96521595a2c3e83867c8c665da06f57f28e1ee60d9e883b058838f0e810f185951a325480644e7f384c2b2e08f59b0b57ca41e2e333554b92b76579f75662e439f3d0468aba6f2967a888df221bef3f0b9f49e2c6a16ac48d9b1e6869492d006caf44bef6bd5c4ed69fa19057bdf1bfb8cd2fc027371159846a2e45696bea01fa234b4197c7d90c18da79ca2a4bdcbf8f6c69e0e72053a272a7c3e7ed853a6d455c1bc806484746f9b2a09f32fe2a5413d3ae9c747695fb1e547a435ed266fd1af081ba1e32015" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_10000000 WHERE value < $1 LIMIT 100", + "rows_returned": 100 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1096, + "Plans": [ + { + "Alias": "integer_encrypted_v3_10000000", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((value)::jsonb) < eql_v3_internal.ore_block_256((('{\"c\": \"mBbLM!LZm@RyJ%Bi*J#RGi4^k7Ktp1y)VEanN$@nNtg)i5pfhZqzBH#Ag_q$u=7zUnpYI*dvfopY{m%`0YD8Se;KqpG5ZizEv0s0Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg\", \"i\": {\"c\": \"value\", \"t\": \"integer_encrypted_v3_10000000\"}, \"v\": 3, \"ob\": [\"6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2298db740f0e43f420833b65d7338d47bcf878829cd80b00ae4ea0ea7d9aa2f236494ad4fbf9f06a4efb59f1b7203520abd9e77e9fea9478eee17f8eafaab26a1f397c513575061606a79c178bd990f7e5c36af0b7da0565dae1f0bfafd9b06508da4b0b9dd0ed9430f2b0ee6d203e083033e6a44bad70b2bf0cdda811ffeaa6f6181b55fe8582fc0e7e7c19334163c65f8755d87d790beea9f7c57b38956e64a17bb2b23725ab712ce81a135c2922b14cabcca408a0dc57971e33cd4ba22c429db0b57df7bccf4434c3e177ed5c240fa371955889c54dafa8e08c834e2afa6df20948a2cf1925a8bfd0607a7bd03e6d981b3a5304f5faf9f76c1ca3dfd2114ce902db6407c7bfe847f405f15dc53487b8\"]}'::jsonb)::eql_v3.integer_ord)::jsonb))", + "Index Name": "integer_encrypted_v3_10000000_ord_index", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4950001, + "Plan Width": 1096, + "Relation Name": "integer_encrypted_v3_10000000", + "Scan Direction": "Forward", + "Startup Cost": 1.19, + "Total Cost": 8581039.32 + } + ], + "Startup Cost": 1.19, + "Total Cost": 18.52 + } + } + ], + "id": "ORE/ore/range_lt_ordered_10/10000000", + "indexes_used": [ + "integer_encrypted_v3_10000000_ord_index" + ], + "parameters": [ + { + "c": "mBbLM!LZm@RyJ%Bi*J#RGi4^k7Ktp1y)VEanN$@nNtg)i5pfhZqzBH#Ag_q$u=7zUnpYI*dvfopY{m%`0YD8Se;KqpG5ZizEv0s0Y;|SC5al#Uy4?0l?zPD$ZD>~0Vg", + "i": { + "c": "value", + "t": "integer_encrypted_v3_10000000" + }, + "ob": [ + "6a6a6a6ab06c241e413a084c2f2db73ff9b3a65b1371a8aff562d9da3bea15a04f6b769a39b089467ffd328aa870db838f4f023047d3775fb47f5c7d2d1631c795176e1460cb7f91f12252f877e7cd2d93b71ec8363578de5b1d06b35a2fc3c8a768f7315c94c75cd4c047c46455b718955448fbc7e8151d504d143d8d7055b2e717822be1cb0a2298db740f0e43f420833b65d7338d47bcf878829cd80b00ae4ea0ea7d9aa2f236494ad4fbf9f06a4efb59f1b7203520abd9e77e9fea9478eee17f8eafaab26a1f397c513575061606a79c178bd990f7e5c36af0b7da0565dae1f0bfafd9b06508da4b0b9dd0ed9430f2b0ee6d203e083033e6a44bad70b2bf0cdda811ffeaa6f6181b55fe8582fc0e7e7c19334163c65f8755d87d790beea9f7c57b38956e64a17bb2b23725ab712ce81a135c2922b14cabcca408a0dc57971e33cd4ba22c429db0b57df7bccf4434c3e177ed5c240fa371955889c54dafa8e08c834e2afa6df20948a2cf1925a8bfd0607a7bd03e6d981b3a5304f5faf9f76c1ca3dfd2114ce902db6407c7bfe847f405f15dc53487b8" + ], + "v": 3 + } + ], + "query": "SELECT id, value FROM integer_encrypted_v3_10000000 WHERE value < $1 ORDER BY eql_v3.ord_term(value) LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "10000000" +} \ No newline at end of file diff --git a/results/query/v3/ore_rows_10000.json b/results/query/v3/ore_rows_10000.json new file mode 100644 index 0000000..0347d53 --- /dev/null +++ b/results/query/v3/ore_rows_10000.json @@ -0,0 +1,11 @@ +{"reason":"benchmark-complete","id":"ORE/ore/range_gt_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_gt_10_10000","iteration_count":[160,320,480,640,800,960,1120,1280,1440,1600],"measured_values":[78583625.0,144369708.0,236223666.0,323668667.0,439225250.0,451696500.0,618704333.0,600583334.0,724046500.0,867942542.0],"unit":"ns","throughput":[],"typical":{"estimate":513123.61818181816,"lower_bound":485122.11367907166,"upper_bound":536417.3584375,"unit":"ns"},"mean":{"estimate":502661.11443551595,"lower_bound":482348.8213973214,"upper_bound":523884.55267658737,"unit":"ns"},"median":{"estimate":497471.3534722222,"lower_bound":470517.1875,"upper_bound":542464.08875,"unit":"ns"},"median_abs_dev":{"estimate":40934.42942009153,"lower_bound":5015.666157204209,"upper_bound":64195.49702561462,"unit":"ns"},"slope":{"estimate":513123.61818181816,"lower_bound":485122.11367907166,"upper_bound":536417.3584375,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_gt_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_gt_10_10000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[98169333.0,223081834.0,332962000.0,433858000.0,541365417.0,649036500.0,730539833.0,841809375.0,1047451666.0,1041691250.0],"unit":"ns","throughput":[],"typical":{"estimate":26994758.70844156,"lower_bound":26240839.153811254,"upper_bound":28129312.64479603,"unit":"ns"},"mean":{"estimate":26893739.1334623,"lower_bound":26159364.56547619,"upper_bound":27621418.909739584,"unit":"ns"},"median":{"estimate":27055729.175,"lower_bound":26090708.32142857,"upper_bound":27746833.333333332,"unit":"ns"},"median_abs_dev":{"estimate":1170280.1195139997,"lower_bound":70948.56153040903,"upper_bound":2227733.4374914933,"unit":"ns"},"slope":{"estimate":26994758.70844156,"lower_bound":26240839.153811254,"upper_bound":28129312.64479603,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_gt_100/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_gt_100_10000","iteration_count":[95,190,285,380,475,570,665,760,855,950],"measured_values":[86223750.0,178967333.0,264024792.0,410010791.0,417357209.0,549835708.0,596369709.0,759771084.0,1046751667.0,881033625.0],"unit":"ns","throughput":[],"typical":{"estimate":1004673.5239097745,"lower_bound":921990.515574641,"upper_bound":1114703.1796123823,"unit":"ns"},"mean":{"estimate":974637.1223249793,"lower_bound":921308.65613797,"upper_bound":1043482.5660150375,"unit":"ns"},"median":{"estimate":934668.5736842105,"lower_bound":907618.4210526316,"upper_bound":1021799.9074561403,"unit":"ns"},"median_abs_dev":{"estimate":50280.5205841844,"lower_bound":12254.867059274804,"upper_bound":138361.19300228203,"unit":"ns"},"slope":{"estimate":1004673.5239097745,"lower_bound":921990.515574641,"upper_bound":1114703.1796123823,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_gt_100/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_gt_100_10000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[131940583.0,255926292.0,376503042.0,522522625.0,660318125.0,792983042.0,868456959.0,1025920541.0,1091663042.0,1239990459.0],"unit":"ns","throughput":[],"typical":{"estimate":41934473.31515151,"lower_bound":41173138.72575251,"upper_bound":43158785.57373608,"unit":"ns"},"mean":{"estimate":42595438.384034395,"lower_bound":41823469.7829365,"upper_bound":43350037.77640972,"unit":"ns"},"median":{"estimate":42700535.60416667,"lower_bound":41355093.28571428,"upper_bound":43980194.333333336,"unit":"ns"},"median_abs_dev":{"estimate":1927625.6758402996,"lower_bound":68427.33232267937,"upper_bound":2250359.2427231334,"unit":"ns"},"slope":{"estimate":41934473.31515151,"lower_bound":41173138.72575251,"upper_bound":43158785.57373608,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_lt_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_lt_10_10000","iteration_count":[198,396,594,792,990,1188,1386,1584,1782,1980],"measured_values":[86153167.0,167882000.0,252826458.0,335783375.0,476600833.0,524341125.0,673338375.0,799641291.0,837249750.0,988602875.0],"unit":"ns","throughput":[],"typical":{"estimate":479920.7189951463,"lower_bound":457852.34442556405,"upper_bound":493263.58414014045,"unit":"ns"},"mean":{"estimate":459121.3364411977,"lower_bound":440219.0568181818,"upper_bound":478213.8556962482,"unit":"ns"},"median":{"estimate":455600.8522727273,"lower_bound":425633.76767676766,"upper_bound":490354.6820707071,"unit":"ns"},"median_abs_dev":{"estimate":44611.6968882871,"lower_bound":2468.3211675421103,"upper_bound":51871.61576886748,"unit":"ns"},"slope":{"estimate":479920.7189951463,"lower_bound":457852.34442556405,"upper_bound":493263.58414014045,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_lt_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_lt_10_10000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[99796708.0,211166000.0,302536416.0,429764625.0,524698208.0,611964666.0,711649208.0,846015916.0,952724208.0,1059000500.0],"unit":"ns","throughput":[],"typical":{"estimate":26206668.927272726,"lower_bound":25785668.111961536,"upper_bound":26452532.58035714,"unit":"ns"},"mean":{"estimate":25994363.65636905,"lower_bound":25599145.876065474,"upper_bound":26368355.066864587,"unit":"ns"},"median":{"estimate":26315330.2,"lower_bound":25354947.875,"upper_bound":26464561.333333332,"unit":"ns"},"median_abs_dev":{"estimate":522350.48448767624,"lower_bound":35186.76138781379,"upper_bound":936739.6512195468,"unit":"ns"},"slope":{"estimate":26206668.927272726,"lower_bound":25785668.111961536,"upper_bound":26452532.58035714,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_lt_100/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_lt_100_10000","iteration_count":[101,202,303,404,505,606,707,808,909,1010],"measured_values":[89619000.0,194978875.0,284754625.0,347758584.0,476456917.0,524269542.0,654831666.0,705763000.0,824554000.0,915934083.0],"unit":"ns","throughput":[],"typical":{"estimate":901710.924263855,"lower_bound":884691.2366423231,"upper_bound":917784.198609234,"unit":"ns"},"mean":{"estimate":907538.8193085023,"lower_bound":886839.1798631933,"upper_bound":928746.8264702184,"unit":"ns"},"median":{"estimate":906982.7693619363,"lower_bound":873469.0594059406,"upper_bound":939784.2409240924,"unit":"ns"},"median_abs_dev":{"estimate":49159.44318665133,"lower_bound":10061.330594643006,"upper_bound":58079.21283344228,"unit":"ns"},"slope":{"estimate":901710.924263855,"lower_bound":884691.2366423231,"upper_bound":917784.198609234,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_lt_100/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_lt_100_10000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[131914542.0,266013666.0,377524209.0,514909334.0,590145000.0,884062417.0,857105750.0,999921292.0,1171037083.0,1277923083.0],"unit":"ns","throughput":[],"typical":{"estimate":42795607.36103896,"lower_bound":41419864.455461755,"upper_bound":44636568.14518634,"unit":"ns"},"mean":{"estimate":43006807.582751326,"lower_bound":41622446.857929885,"upper_bound":44664303.00371032,"unit":"ns"},"median":{"estimate":42753273.63333333,"lower_bound":41380846.92857143,"upper_bound":43971514.0,"unit":"ns"},"median_abs_dev":{"estimate":1711014.3911734242,"lower_bound":539810.2026164532,"upper_bound":3691933.883655075,"unit":"ns"},"slope":{"estimate":42795607.36103896,"lower_bound":41419864.455461755,"upper_bound":44636568.14518634,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_lt_ordered_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_lt_ordered_10_10000","iteration_count":[148,296,444,592,740,888,1036,1184,1332,1480],"measured_values":[75082417.0,144914000.0,276376375.0,297332083.0,372473708.0,486007750.0,523580541.0,646874292.0,684106333.0,780950583.0],"unit":"ns","throughput":[],"typical":{"estimate":525944.2587574588,"lower_bound":513311.6056964657,"upper_bound":539987.4967119526,"unit":"ns"},"mean":{"estimate":526525.2088315103,"lower_bound":507296.8513089876,"upper_bound":551895.9830694981,"unit":"ns"},"median":{"estimate":510453.48573573574,"lower_bound":503342.84864864865,"upper_bound":546346.5304054054,"unit":"ns"},"median_abs_dev":{"estimate":18843.23233989142,"lower_bound":2325.0743501068123,"upper_bound":50623.10946700341,"unit":"ns"},"slope":{"estimate":525944.2587574588,"lower_bound":513311.6056964657,"upper_bound":539987.4967119526,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_lt_ordered_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_lt_ordered_10_10000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[101313792.0,209716791.0,314207958.0,421809250.0,530736625.0,672272916.0,777879000.0,823488750.0,954500208.0,1051844375.0],"unit":"ns","throughput":[],"typical":{"estimate":26610349.02012987,"lower_bound":26146527.262798633,"upper_bound":27260608.61982422,"unit":"ns"},"mean":{"estimate":26496374.458630953,"lower_bound":26040339.195833333,"upper_bound":27001626.988095235,"unit":"ns"},"median":{"estimate":26329593.75,"lower_bound":25974311.15625,"upper_bound":27147643.76190476,"unit":"ns"},"median_abs_dev":{"estimate":290247.4231220791,"lower_bound":83109.27276201546,"upper_bound":1434654.729104787,"unit":"ns"},"slope":{"estimate":26610349.02012987,"lower_bound":26146527.262798633,"upper_bound":27260608.61982422,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"ORE","benchmarks":["ORE/ore/range_gt_10/10000","ORE/ore_decrypt/range_gt_10/10000","ORE/ore/range_gt_100/10000","ORE/ore_decrypt/range_gt_100/10000","ORE/ore/range_lt_10/10000","ORE/ore_decrypt/range_lt_10/10000","ORE/ore/range_lt_100/10000","ORE/ore_decrypt/range_lt_100/10000","ORE/ore/range_lt_ordered_10/10000","ORE/ore_decrypt/range_lt_ordered_10/10000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE"} diff --git a/results/query/v3/ore_rows_100000.json b/results/query/v3/ore_rows_100000.json new file mode 100644 index 0000000..e8151af --- /dev/null +++ b/results/query/v3/ore_rows_100000.json @@ -0,0 +1,11 @@ +{"reason":"benchmark-complete","id":"ORE/ore/range_gt_10/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_gt_10_100000","iteration_count":[174,348,522,696,870,1044,1218,1392,1566,1740],"measured_values":[86238500.0,195470292.0,367501125.0,349511708.0,429370791.0,575752083.0,633379917.0,738766958.0,815696584.0,928022500.0],"unit":"ns","throughput":[],"typical":{"estimate":530592.4030900134,"lower_bound":519326.11902113457,"upper_bound":546933.1085135399,"unit":"ns"},"mean":{"estimate":541349.8307548804,"lower_bound":512929.5344412516,"upper_bound":582168.8349708081,"unit":"ns"},"median":{"estimate":525801.2170338442,"lower_bound":502171.9942528736,"upper_bound":551486.6695402298,"unit":"ns"},"median_abs_dev":{"estimate":36556.96814150127,"lower_bound":6406.573515226129,"upper_bound":56803.13929973231,"unit":"ns"},"slope":{"estimate":530592.4030900134,"lower_bound":519326.11902113457,"upper_bound":546933.1085135399,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_gt_10/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_gt_10_100000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[102213584.0,195588625.0,303903625.0,424771209.0,494895250.0,605364958.0,881958792.0,828127875.0,954777208.0,1020151708.0],"unit":"ns","throughput":[],"typical":{"estimate":26496168.207142856,"lower_bound":25422713.385093167,"upper_bound":28302382.205536913,"unit":"ns"},"mean":{"estimate":26124668.53780754,"lower_bound":25219323.970000003,"upper_bound":27457442.817519844,"unit":"ns"},"median":{"estimate":25528594.35,"lower_bound":25035032.291666664,"upper_bound":26521589.111111112,"unit":"ns"},"median_abs_dev":{"estimate":840807.3481195606,"lower_bound":169086.01742312405,"upper_bound":1661027.092673793,"unit":"ns"},"slope":{"estimate":26496168.207142856,"lower_bound":25422713.385093167,"upper_bound":28302382.205536913,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_gt_100/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_gt_100_100000","iteration_count":[93,186,279,372,465,558,651,744,837,930],"measured_values":[85207916.0,176228292.0,262501167.0,397960166.0,454575792.0,559793750.0,603492458.0,746763625.0,851385208.0,899718042.0],"unit":"ns","throughput":[],"typical":{"estimate":986087.2398547688,"lower_bound":960748.0716562546,"upper_bound":1010420.8504071624,"unit":"ns"},"mean":{"estimate":977048.850847841,"lower_bound":950500.3061938045,"upper_bound":1005750.6810987368,"unit":"ns"},"median":{"estimate":972510.5516129032,"lower_bound":937243.8402457756,"upper_bound":1010200.6170848268,"unit":"ns"},"median_abs_dev":{"estimate":46590.81676276699,"lower_bound":10357.460243716845,"upper_bound":86820.21538142892,"unit":"ns"},"slope":{"estimate":986087.2398547688,"lower_bound":960748.0716562546,"upper_bound":1010420.8504071624,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_gt_100/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_gt_100_100000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[103555709.0,199511125.0,337774708.0,415163708.0,490076292.0,597933041.0,739010000.0,824633792.0,905311083.0,982952834.0],"unit":"ns","throughput":[],"typical":{"estimate":33733337.700432904,"lower_bound":33128443.65238095,"upper_bound":34591191.84502924,"unit":"ns"},"mean":{"estimate":34163400.59809524,"lower_bound":33397853.678587303,"upper_bound":35090146.255555555,"unit":"ns"},"median":{"estimate":33944890.722222224,"lower_bound":33008474.316666666,"upper_bound":34854761.02380952,"unit":"ns"},"median_abs_dev":{"estimate":1052219.7338193683,"lower_bound":175861.8081778251,"upper_bound":2203974.0063149757,"unit":"ns"},"slope":{"estimate":33733337.700432904,"lower_bound":33128443.65238095,"upper_bound":34591191.84502924,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_lt_10/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_lt_10_100000","iteration_count":[184,368,552,736,920,1104,1288,1472,1656,1840],"measured_values":[125929875.0,177295500.0,262236750.0,364535417.0,506479708.0,563555333.0,684304625.0,732319083.0,772377625.0,895151625.0],"unit":"ns","throughput":[],"typical":{"estimate":496763.1739836251,"lower_bound":481426.76137046685,"upper_bound":519908.6166554444,"unit":"ns"},"mean":{"estimate":517922.90610917006,"lower_bound":487933.5998814106,"upper_bound":560304.2980848862,"unit":"ns"},"median":{"estimate":496396.0315896739,"lower_bound":480781.01222826086,"upper_bound":531292.4107142857,"unit":"ns"},"median_abs_dev":{"estimate":26645.462483538104,"lower_bound":8157.212177123434,"upper_bound":62944.798771908565,"unit":"ns"},"slope":{"estimate":496763.1739836251,"lower_bound":481426.76137046685,"upper_bound":519908.6166554444,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_lt_10/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_lt_10_100000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[104359708.0,216483625.0,307312583.0,428335875.0,499846583.0,625474833.0,710539042.0,837558916.0,943716625.0,990065000.0],"unit":"ns","throughput":[],"typical":{"estimate":25644827.511038963,"lower_bound":25117671.81422652,"upper_bound":26174047.52929155,"unit":"ns"},"mean":{"estimate":25910062.0930754,"lower_bound":25477240.1656875,"upper_bound":26335714.116666667,"unit":"ns"},"median":{"estimate":26075689.1875,"lower_bound":25300855.53333333,"upper_bound":26472354.15625,"unit":"ns"},"median_abs_dev":{"estimate":861101.6784811383,"lower_bound":83221.85769751668,"upper_bound":1284553.8470654413,"unit":"ns"},"slope":{"estimate":25644827.511038963,"lower_bound":25117671.81422652,"upper_bound":26174047.52929155,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_lt_100/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_lt_100_100000","iteration_count":[94,188,282,376,470,564,658,752,846,940],"measured_values":[84198125.0,168753500.0,257442375.0,385726209.0,426684625.0,546675167.0,562829958.0,774658209.0,819409292.0,894369583.0],"unit":"ns","throughput":[],"typical":{"estimate":956227.3017131804,"lower_bound":912894.2513125398,"upper_bound":992485.0380071746,"unit":"ns"},"mean":{"estimate":941477.6554377744,"lower_bound":908436.1905965047,"upper_bound":976130.2158421986,"unit":"ns"},"median":{"estimate":932186.6132978724,"lower_bound":897625.0,"upper_bound":997218.2401004728,"unit":"ns"},"median_abs_dev":{"estimate":53999.38154380158,"lower_bound":7526.560717440659,"upper_bound":96474.8878662177,"unit":"ns"},"slope":{"estimate":956227.3017131804,"lower_bound":912894.2513125398,"upper_bound":992485.0380071746,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_lt_100/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_lt_100_100000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[94798250.0,183679875.0,310972708.0,391997500.0,523224958.0,626817875.0,726630625.0,848128500.0,882173792.0,962576166.0],"unit":"ns","throughput":[],"typical":{"estimate":33573044.43896104,"lower_bound":32632555.681557845,"upper_bound":34819507.94074994,"unit":"ns"},"mean":{"estimate":33383571.11962963,"lower_bound":32395152.921388887,"upper_bound":34321008.39185185,"unit":"ns"},"median":{"estimate":33612813.25925926,"lower_bound":32085872.2,"upper_bound":34823215.277777776,"unit":"ns"},"median_abs_dev":{"estimate":1837869.9389701714,"lower_bound":200664.09958749826,"upper_bound":2920136.7741738763,"unit":"ns"},"slope":{"estimate":33573044.43896104,"lower_bound":32632555.681557845,"upper_bound":34819507.94074994,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_lt_ordered_10/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_lt_ordered_10_100000","iteration_count":[156,312,468,624,780,936,1092,1248,1404,1560],"measured_values":[83094208.0,165180250.0,246083083.0,376429708.0,417638458.0,532078000.0,581538250.0,702763042.0,774806333.0,860494709.0],"unit":"ns","throughput":[],"typical":{"estimate":552933.0544788545,"lower_bound":543525.6769626769,"upper_bound":562662.1441864223,"unit":"ns"},"mean":{"estimate":549415.480232499,"lower_bound":536677.1442454212,"upper_bound":564501.2982702482,"unit":"ns"},"median":{"estimate":543516.546474359,"lower_bound":531039.5288461539,"upper_bound":563111.4118589744,"unit":"ns"},"median_abs_dev":{"estimate":18580.706232626504,"lower_bound":2142.1609111998437,"upper_bound":38715.62551748927,"unit":"ns"},"slope":{"estimate":552933.0544788545,"lower_bound":543525.6769626769,"upper_bound":562662.1441864223,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_lt_ordered_10/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_lt_ordered_10_100000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[101325250.0,202889167.0,290833833.0,406750083.0,513767333.0,607266333.0,740703208.0,818020083.0,938042834.0,1038562583.0],"unit":"ns","throughput":[],"typical":{"estimate":25828658.78831169,"lower_bound":25489829.76707485,"upper_bound":26054880.751811594,"unit":"ns"},"mean":{"estimate":25537924.53951389,"lower_bound":25171300.13638889,"upper_bound":25866370.00875,"unit":"ns"},"median":{"estimate":25492503.890625,"lower_bound":25331312.5,"upper_bound":25964064.575,"unit":"ns"},"median_abs_dev":{"estimate":285847.3320326943,"lower_bound":45022.345056943595,"upper_bound":937189.6342109264,"unit":"ns"},"slope":{"estimate":25828658.78831169,"lower_bound":25489829.76707485,"upper_bound":26054880.751811594,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"ORE","benchmarks":["ORE/ore/range_gt_10/100000","ORE/ore_decrypt/range_gt_10/100000","ORE/ore/range_gt_100/100000","ORE/ore_decrypt/range_gt_100/100000","ORE/ore/range_lt_10/100000","ORE/ore_decrypt/range_lt_10/100000","ORE/ore/range_lt_100/100000","ORE/ore_decrypt/range_lt_100/100000","ORE/ore/range_lt_ordered_10/100000","ORE/ore_decrypt/range_lt_ordered_10/100000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE"} diff --git a/results/query/v3/ore_rows_1000000.json b/results/query/v3/ore_rows_1000000.json new file mode 100644 index 0000000..9f26f7d --- /dev/null +++ b/results/query/v3/ore_rows_1000000.json @@ -0,0 +1,11 @@ +{"reason":"benchmark-complete","id":"ORE/ore/range_gt_10/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_gt_10_1000000","iteration_count":[169,338,507,676,845,1014,1183,1352,1521,1690],"measured_values":[85109792.0,168405250.0,291665292.0,364481750.0,438518166.0,569433542.0,653090666.0,704160584.0,911987125.0,923548875.0],"unit":"ns","throughput":[],"typical":{"estimate":553482.3247368017,"lower_bound":531982.9471232531,"upper_bound":576767.3051786863,"unit":"ns"},"mean":{"estimate":541579.5099896684,"lower_bound":523310.90501267964,"upper_bound":561082.7096374566,"unit":"ns"},"median":{"estimate":542826.4053254437,"lower_bound":512218.5355029586,"upper_bound":563669.9129332206,"unit":"ns"},"median_abs_dev":{"estimate":34001.62671256336,"lower_bound":9554.56320699986,"upper_bound":56321.81871837188,"unit":"ns"},"slope":{"estimate":553482.3247368017,"lower_bound":531982.9471232531,"upper_bound":576767.3051786863,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_gt_10/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_gt_10_1000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[102386917.0,183167417.0,309119208.0,428382667.0,527453416.0,629984292.0,751144250.0,835516375.0,922356958.0,1018724875.0],"unit":"ns","throughput":[],"typical":{"estimate":25946353.894155845,"lower_bound":25626056.022082172,"upper_bound":26412606.595081966,"unit":"ns"},"mean":{"estimate":25767413.8924504,"lower_bound":25026670.28597842,"upper_bound":26312703.437990326,"unit":"ns"},"median":{"estimate":25934910.359375,"lower_bound":25544574.243055556,"upper_bound":26511631.09375,"unit":"ns"},"median_abs_dev":{"estimate":575205.4608030623,"lower_bound":113348.27886683308,"upper_bound":1292092.2343701532,"unit":"ns"},"slope":{"estimate":25946353.894155845,"lower_bound":25626056.022082172,"upper_bound":26412606.595081966,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_gt_100/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_gt_100_1000000","iteration_count":[98,196,294,392,490,588,686,784,882,980],"measured_values":[139468000.0,169080125.0,236348708.0,345006500.0,497005458.0,534352792.0,669949792.0,818046125.0,800661834.0,925684792.0],"unit":"ns","throughput":[],"typical":{"estimate":952946.365915717,"lower_bound":914843.5512376274,"upper_bound":995928.5562865321,"unit":"ns"},"mean":{"estimate":976526.8004093781,"lower_bound":893752.3225085035,"upper_bound":1091158.4078328474,"unit":"ns"},"median":{"estimate":926669.7850340136,"lower_bound":880118.6224489796,"upper_bound":1014296.8530612245,"unit":"ns"},"median_abs_dev":{"estimate":84470.76014881364,"lower_bound":21963.2536600742,"upper_bound":177555.438796868,"unit":"ns"},"slope":{"estimate":952946.365915717,"lower_bound":914843.5512376274,"upper_bound":995928.5562865321,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_gt_100/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_gt_100_1000000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[110796958.0,201871084.0,325112125.0,423079625.0,486954416.0,679915917.0,761148750.0,854027000.0,1037842250.0,1088337625.0],"unit":"ns","throughput":[],"typical":{"estimate":36433485.136796534,"lower_bound":35211026.5345679,"upper_bound":37455015.87148594,"unit":"ns"},"mean":{"estimate":35874059.86843915,"lower_bound":34780350.69666667,"upper_bound":36881553.14880953,"unit":"ns"},"median":{"estimate":36184374.00793651,"lower_bound":34614819.5,"upper_bound":37025513.66666667,"unit":"ns"},"median_abs_dev":{"estimate":1242184.465371821,"lower_bound":138692.52087105328,"upper_bound":3060031.3659235854,"unit":"ns"},"slope":{"estimate":36433485.136796534,"lower_bound":35211026.5345679,"upper_bound":37455015.87148594,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_lt_10/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_lt_10_1000000","iteration_count":[183,366,549,732,915,1098,1281,1464,1647,1830],"measured_values":[138445250.0,185568708.0,267203375.0,345554167.0,472129625.0,508896750.0,625008834.0,625576125.0,825735250.0,919341708.0],"unit":"ns","throughput":[],"typical":{"estimate":484169.23216237314,"lower_bound":457708.4758322772,"upper_bound":501861.2981302674,"unit":"ns"},"mean":{"estimate":512073.50340901205,"lower_bound":472486.2515702792,"upper_bound":571895.3714211443,"unit":"ns"},"median":{"estimate":494632.0693902334,"lower_bound":472068.53415300546,"upper_bound":509180.58961748634,"unit":"ns"},"median_abs_dev":{"estimate":25013.574476320944,"lower_bound":4196.62029999423,"upper_bound":62146.16467694463,"unit":"ns"},"slope":{"estimate":484169.23216237314,"lower_bound":457708.4758322772,"upper_bound":501861.2981302674,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_lt_10/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_lt_10_1000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[105063667.0,218670500.0,315916417.0,428586084.0,534233500.0,672531666.0,789696875.0,822910375.0,924800291.0,1047474125.0],"unit":"ns","throughput":[],"typical":{"estimate":26506468.015584417,"lower_bound":25950892.526397515,"upper_bound":27416859.56931795,"unit":"ns"},"mean":{"estimate":26724171.44707341,"lower_bound":26232826.871726193,"upper_bound":27259228.26361607,"unit":"ns"},"median":{"estimate":26519021.541666664,"lower_bound":25990932.984375,"upper_bound":27404391.5,"unit":"ns"},"median_abs_dev":{"estimate":841553.9453125522,"lower_bound":103422.4367763838,"upper_bound":1531827.3429108784,"unit":"ns"},"slope":{"estimate":26506468.015584417,"lower_bound":25950892.526397515,"upper_bound":27416859.56931795,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_lt_100/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_lt_100_1000000","iteration_count":[108,216,324,432,540,648,756,864,972,1080],"measured_values":[82858625.0,165762209.0,251952208.0,381887208.0,460892000.0,592208375.0,676397500.0,819228167.0,898431417.0,1017169042.0],"unit":"ns","throughput":[],"typical":{"estimate":916346.3145262145,"lower_bound":883787.0257277573,"upper_bound":932334.1018357768,"unit":"ns"},"mean":{"estimate":867268.2861364639,"lower_bound":823743.2412229937,"upper_bound":907698.274376984,"unit":"ns"},"median":{"estimate":889351.9272486772,"lower_bound":777630.2716049383,"upper_bound":927862.500154321,"unit":"ns"},"median_abs_dev":{"estimate":65471.23183265324,"lower_bound":7937.485297970398,"upper_bound":116305.90794487964,"unit":"ns"},"slope":{"estimate":916346.3145262145,"lower_bound":883787.0257277573,"upper_bound":932334.1018357768,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_lt_100/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_lt_100_1000000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[127249208.0,253365333.0,387951291.0,487940083.0,650050542.0,726263291.0,862321792.0,979810042.0,1161306042.0,1219028000.0],"unit":"ns","throughput":[],"typical":{"estimate":41449518.435497835,"lower_bound":40750776.35290915,"upper_bound":42419219.21577696,"unit":"ns"},"mean":{"estimate":41762995.66095238,"lower_bound":41088957.54132937,"upper_bound":42458011.20666666,"unit":"ns"},"median":{"estimate":41645248.98809524,"lower_bound":40661673.583333336,"upper_bound":43011334.88888889,"unit":"ns"},"median_abs_dev":{"estimate":1478565.616175214,"lower_bound":141700.7897593081,"upper_bound":1782437.388813749,"unit":"ns"},"slope":{"estimate":41449518.435497835,"lower_bound":40750776.35290915,"upper_bound":42419219.21577696,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_lt_ordered_10/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_lt_ordered_10_1000000","iteration_count":[160,320,480,640,800,960,1120,1280,1440,1600],"measured_values":[78950416.0,163700375.0,309274084.0,339063417.0,397248041.0,532908542.0,575302958.0,637561000.0,819437417.0,837329000.0],"unit":"ns","throughput":[],"typical":{"estimate":531655.097435065,"lower_bound":511242.6715176399,"upper_bound":555187.4516034985,"unit":"ns"},"mean":{"estimate":533492.6758516865,"lower_bound":509970.23335019837,"upper_bound":563524.58466906,"unit":"ns"},"median":{"estimate":518496.99017857143,"lower_bound":498094.53125,"upper_bound":555113.0645833333,"unit":"ns"},"median_abs_dev":{"estimate":31386.19507428364,"lower_bound":4587.839828174565,"upper_bound":63250.373981956276,"unit":"ns"},"slope":{"estimate":531655.097435065,"lower_bound":511242.6715176399,"upper_bound":555187.4516034985,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_lt_ordered_10/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_lt_ordered_10_1000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[107023875.0,229579208.0,327068083.0,429683666.0,504931125.0,647324208.0,744428500.0,846676333.0,956826750.0,1153609750.0],"unit":"ns","throughput":[],"typical":{"estimate":27147188.63051948,"lower_bound":26340236.29632867,"upper_bound":28057914.270971302,"unit":"ns"},"mean":{"estimate":27024680.284077384,"lower_bound":26430002.11895833,"upper_bound":27656779.650416665,"unit":"ns"},"median":{"estimate":26805598.9375,"lower_bound":26522683.77455357,"upper_bound":27834621.5,"unit":"ns"},"median_abs_dev":{"estimate":425537.056779583,"lower_bound":101045.15280296428,"upper_bound":1980857.699832747,"unit":"ns"},"slope":{"estimate":27147188.63051948,"lower_bound":26340236.29632867,"upper_bound":28057914.270971302,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"ORE","benchmarks":["ORE/ore/range_gt_10/1000000","ORE/ore_decrypt/range_gt_10/1000000","ORE/ore/range_gt_100/1000000","ORE/ore_decrypt/range_gt_100/1000000","ORE/ore/range_lt_10/1000000","ORE/ore_decrypt/range_lt_10/1000000","ORE/ore/range_lt_100/1000000","ORE/ore_decrypt/range_lt_100/1000000","ORE/ore/range_lt_ordered_10/1000000","ORE/ore_decrypt/range_lt_ordered_10/1000000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE"} diff --git a/results/query/v3/ore_rows_10000000.json b/results/query/v3/ore_rows_10000000.json new file mode 100644 index 0000000..e79677f --- /dev/null +++ b/results/query/v3/ore_rows_10000000.json @@ -0,0 +1,11 @@ +{"reason":"benchmark-complete","id":"ORE/ore/range_gt_10/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_gt_10_10000000","iteration_count":[165,330,495,660,825,990,1155,1320,1485,1650],"measured_values":[86704667.0,171704917.0,324112292.0,349701583.0,424620959.0,556610750.0,606218125.0,732291000.0,822020000.0,907008208.0],"unit":"ns","throughput":[],"typical":{"estimate":548353.3090751673,"lower_bound":536270.7530810498,"upper_bound":559021.3252216219,"unit":"ns"},"mean":{"estimate":549022.9955704666,"lower_bound":529597.7942978354,"upper_bound":575959.9668027897,"unit":"ns"},"median":{"estimate":539776.4137878788,"lower_bound":522900.3803030303,"upper_bound":557890.9511784512,"unit":"ns"},"median_abs_dev":{"estimate":22166.153242835764,"lower_bound":3696.6449766441733,"upper_bound":44810.24150299456,"unit":"ns"},"slope":{"estimate":548353.3090751673,"lower_bound":536270.7530810498,"upper_bound":559021.3252216219,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_gt_10/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_gt_10_10000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[101159167.0,210366958.0,305394125.0,442454292.0,507794667.0,616290792.0,781780209.0,851469917.0,954439917.0,1028051833.0],"unit":"ns","throughput":[],"typical":{"estimate":26363187.724025972,"lower_bound":25836293.415929202,"upper_bound":27015236.290145986,"unit":"ns"},"mean":{"estimate":26249975.391458333,"lower_bound":25733688.908026043,"upper_bound":26827342.023239583,"unit":"ns"},"median":{"estimate":25998582.7875,"lower_bound":25449510.416666668,"upper_bound":27082806.583333336,"unit":"ns"},"median_abs_dev":{"estimate":858367.4212784322,"lower_bound":148173.41352939827,"upper_bound":1633738.315345346,"unit":"ns"},"slope":{"estimate":26363187.724025972,"lower_bound":25836293.415929202,"upper_bound":27015236.290145986,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_gt_100/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_gt_100_10000000","iteration_count":[92,184,276,368,460,552,644,736,828,920],"measured_values":[87993792.0,172870625.0,262187750.0,399620833.0,442902333.0,568942417.0,686655583.0,755925625.0,835385250.0,905329209.0],"unit":"ns","throughput":[],"typical":{"estimate":1012780.9489553925,"lower_bound":991426.2290054555,"upper_bound":1039252.0257608696,"unit":"ns"},"mean":{"estimate":1001165.5372347308,"lower_bound":972343.6282065216,"upper_bound":1031626.0366071429,"unit":"ns"},"median":{"estimate":996486.4360507247,"lower_bound":956393.3873188405,"upper_bound":1046654.1186917701,"unit":"ns"},"median_abs_dev":{"estimate":55033.016531120804,"lower_bound":9634.890798511746,"upper_bound":86198.18558598071,"unit":"ns"},"slope":{"estimate":1012780.9489553925,"lower_bound":991426.2290054555,"upper_bound":1039252.0257608696,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_gt_100/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_gt_100_10000000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[117519458.0,233521000.0,318576875.0,431353833.0,542544375.0,680090291.0,779642500.0,903366500.0,1024756958.0,1110171375.0],"unit":"ns","throughput":[],"typical":{"estimate":37288248.405194804,"lower_bound":36810946.70246913,"upper_bound":37669455.23757904,"unit":"ns"},"mean":{"estimate":37311509.96574074,"lower_bound":36585126.51111111,"upper_bound":38035551.58333333,"unit":"ns"},"median":{"estimate":37383052.083333336,"lower_bound":36169625.0,"upper_bound":38351480.30555555,"unit":"ns"},"median_abs_dev":{"estimate":1322728.5553279873,"lower_bound":232538.81843272224,"upper_bound":2180379.47379053,"unit":"ns"},"slope":{"estimate":37288248.405194804,"lower_bound":36810946.70246913,"upper_bound":37669455.23757904,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_lt_10/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_lt_10_10000000","iteration_count":[196,392,588,784,980,1176,1372,1568,1764,1960],"measured_values":[87728042.0,174509042.0,308308041.0,380504208.0,479533250.0,603294000.0,710083125.0,701114750.0,829903833.0,915266625.0],"unit":"ns","throughput":[],"typical":{"estimate":478431.1947124304,"lower_bound":463734.60654602305,"upper_bound":500992.29734842083,"unit":"ns"},"mean":{"estimate":480689.59269314865,"lower_bound":463339.9695153061,"upper_bound":498518.9032069971,"unit":"ns"},"median":{"estimate":477902.012755102,"lower_bound":447592.05102040817,"upper_bound":513005.10204081633,"unit":"ns"},"median_abs_dev":{"estimate":45273.01791677894,"lower_bound":2910.9091786781532,"upper_bound":49837.64133969482,"unit":"ns"},"slope":{"estimate":478431.1947124304,"lower_bound":463734.60654602305,"upper_bound":500992.29734842083,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_lt_10/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_lt_10_10000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[98874792.0,214087791.0,317468833.0,422743791.0,515085334.0,608683042.0,719640875.0,854808167.0,929819625.0,1051976458.0],"unit":"ns","throughput":[],"typical":{"estimate":26079253.003246754,"lower_bound":25737163.091540404,"upper_bound":26387782.887704916,"unit":"ns"},"mean":{"estimate":26001490.44193452,"lower_bound":25604872.26306845,"upper_bound":26363755.255668152,"unit":"ns"},"median":{"estimate":26063867.183333334,"lower_bound":25558030.058333334,"upper_bound":26567121.078125,"unit":"ns"},"median_abs_dev":{"estimate":559144.9830231917,"lower_bound":94043.61083039347,"upper_bound":1171782.8596816952,"unit":"ns"},"slope":{"estimate":26079253.003246754,"lower_bound":25737163.091540404,"upper_bound":26387782.887704916,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_lt_100/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_lt_100_10000000","iteration_count":[99,198,297,396,495,594,693,792,891,990],"measured_values":[86813500.0,172109541.0,257665083.0,349667875.0,465723333.0,519448292.0,644079583.0,733029833.0,782346792.0,909617583.0],"unit":"ns","throughput":[],"typical":{"estimate":906679.7442214352,"lower_bound":886519.5096774193,"upper_bound":922409.365838048,"unit":"ns"},"mean":{"estimate":896386.1211531985,"lower_bound":880202.7681830807,"upper_bound":913649.705997685,"unit":"ns"},"median":{"estimate":880527.2226430976,"lower_bound":873072.0732323232,"upper_bound":925542.7184343435,"unit":"ns"},"median_abs_dev":{"estimate":17980.33289113875,"lower_bound":2641.0197288701465,"upper_bound":43128.32131300594,"unit":"ns"},"slope":{"estimate":906679.7442214352,"lower_bound":886519.5096774193,"upper_bound":922409.365838048,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_lt_100/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_lt_100_10000000","iteration_count":[3,6,9,12,15,18,21,24,27,30],"measured_values":[107260458.0,210538041.0,343552042.0,443548375.0,575134500.0,660675917.0,775888000.0,885934167.0,1018983917.0,1096825458.0],"unit":"ns","throughput":[],"typical":{"estimate":37082868.69004329,"lower_bound":36709955.709484465,"upper_bound":37561384.878014185,"unit":"ns"},"mean":{"estimate":36918645.57236773,"lower_bound":36310796.767658725,"upper_bound":37495197.35046296,"unit":"ns"},"median":{"estimate":36930485.622023806,"lower_bound":36228851.80555555,"upper_bound":37740145.074074075,"unit":"ns"},"median_abs_dev":{"estimate":874212.4607107367,"lower_bound":47263.74719840417,"upper_bound":1805425.754455618,"unit":"ns"},"slope":{"estimate":37082868.69004329,"lower_bound":36709955.709484465,"upper_bound":37561384.878014185,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore/range_lt_ordered_10/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_range_lt_ordered_10_10000000","iteration_count":[171,342,513,684,855,1026,1197,1368,1539,1710],"measured_values":[87534459.0,175134167.0,305112375.0,353807292.0,442200333.0,573433292.0,739884541.0,717556375.0,833289292.0,922351791.0],"unit":"ns","throughput":[],"typical":{"estimate":547774.5094250778,"lower_bound":530802.3599612326,"upper_bound":574213.349636718,"unit":"ns"},"mean":{"estimate":543558.4731525573,"lower_bound":523938.6883484812,"upper_bound":566764.3465264435,"unit":"ns"},"median":{"estimate":531958.2630847953,"lower_bound":514675.1652046783,"upper_bound":568104.748862898,"unit":"ns"},"median_abs_dev":{"estimate":25674.885486504234,"lower_bound":3835.423273135702,"upper_bound":56833.399814592165,"unit":"ns"},"slope":{"estimate":547774.5094250778,"lower_bound":530802.3599612326,"upper_bound":574213.349636718,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"ORE/ore_decrypt/range_lt_ordered_10/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE/ore_decrypt_range_lt_ordered_10_10000000","iteration_count":[4,8,12,16,20,24,28,32,36,40],"measured_values":[101676334.0,219620125.0,320811583.0,437781500.0,512554958.0,633396083.0,738845833.0,834707750.0,936996000.0,1036710208.0],"unit":"ns","throughput":[],"typical":{"estimate":26147582.812987015,"lower_bound":25991471.023725837,"upper_bound":26441727.369795907,"unit":"ns"},"mean":{"estimate":26340388.304940473,"lower_bound":25959575.68452381,"upper_bound":26756130.006874997,"unit":"ns"},"median":{"estimate":26235984.183035716,"lower_bound":25827707.28333333,"upper_bound":26876423.604166664,"unit":"ns"},"median_abs_dev":{"estimate":605303.5993187126,"lower_bound":123694.78913773183,"upper_bound":1211136.9311667744,"unit":"ns"},"slope":{"estimate":26147582.812987015,"lower_bound":25991471.023725837,"upper_bound":26441727.369795907,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"ORE","benchmarks":["ORE/ore/range_gt_10/10000000","ORE/ore_decrypt/range_gt_10/10000000","ORE/ore/range_gt_100/10000000","ORE/ore_decrypt/range_gt_100/10000000","ORE/ore/range_lt_10/10000000","ORE/ore_decrypt/range_lt_10/10000000","ORE/ore/range_lt_100/10000000","ORE/ore_decrypt/range_lt_100/10000000","ORE/ore/range_lt_ordered_10/10000000","ORE/ore_decrypt/range_lt_ordered_10/10000000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/ORE"} diff --git a/results/query/v3/plaintext_metadata_10000.json b/results/query/v3/plaintext_metadata_10000.json new file mode 100644 index 0000000..94b9888 --- /dev/null +++ b/results/query/v3/plaintext_metadata_10000.json @@ -0,0 +1,204 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 37, + "Plans": [ + { + "Alias": "string_plaintext_10000", + "Async Capable": false, + "Index Cond": "(value = '267f4e4740f4d3598ed11f9332de54a0'::text)", + "Index Name": "string_plaintext_10000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 37, + "Relation Name": "string_plaintext_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.29, + "Total Cost": 8.3 + } + ], + "Startup Cost": 0.29, + "Total Cost": 8.3 + } + } + ], + "id": "PLAINTEXT/plaintext/exact_eq/10000", + "indexes_used": [ + "string_plaintext_10000_value_idx" + ], + "parameters": [], + "query": "SELECT id, value FROM string_plaintext_10000 WHERE value = $1 LIMIT 1", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_10000", + "Async Capable": false, + "Filter": "(value > 5000)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5019, + "Plan Width": 8, + "Relation Name": "integer_plaintext_10000", + "Startup Cost": 0.0, + "Total Cost": 170.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 0.34 + } + } + ], + "id": "PLAINTEXT/plaintext/range_gt_10/10000", + "indexes_used": [], + "parameters": [], + "query": "SELECT id, value FROM integer_plaintext_10000 WHERE value > $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_10000", + "Async Capable": false, + "Index Cond": "(value < 5000)", + "Index Name": "integer_plaintext_10000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4980, + "Plan Width": 8, + "Relation Name": "integer_plaintext_10000", + "Scan Direction": "Forward", + "Startup Cost": 0.29, + "Total Cost": 327.43 + } + ], + "Startup Cost": 0.29, + "Total Cost": 0.94 + } + } + ], + "id": "PLAINTEXT/plaintext/range_lt_ordered_10/10000", + "indexes_used": [ + "integer_plaintext_10000_value_idx" + ], + "parameters": [], + "query": "SELECT id, value FROM integer_plaintext_10000 WHERE value < $1 ORDER BY value LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_10000", + "Async Capable": false, + "Node Type": "Bitmap Heap Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 101, + "Plan Width": 4, + "Plans": [ + { + "Async Capable": false, + "Index Cond": "(value @> '{\"age\": 97}'::jsonb)", + "Index Name": "json_small_plaintext_10000_gin_idx", + "Node Type": "Bitmap Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 101, + "Plan Width": 0, + "Startup Cost": 0.0, + "Total Cost": 13.33 + } + ], + "Recheck Cond": "(value @> '{\"age\": 97}'::jsonb)", + "Relation Name": "json_small_plaintext_10000", + "Startup Cost": 13.36, + "Total Cost": 213.28 + } + ], + "Startup Cost": 13.36, + "Total Cost": 33.15 + } + } + ], + "id": "PLAINTEXT/plaintext/json_contains/10000", + "indexes_used": [ + "json_small_plaintext_10000_gin_idx" + ], + "parameters": [], + "query": "SELECT id FROM json_small_plaintext_10000 WHERE value @> $1::jsonb LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_10000", + "Async Capable": false, + "Filter": "((value -> 'age'::text) = '97'::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50, + "Plan Width": 4, + "Relation Name": "json_small_plaintext_10000", + "Startup Cost": 0.0, + "Total Cost": 421.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 84.2 + } + } + ], + "id": "PLAINTEXT/plaintext/json_field_eq/10000", + "indexes_used": [], + "parameters": [], + "query": "SELECT id FROM json_small_plaintext_10000 WHERE value -> 'age' = $1::jsonb LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "10000" +} \ No newline at end of file diff --git a/results/query/v3/plaintext_metadata_100000.json b/results/query/v3/plaintext_metadata_100000.json new file mode 100644 index 0000000..b152d4e --- /dev/null +++ b/results/query/v3/plaintext_metadata_100000.json @@ -0,0 +1,188 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 37, + "Plans": [ + { + "Alias": "string_plaintext_100000", + "Async Capable": false, + "Index Cond": "(value = 'd76d68cf03e259209831f84f5cfa3bfc'::text)", + "Index Name": "string_plaintext_100000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 37, + "Relation Name": "string_plaintext_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.42, + "Total Cost": 8.44 + } + ], + "Startup Cost": 0.42, + "Total Cost": 8.44 + } + } + ], + "id": "PLAINTEXT/plaintext/exact_eq/100000", + "indexes_used": [ + "string_plaintext_100000_value_idx" + ], + "parameters": [], + "query": "SELECT id, value FROM string_plaintext_100000 WHERE value = $1 LIMIT 1", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_100000", + "Async Capable": false, + "Filter": "(value > 5000)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 49805, + "Plan Width": 8, + "Relation Name": "integer_plaintext_100000", + "Startup Cost": 0.0, + "Total Cost": 1693.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 0.34 + } + } + ], + "id": "PLAINTEXT/plaintext/range_gt_10/100000", + "indexes_used": [], + "parameters": [], + "query": "SELECT id, value FROM integer_plaintext_100000 WHERE value > $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_100000", + "Async Capable": false, + "Index Cond": "(value < 5000)", + "Index Name": "integer_plaintext_100000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50194, + "Plan Width": 8, + "Relation Name": "integer_plaintext_100000", + "Scan Direction": "Forward", + "Startup Cost": 0.29, + "Total Cost": 3206.69 + } + ], + "Startup Cost": 0.29, + "Total Cost": 0.93 + } + } + ], + "id": "PLAINTEXT/plaintext/range_lt_ordered_10/100000", + "indexes_used": [ + "integer_plaintext_100000_value_idx" + ], + "parameters": [], + "query": "SELECT id, value FROM integer_plaintext_100000 WHERE value < $1 ORDER BY value LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_100000", + "Async Capable": false, + "Filter": "(value @> '{\"age\": 63}'::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1010, + "Plan Width": 4, + "Relation Name": "json_small_plaintext_100000", + "Startup Cost": 0.0, + "Total Cost": 3953.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 39.14 + } + } + ], + "id": "PLAINTEXT/plaintext/json_contains/100000", + "indexes_used": [], + "parameters": [], + "query": "SELECT id FROM json_small_plaintext_100000 WHERE value @> $1::jsonb LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_100000", + "Async Capable": false, + "Filter": "((value -> 'age'::text) = '63'::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500, + "Plan Width": 4, + "Relation Name": "json_small_plaintext_100000", + "Startup Cost": 0.0, + "Total Cost": 4203.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 84.06 + } + } + ], + "id": "PLAINTEXT/plaintext/json_field_eq/100000", + "indexes_used": [], + "parameters": [], + "query": "SELECT id FROM json_small_plaintext_100000 WHERE value -> 'age' = $1::jsonb LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "100000" +} \ No newline at end of file diff --git a/results/query/v3/plaintext_metadata_1000000.json b/results/query/v3/plaintext_metadata_1000000.json new file mode 100644 index 0000000..d0c4cdd --- /dev/null +++ b/results/query/v3/plaintext_metadata_1000000.json @@ -0,0 +1,188 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 37, + "Plans": [ + { + "Alias": "string_plaintext_1000000", + "Async Capable": false, + "Index Cond": "(value = '77156d51418f4afaec005ee57a10ba1e'::text)", + "Index Name": "string_plaintext_1000000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 37, + "Relation Name": "string_plaintext_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.42, + "Total Cost": 8.44 + } + ], + "Startup Cost": 0.42, + "Total Cost": 8.44 + } + } + ], + "id": "PLAINTEXT/plaintext/exact_eq/1000000", + "indexes_used": [ + "string_plaintext_1000000_value_idx" + ], + "parameters": [], + "query": "SELECT id, value FROM string_plaintext_1000000 WHERE value = $1 LIMIT 1", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_1000000", + "Async Capable": false, + "Filter": "(value > 5000)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 500922, + "Plan Width": 8, + "Relation Name": "integer_plaintext_1000000", + "Startup Cost": 0.0, + "Total Cost": 16925.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 0.34 + } + } + ], + "id": "PLAINTEXT/plaintext/range_gt_10/1000000", + "indexes_used": [], + "parameters": [], + "query": "SELECT id, value FROM integer_plaintext_1000000 WHERE value > $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_1000000", + "Async Capable": false, + "Index Cond": "(value < 5000)", + "Index Name": "integer_plaintext_1000000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 499077, + "Plan Width": 8, + "Relation Name": "integer_plaintext_1000000", + "Scan Direction": "Forward", + "Startup Cost": 0.42, + "Total Cost": 31914.21 + } + ], + "Startup Cost": 0.42, + "Total Cost": 1.06 + } + } + ], + "id": "PLAINTEXT/plaintext/range_lt_ordered_10/1000000", + "indexes_used": [ + "integer_plaintext_1000000_value_idx" + ], + "parameters": [], + "query": "SELECT id, value FROM integer_plaintext_1000000 WHERE value < $1 ORDER BY value LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_1000000", + "Async Capable": false, + "Filter": "(value @> '{\"age\": 74}'::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 10101, + "Plan Width": 4, + "Relation Name": "json_small_plaintext_1000000", + "Startup Cost": 0.0, + "Total Cost": 39528.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 39.13 + } + } + ], + "id": "PLAINTEXT/plaintext/json_contains/1000000", + "indexes_used": [], + "parameters": [], + "query": "SELECT id FROM json_small_plaintext_1000000 WHERE value @> $1::jsonb LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_1000000", + "Async Capable": false, + "Filter": "((value -> 'age'::text) = '74'::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5000, + "Plan Width": 4, + "Relation Name": "json_small_plaintext_1000000", + "Startup Cost": 0.0, + "Total Cost": 42028.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 84.06 + } + } + ], + "id": "PLAINTEXT/plaintext/json_field_eq/1000000", + "indexes_used": [], + "parameters": [], + "query": "SELECT id FROM json_small_plaintext_1000000 WHERE value -> 'age' = $1::jsonb LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "1000000" +} \ No newline at end of file diff --git a/results/query/v3/plaintext_metadata_10000000.json b/results/query/v3/plaintext_metadata_10000000.json new file mode 100644 index 0000000..d329dea --- /dev/null +++ b/results/query/v3/plaintext_metadata_10000000.json @@ -0,0 +1,188 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 1, + "Plan Width": 37, + "Plans": [ + { + "Alias": "string_plaintext_10000000", + "Async Capable": false, + "Index Cond": "(value = '311751f432da063c08c83d20cb7cd05b'::text)", + "Index Name": "string_plaintext_10000000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 1, + "Plan Width": 37, + "Relation Name": "string_plaintext_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.56, + "Total Cost": 8.58 + } + ], + "Startup Cost": 0.56, + "Total Cost": 8.58 + } + } + ], + "id": "PLAINTEXT/plaintext/exact_eq/10000000", + "indexes_used": [ + "string_plaintext_10000000_value_idx" + ], + "parameters": [], + "query": "SELECT id, value FROM string_plaintext_10000000 WHERE value = $1 LIMIT 1", + "rows_returned": 1 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_10000000", + "Async Capable": false, + "Filter": "(value > 5000)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4944950, + "Plan Width": 8, + "Relation Name": "integer_plaintext_10000000", + "Startup Cost": 0.0, + "Total Cost": 169248.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 0.34 + } + } + ], + "id": "PLAINTEXT/plaintext/range_gt_10/10000000", + "indexes_used": [], + "parameters": [], + "query": "SELECT id, value FROM integer_plaintext_10000000 WHERE value > $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 8, + "Plans": [ + { + "Alias": "integer_plaintext_10000000", + "Async Capable": false, + "Index Cond": "(value < 5000)", + "Index Name": "integer_plaintext_10000000_value_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 5055049, + "Plan Width": 8, + "Relation Name": "integer_plaintext_10000000", + "Scan Direction": "Forward", + "Startup Cost": 0.43, + "Total Cost": 320895.98 + } + ], + "Startup Cost": 0.43, + "Total Cost": 1.07 + } + } + ], + "id": "PLAINTEXT/plaintext/range_lt_ordered_10/10000000", + "indexes_used": [ + "integer_plaintext_10000000_value_idx" + ], + "parameters": [], + "query": "SELECT id, value FROM integer_plaintext_10000000 WHERE value < $1 ORDER BY value LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_10000000", + "Async Capable": false, + "Filter": "(value @> '{\"age\": 63}'::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 202020, + "Plan Width": 4, + "Relation Name": "json_small_plaintext_10000000", + "Startup Cost": 0.0, + "Total Cost": 395271.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 19.57 + } + } + ], + "id": "PLAINTEXT/plaintext/json_contains/10000000", + "indexes_used": [], + "parameters": [], + "query": "SELECT id FROM json_small_plaintext_10000000 WHERE value @> $1::jsonb LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 4, + "Plans": [ + { + "Alias": "json_small_plaintext_10000000", + "Async Capable": false, + "Filter": "((value -> 'age'::text) = '63'::jsonb)", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 50000, + "Plan Width": 4, + "Relation Name": "json_small_plaintext_10000000", + "Startup Cost": 0.0, + "Total Cost": 420271.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 84.05 + } + } + ], + "id": "PLAINTEXT/plaintext/json_field_eq/10000000", + "indexes_used": [], + "parameters": [], + "query": "SELECT id FROM json_small_plaintext_10000000 WHERE value -> 'age' = $1::jsonb LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "10000000" +} \ No newline at end of file diff --git a/results/query/v3/plaintext_rows_10000.json b/results/query/v3/plaintext_rows_10000.json new file mode 100644 index 0000000..af37b8a --- /dev/null +++ b/results/query/v3/plaintext_rows_10000.json @@ -0,0 +1,6 @@ +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/exact_eq/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_exact_eq_10000","iteration_count":[928,1856,2784,3712,4640,5568,6496,7424,8352,9280],"measured_values":[83288417.0,166475416.0,258711250.0,386425125.0,408402875.0,540765792.0,572643584.0,718536042.0,795077084.0,883869000.0],"unit":"ns","throughput":[],"typical":{"estimate":94536.10559225257,"lower_bound":91752.54753199771,"upper_bound":96624.67796376717,"unit":"ns"},"mean":{"estimate":93699.32395918856,"lower_bound":90908.85129989182,"upper_bound":96816.0690463362,"unit":"ns"},"median":{"estimate":94061.95126915709,"lower_bound":88951.85521859606,"upper_bound":96785.56600215517,"unit":"ns"},"median_abs_dev":{"estimate":5463.265074882656,"lower_bound":496.26639156666255,"upper_bound":9368.888929601091,"unit":"ns"},"slope":{"estimate":94536.10559225257,"lower_bound":91752.54753199771,"upper_bound":96624.67796376717,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/range_gt_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_range_gt_10_10000","iteration_count":[944,1888,2832,3776,4720,5664,6608,7552,8496,9440],"measured_values":[83529708.0,171371667.0,252781208.0,388479667.0,418563667.0,569707875.0,598139208.0,787225541.0,852686709.0,1052264750.0],"unit":"ns","throughput":[],"typical":{"estimate":101615.69333039841,"lower_bound":94434.28199058797,"upper_bound":106881.43621366828,"unit":"ns"},"mean":{"estimate":96724.68224513215,"lower_bound":92036.51436667674,"upper_bound":101609.31190854519,"unit":"ns"},"median":{"estimate":95566.10231285311,"lower_bound":89258.90112994351,"upper_bound":102881.26774364407,"unit":"ns"},"median_abs_dev":{"estimate":9781.12751557697,"lower_bound":573.796553796139,"upper_bound":15344.785261420939,"unit":"ns"},"slope":{"estimate":101615.69333039841,"lower_bound":94434.28199058797,"upper_bound":106881.43621366828,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/range_lt_ordered_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_range_lt_ordered_10_10000","iteration_count":[906,1812,2718,3624,4530,5436,6342,7248,8154,9060],"measured_values":[88026166.0,167735959.0,322982583.0,350347750.0,453235667.0,555231791.0,667064541.0,596150792.0,813752833.0,907314083.0],"unit":"ns","throughput":[],"typical":{"estimate":98124.99745993521,"lower_bound":91468.94654529572,"upper_bound":103019.17440884921,"unit":"ns"},"mean":{"estimate":99480.11947089946,"lower_bound":94116.78412505696,"upper_bound":105039.1415072357,"unit":"ns"},"median":{"estimate":99925.00819229826,"lower_bound":94864.31870860927,"upper_bound":102663.54455219174,"unit":"ns"},"median_abs_dev":{"estimate":4460.082381785338,"lower_bound":326.2225233400916,"upper_bound":14744.000857833264,"unit":"ns"},"slope":{"estimate":98124.99745993521,"lower_bound":91468.94654529572,"upper_bound":103019.17440884921,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/json_contains/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_json_contains_10000","iteration_count":[857,1714,2571,3428,4285,5142,5999,6856,7713,8570],"measured_values":[87994125.0,212450917.0,273198625.0,355930625.0,488899666.0,535711166.0,686988459.0,771688792.0,827182333.0,961599084.0],"unit":"ns","throughput":[],"typical":{"estimate":110497.32848201973,"lower_bound":107670.1098565939,"upper_bound":112828.26075839598,"unit":"ns"},"mean":{"estimate":110152.26832629515,"lower_bound":106522.78669828073,"upper_bound":114222.44937939655,"unit":"ns"},"median":{"estimate":109725.23717100998,"lower_bound":104183.42395954882,"upper_bound":114095.60466744457,"unit":"ns"},"median_abs_dev":{"estimate":6792.007694555837,"lower_bound":1116.7674210135665,"upper_bound":12383.524740805819,"unit":"ns"},"slope":{"estimate":110497.32848201973,"lower_bound":107670.1098565939,"upper_bound":112828.26075839598,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/json_field_eq/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_json_field_eq_10000","iteration_count":[404,808,1212,1616,2020,2424,2828,3232,3636,4040],"measured_values":[86175416.0,167900292.0,298001208.0,343089375.0,420519541.0,549003542.0,585784958.0,787121250.0,781740625.0,841710666.0],"unit":"ns","throughput":[],"typical":{"estimate":218176.63026874117,"lower_bound":209944.0910775548,"upper_bound":230654.65451686145,"unit":"ns"},"mean":{"estimate":218797.27673424484,"lower_bound":210825.70855555555,"upper_bound":228128.99356337418,"unit":"ns"},"median":{"estimate":212806.6333539604,"lower_bound":208070.80767326732,"upper_bound":229270.0813050055,"unit":"ns"},"median_abs_dev":{"estimate":7144.564042007659,"lower_bound":564.2768160216737,"upper_bound":24144.213967394124,"unit":"ns"},"slope":{"estimate":218176.63026874117,"lower_bound":209944.0910775548,"upper_bound":230654.65451686145,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"PLAINTEXT","benchmarks":["PLAINTEXT/plaintext/exact_eq/10000","PLAINTEXT/plaintext/range_gt_10/10000","PLAINTEXT/plaintext/range_lt_ordered_10/10000","PLAINTEXT/plaintext/json_contains/10000","PLAINTEXT/plaintext/json_field_eq/10000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT"} diff --git a/results/query/v3/plaintext_rows_100000.json b/results/query/v3/plaintext_rows_100000.json new file mode 100644 index 0000000..a1360da --- /dev/null +++ b/results/query/v3/plaintext_rows_100000.json @@ -0,0 +1,6 @@ +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/exact_eq/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_exact_eq_100000","iteration_count":[951,1902,2853,3804,4755,5706,6657,7608,8559,9510],"measured_values":[90958625.0,167710458.0,257814875.0,348328250.0,472361500.0,508415625.0,664391375.0,739479833.0,767977916.0,909957625.0],"unit":"ns","throughput":[],"typical":{"estimate":94455.30801207206,"lower_bound":91273.49193415181,"upper_bound":97253.65621376228,"unit":"ns"},"mean":{"estimate":93661.10624801795,"lower_bound":91145.73633991682,"upper_bound":96266.40883670382,"unit":"ns"},"median":{"estimate":93607.09121976866,"lower_bound":89727.52844958522,"upper_bound":97512.12539432177,"unit":"ns"},"median_abs_dev":{"estimate":5537.611900456578,"lower_bound":927.5090177780726,"upper_bound":6708.297183743034,"unit":"ns"},"slope":{"estimate":94455.30801207206,"lower_bound":91273.49193415181,"upper_bound":97253.65621376228,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/range_gt_10/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_range_gt_10_100000","iteration_count":[943,1886,2829,3772,4715,5658,6601,7544,8487,9430],"measured_values":[82486250.0,159046041.0,244574083.0,328288167.0,471617000.0,453412250.0,511861958.0,605223709.0,829397542.0,896311375.0],"unit":"ns","throughput":[],"typical":{"estimate":89183.53074603021,"lower_bound":81259.50602037666,"upper_bound":94951.20052038426,"unit":"ns"},"mean":{"estimate":87599.21901837263,"lower_bound":83222.96331995152,"upper_bound":92271.07027321197,"unit":"ns"},"median":{"estimate":86742.70205903146,"lower_bound":80225.83629374337,"upper_bound":95048.9262990456,"unit":"ns"},"median_abs_dev":{"estimate":9728.138783666946,"lower_bound":755.8867476619741,"upper_bound":12977.073869875998,"unit":"ns"},"slope":{"estimate":89183.53074603021,"lower_bound":81259.50602037666,"upper_bound":94951.20052038426,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/range_lt_ordered_10/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_range_lt_ordered_10_100000","iteration_count":[900,1800,2700,3600,4500,5400,6300,7200,8100,9000],"measured_values":[87308459.0,216281167.0,270279625.0,354003417.0,482892334.0,531733750.0,660270875.0,680060250.0,821799416.0,917456792.0],"unit":"ns","throughput":[],"typical":{"estimate":100966.02682539682,"lower_bound":98022.40535319927,"upper_bound":103611.01924064769,"unit":"ns"},"mean":{"estimate":102403.61454850089,"lower_bound":98724.03516578484,"upper_bound":107110.36036047178,"unit":"ns"},"median":{"estimate":100780.14141975308,"lower_bound":97739.30592592593,"upper_bound":104804.9007936508,"unit":"ns"},"median_abs_dev":{"estimate":4608.366573527728,"lower_bound":1082.1601538989419,"upper_bound":9322.297111407262,"unit":"ns"},"slope":{"estimate":100966.02682539682,"lower_bound":98022.40535319927,"upper_bound":103611.01924064769,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/json_contains/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_json_contains_100000","iteration_count":[381,762,1143,1524,1905,2286,2667,3048,3429,3810],"measured_values":[85633041.0,170521209.0,254228125.0,379581500.0,421608084.0,546801958.0,593750792.0,730877834.0,805782125.0,878625000.0],"unit":"ns","throughput":[],"typical":{"estimate":232730.71781709103,"lower_bound":227714.99601830257,"upper_bound":237417.91798931884,"unit":"ns"},"mean":{"estimate":230856.20039015956,"lower_bound":225559.51600841564,"upper_bound":236660.86592751424,"unit":"ns"},"median":{"estimate":227684.43700787402,"lower_bound":222628.71841019872,"upper_bound":239195.9571303587,"unit":"ns"},"median_abs_dev":{"estimate":8621.680482000189,"lower_bound":1007.6546496958551,"upper_bound":17315.821178518876,"unit":"ns"},"slope":{"estimate":232730.71781709103,"lower_bound":227714.99601830257,"upper_bound":237417.91798931884,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/json_field_eq/100000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_json_field_eq_100000","iteration_count":[407,814,1221,1628,2035,2442,2849,3256,3663,4070],"measured_values":[87188625.0,218362792.0,261345583.0,346660917.0,470749541.0,519585375.0,647112542.0,654449209.0,822739709.0,923596625.0],"unit":"ns","throughput":[],"typical":{"estimate":220631.54330387057,"lower_bound":211326.75386397095,"upper_bound":226969.06720770357,"unit":"ns"},"mean":{"estimate":223322.82579550328,"lower_bound":213975.57608960013,"upper_bound":235321.22811115495,"unit":"ns"},"median":{"estimate":219415.4155064155,"lower_bound":212936.6812039312,"upper_bound":229127.23673218675,"unit":"ns"},"median_abs_dev":{"estimate":10494.950010237588,"lower_bound":942.8021406329141,"upper_bound":22252.308502878674,"unit":"ns"},"slope":{"estimate":220631.54330387057,"lower_bound":211326.75386397095,"upper_bound":226969.06720770357,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"PLAINTEXT","benchmarks":["PLAINTEXT/plaintext/exact_eq/100000","PLAINTEXT/plaintext/range_gt_10/100000","PLAINTEXT/plaintext/range_lt_ordered_10/100000","PLAINTEXT/plaintext/json_contains/100000","PLAINTEXT/plaintext/json_field_eq/100000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT"} diff --git a/results/query/v3/plaintext_rows_1000000.json b/results/query/v3/plaintext_rows_1000000.json new file mode 100644 index 0000000..07b49f9 --- /dev/null +++ b/results/query/v3/plaintext_rows_1000000.json @@ -0,0 +1,6 @@ +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/exact_eq/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_exact_eq_1000000","iteration_count":[947,1894,2841,3788,4735,5682,6629,7576,8523,9470],"measured_values":[85821333.0,173743792.0,297852959.0,340886208.0,431548791.0,558976208.0,643879541.0,694162583.0,819578625.0,916075625.0],"unit":"ns","throughput":[],"typical":{"estimate":95446.82498388622,"lower_bound":93239.1940391785,"upper_bound":97085.80690943514,"unit":"ns"},"mean":{"estimate":94835.95869198472,"lower_bound":92256.9709426824,"upper_bound":97741.08515361794,"unit":"ns"},"median":{"estimate":93947.30077437522,"lower_bound":91125.47828669482,"upper_bound":97555.57752551918,"unit":"ns"},"median_abs_dev":{"estimate":4440.780954148771,"lower_bound":440.03457628499376,"upper_bound":8587.83719265685,"unit":"ns"},"slope":{"estimate":95446.82498388622,"lower_bound":93239.1940391785,"upper_bound":97085.80690943514,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/range_gt_10/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_range_gt_10_1000000","iteration_count":[976,1952,2928,3904,4880,5856,6832,7808,8784,9760],"measured_values":[86266666.0,171897000.0,304004542.0,348820458.0,436592375.0,558870000.0,593242916.0,744598375.0,825979041.0,966593584.0],"unit":"ns","throughput":[],"typical":{"estimate":94429.35017032149,"lower_bound":90560.89994184759,"upper_bound":97161.33102514027,"unit":"ns"},"mean":{"estimate":92979.22081028004,"lower_bound":89920.54456967213,"upper_bound":96352.41718579235,"unit":"ns"},"median":{"estimate":91748.93647540984,"lower_bound":88387.97745901639,"upper_bound":97199.87462858605,"unit":"ns"},"median_abs_dev":{"estimate":5412.3047832540815,"lower_bound":798.8790961654224,"upper_bound":9771.59180856876,"unit":"ns"},"slope":{"estimate":94429.35017032149,"lower_bound":90560.89994184759,"upper_bound":97161.33102514027,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/range_lt_ordered_10/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_range_lt_ordered_10_1000000","iteration_count":[912,1824,2736,3648,4560,5472,6384,7296,8208,9120],"measured_values":[85671625.0,173013917.0,301802750.0,350495125.0,438231417.0,560966208.0,634416625.0,732790708.0,983157458.0,946897250.0],"unit":"ns","throughput":[],"typical":{"estimate":105139.76476133516,"lower_bound":99380.84995807534,"upper_bound":112023.80729769061,"unit":"ns"},"mean":{"estimate":101721.83775228001,"lower_bound":97486.09841087092,"upper_bound":106860.95413316277,"unit":"ns"},"median":{"estimate":99906.68033364663,"lower_bound":95478.75104166666,"upper_bound":106411.88852339181,"unit":"ns"},"median_abs_dev":{"estimate":5743.403518511174,"lower_bound":944.3666413098048,"upper_bound":11552.816739194735,"unit":"ns"},"slope":{"estimate":105139.76476133516,"lower_bound":99380.84995807534,"upper_bound":112023.80729769061,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/json_contains/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_json_contains_1000000","iteration_count":[351,702,1053,1404,1755,2106,2457,2808,3159,3510],"measured_values":[85592625.0,221112333.0,282097292.0,339727458.0,578680583.0,590405750.0,759994917.0,840876000.0,945505125.0,965967083.0],"unit":"ns","throughput":[],"typical":{"estimate":291449.63028083026,"lower_bound":278856.35899343714,"upper_bound":304215.6970198526,"unit":"ns"},"mean":{"estimate":286206.0391249491,"lower_bound":268629.3990788224,"upper_bound":303193.52824365755,"unit":"ns"},"median":{"estimate":289824.90503323835,"lower_bound":259528.9648148148,"upper_bound":309318.2405372405,"unit":"ns"},"median_abs_dev":{"estimate":30704.332381099946,"lower_bound":7422.667240870854,"upper_bound":50291.00893704216,"unit":"ns"},"slope":{"estimate":291449.63028083026,"lower_bound":278856.35899343714,"upper_bound":304215.6970198526,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/json_field_eq/1000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_json_field_eq_1000000","iteration_count":[214,428,642,856,1070,1284,1498,1712,1926,2140],"measured_values":[55829542.0,112844625.0,169881125.0,292652000.0,292106709.0,371302833.0,483392375.0,474361083.0,608970167.0,583374791.0],"unit":"ns","throughput":[],"typical":{"estimate":293035.99237771577,"lower_bound":276773.8483838324,"upper_bound":311806.6374185695,"unit":"ns"},"mean":{"estimate":288177.1324308337,"lower_bound":272668.17353008175,"upper_bound":305960.8220508826,"unit":"ns"},"median":{"estimate":275038.4980724299,"lower_bound":264612.3442367601,"upper_bound":316183.88733125647,"unit":"ns"},"median_abs_dev":{"estimate":18918.713500107027,"lower_bound":3317.3391778227483,"upper_bound":44299.035845372855,"unit":"ns"},"slope":{"estimate":293035.99237771577,"lower_bound":276773.8483838324,"upper_bound":311806.6374185695,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"PLAINTEXT","benchmarks":["PLAINTEXT/plaintext/exact_eq/1000000","PLAINTEXT/plaintext/range_gt_10/1000000","PLAINTEXT/plaintext/range_lt_ordered_10/1000000","PLAINTEXT/plaintext/json_contains/1000000","PLAINTEXT/plaintext/json_field_eq/1000000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT"} diff --git a/results/query/v3/plaintext_rows_10000000.json b/results/query/v3/plaintext_rows_10000000.json new file mode 100644 index 0000000..29c2967 --- /dev/null +++ b/results/query/v3/plaintext_rows_10000000.json @@ -0,0 +1,6 @@ +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/exact_eq/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_exact_eq_10000000","iteration_count":[939,1878,2817,3756,4695,5634,6573,7512,8451,9390],"measured_values":[108970875.0,137888209.0,252361583.0,333044292.0,464601042.0,510305875.0,631172791.0,685847167.0,799318708.0,889794167.0],"unit":"ns","throughput":[],"typical":{"estimate":93649.35503367771,"lower_bound":91501.4685511228,"upper_bound":95136.60375016723,"unit":"ns"},"mean":{"estimate":93392.84469196376,"lower_bound":87287.47130369188,"upper_bound":99754.44052225436,"unit":"ns"},"median":{"estimate":92941.47265856112,"lower_bound":89585.22648207312,"upper_bound":96858.16033013845,"unit":"ns"},"median_abs_dev":{"estimate":4773.8565793578655,"lower_bound":1069.202307570945,"upper_bound":16754.987882571455,"unit":"ns"},"slope":{"estimate":93649.35503367771,"lower_bound":91501.4685511228,"upper_bound":95136.60375016723,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/range_gt_10/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_range_gt_10_10000000","iteration_count":[1044,2088,3132,4176,5220,6264,7308,8352,9396,10440],"measured_values":[90581167.0,180978917.0,271124333.0,392806042.0,451948000.0,578173833.0,641067625.0,758210250.0,866578833.0,942762583.0],"unit":"ns","throughput":[],"typical":{"estimate":90426.2075633179,"lower_bound":88885.57352830152,"upper_bound":91607.57730040947,"unit":"ns"},"mean":{"estimate":89398.37021095603,"lower_bound":87753.61292082309,"upper_bound":91121.44724980045,"unit":"ns"},"median":{"estimate":89012.1396483306,"lower_bound":86671.82327586206,"upper_bound":92228.4837164751,"unit":"ns"},"median_abs_dev":{"estimate":3534.871296668791,"lower_bound":91.95468941151275,"upper_bound":4864.219153154336,"unit":"ns"},"slope":{"estimate":90426.2075633179,"lower_bound":88885.57352830152,"upper_bound":91607.57730040947,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/range_lt_ordered_10/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_range_lt_ordered_10_10000000","iteration_count":[936,1872,2808,3744,4680,5616,6552,7488,8424,9360],"measured_values":[87514708.0,175407000.0,262924333.0,382715958.0,433749083.0,558494166.0,616506167.0,744447416.0,823029125.0,995401541.0],"unit":"ns","throughput":[],"typical":{"estimate":99650.5605006105,"lower_bound":95814.40368769622,"upper_bound":103185.7081013431,"unit":"ns"},"mean":{"estimate":97274.24045516211,"lower_bound":94750.32876814542,"upper_bound":100084.97227926162,"unit":"ns"},"median":{"estimate":95897.43062338897,"lower_bound":93599.4700854701,"upper_bound":100819.93402777778,"unit":"ns"},"median_abs_dev":{"estimate":4162.261245713368,"lower_bound":198.66813247721046,"upper_bound":8206.949917438538,"unit":"ns"},"slope":{"estimate":99650.5605006105,"lower_bound":95814.40368769622,"upper_bound":103185.7081013431,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/json_contains/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_json_contains_10000000","iteration_count":[608,1216,1824,2432,3040,3648,4256,4864,5472,6080],"measured_values":[119570459.0,177080916.0,264210333.0,352150542.0,463889667.0,522856709.0,650928000.0,741876458.0,792843875.0,909360833.0],"unit":"ns","throughput":[],"typical":{"estimate":148890.40035885168,"lower_bound":146078.82089334188,"upper_bound":151543.23954012003,"unit":"ns"},"mean":{"estimate":152778.53625952904,"lower_bound":146172.70948373538,"upper_bound":163380.2605122931,"unit":"ns"},"median":{"estimate":147595.83988486842,"lower_bound":144844.900813231,"upper_bound":152733.7759339756,"unit":"ns"},"median_abs_dev":{"estimate":5238.017131661204,"lower_bound":79.19107803486226,"upper_bound":11345.351975745323,"unit":"ns"},"slope":{"estimate":148890.40035885168,"lower_bound":146078.82089334188,"upper_bound":151543.23954012003,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"PLAINTEXT/plaintext/json_field_eq/10000000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT/plaintext_json_field_eq_10000000","iteration_count":[622,1244,1866,2488,3110,3732,4354,4976,5598,6220],"measured_values":[87831166.0,171382917.0,280025250.0,378308375.0,441882584.0,554791458.0,612562500.0,748573875.0,821090000.0,974274791.0],"unit":"ns","throughput":[],"typical":{"estimate":149209.3136008686,"lower_bound":144387.72369635117,"upper_bound":153340.1739806082,"unit":"ns"},"mean":{"estimate":146627.5871894937,"lower_bound":143108.68805708672,"upper_bound":150152.98138206248,"unit":"ns"},"median":{"estimate":147666.7726866738,"lower_bound":141207.66237942124,"upper_bound":151060.16378617362,"unit":"ns"},"median_abs_dev":{"estimate":7389.8514653231905,"lower_bound":1033.9921903889563,"upper_bound":10620.898359244124,"unit":"ns"},"slope":{"estimate":149209.3136008686,"lower_bound":144387.72369635117,"upper_bound":153340.1739806082,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"PLAINTEXT","benchmarks":["PLAINTEXT/plaintext/exact_eq/10000000","PLAINTEXT/plaintext/range_gt_10/10000000","PLAINTEXT/plaintext/range_lt_ordered_10/10000000","PLAINTEXT/plaintext/json_contains/10000000","PLAINTEXT/plaintext/json_field_eq/10000000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/PLAINTEXT"} diff --git a/results/query/v3/scalar_smoke_metadata_10000.json b/results/query/v3/scalar_smoke_metadata_10000.json new file mode 100644 index 0000000..b63432a --- /dev/null +++ b/results/query/v3/scalar_smoke_metadata_10000.json @@ -0,0 +1,495 @@ +{ + "scenarios": [ + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1060, + "Plans": [ + { + "Alias": "scalar_smoke_v3", + "Async Capable": false, + "Filter": "(eql_v3_internal.ore_block_256((date_val)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbKZu)rt43gi;3VjKw=*jKp37Orc?Z6Y;MJncaO1(FPZ@HJmAmi;r{`9^_w--BZ=uODE-oqu+wuNHbZCOep`kbSLp{QhGbY)+5VQj<@(FPZ@HJmAmi;r{`9^_w--BZ=uODE-oqu+wuNHbZCOep`kbSLp{QhGbY)+5VQj<@ $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 1092, + "Plans": [ + { + "Alias": "scalar_smoke_v3", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((date_val)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbKZu)rt43gi;3VjKw=*jKp37Orc?Z6Y;MJncaO1(FPZ@HJmAmi;r{`9^_w--BZ=uODE-oqu+wuNHbZCOep`kbSLp{QhGbY)+5VQj<@(FPZ@HJmAmi;r{`9^_w--BZ=uODE-oqu+wuNHbZCOep`kbSLp{QhGbY)+5VQj<@ $1 ORDER BY eql_v3.ord_term(date_val) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 22, + "Plans": [ + { + "Alias": "scalar_smoke_v3", + "Async Capable": false, + "Filter": "(eql_v3_internal.ore_block_256((timestamp_val)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbLjz2u}|LpUMg50K`w`*Ui<8oxC&ZlWmCjwLY%8-x~_cn89!$l3|6s@;>sAX{uhN3b@wh?v%+tXsVkh#mTB9SM?xUh}A4;fcOvSFLnuZDn(GVQp|~0Vg\", \"i\": {\"c\": \"timestamp_val\", \"t\": \"scalar_smoke_v3\"}, \"v\": 3, \"ob\": [\"b04f4f4fc6b84f81b5b5b5b58f1fb437c31425bb5254907f79d48fe3ce87baeaee53f57dd34855b1bc24266860981de3b4bde2090939d44084203db03f7eb33c2f314b52edc1861f620c904aafa734f622dc0bb073713fe56690d1923604584ed1017af6983b68bd850316b9bce80a14fb46fe0ab0d1aba4f93d54c6e6942b7fffe9e6384a3be99fc10660c75658ac8eae9885925e10c9f63bba6945ed88703189e8a75505a94954b9f5ee67fa93bdeb07c24ed3b3429840f5407912c840a26ce5586095926d526364b2e3d31b354455bd0e84d3e1c79cf6ffb756b18b5123c71a02733ec3adf289cf31bf82a41a8d252ce1ba7dd0a2f7caee374324449655bfa5678a45dd86a802bcd38000d7f9c108922746fd52a22fc0e33daf754e812c5bbec1487fb8c72ff250ff7206259735dfd59eb9239ac5d187eea6ceea5fca7968b334419ae3c0e4bdfb9c8d3f36ff1bc5eff46f4c400ddce8ca3775aed3e841a5639b84536ad4e9c56f6d6dc785897b7c99fbee42d4f48421041ce95856fc37def27d255b9ca124eee5a465613cf19ec1f2b35fc8f6605651c95ac2bc3816e06f420fb39a7cf41ffc6901cf4cc3f32df7d60365d47fc3426de70cfe30b1ad831917d73d4d3bce20200f10acad134333402815c9c5ec93872aaabe8d94fa3bab253e19f4d26ca4d5f14b5df3f0c774a7fd34872e5dbaa51c76dd327d7da89d88b2d8048b983ca709482ffb0abfc8cf78cf95f0702f083d21dd8fedb27efe7e197b6dd4f56e2b3c1e01b8c40dd8005f4b1ac009bcbd91f550ad3ebe1068f4bb4bc1bedb6a9c1b9a906c13e8d1a61a50cd86d4324b98ef590fb61a032c57\"]}'::jsonb)::eql_v3.timestamp_ord)::jsonb))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4950, + "Plan Width": 22, + "Relation Name": "scalar_smoke_v3", + "Startup Cost": 0.0, + "Total Cost": 9625.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 19.44 + } + } + ], + "id": "SMOKE_V3/smoke/timestamp_ord/range_gt_10/10000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbLjz2u}|LpUMg50K`w`*Ui<8oxC&ZlWmCjwLY%8-x~_cn89!$l3|6s@;>sAX{uhN3b@wh?v%+tXsVkh#mTB9SM?xUh}A4;fcOvSFLnuZDn(GVQp|~0Vg", + "i": { + "c": "timestamp_val", + "t": "scalar_smoke_v3" + }, + "ob": [ + "b04f4f4fc6b84f81b5b5b5b58f1fb437c31425bb5254907f79d48fe3ce87baeaee53f57dd34855b1bc24266860981de3b4bde2090939d44084203db03f7eb33c2f314b52edc1861f620c904aafa734f622dc0bb073713fe56690d1923604584ed1017af6983b68bd850316b9bce80a14fb46fe0ab0d1aba4f93d54c6e6942b7fffe9e6384a3be99fc10660c75658ac8eae9885925e10c9f63bba6945ed88703189e8a75505a94954b9f5ee67fa93bdeb07c24ed3b3429840f5407912c840a26ce5586095926d526364b2e3d31b354455bd0e84d3e1c79cf6ffb756b18b5123c71a02733ec3adf289cf31bf82a41a8d252ce1ba7dd0a2f7caee374324449655bfa5678a45dd86a802bcd38000d7f9c108922746fd52a22fc0e33daf754e812c5bbec1487fb8c72ff250ff7206259735dfd59eb9239ac5d187eea6ceea5fca7968b334419ae3c0e4bdfb9c8d3f36ff1bc5eff46f4c400ddce8ca3775aed3e841a5639b84536ad4e9c56f6d6dc785897b7c99fbee42d4f48421041ce95856fc37def27d255b9ca124eee5a465613cf19ec1f2b35fc8f6605651c95ac2bc3816e06f420fb39a7cf41ffc6901cf4cc3f32df7d60365d47fc3426de70cfe30b1ad831917d73d4d3bce20200f10acad134333402815c9c5ec93872aaabe8d94fa3bab253e19f4d26ca4d5f14b5df3f0c774a7fd34872e5dbaa51c76dd327d7da89d88b2d8048b983ca709482ffb0abfc8cf78cf95f0702f083d21dd8fedb27efe7e197b6dd4f56e2b3c1e01b8c40dd8005f4b1ac009bcbd91f550ad3ebe1068f4bb4bc1bedb6a9c1b9a906c13e8d1a61a50cd86d4324b98ef590fb61a032c57" + ], + "v": 3 + } + ], + "query": "SELECT id, timestamp_val FROM scalar_smoke_v3 WHERE timestamp_val > $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 54, + "Plans": [ + { + "Alias": "scalar_smoke_v3", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((timestamp_val)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbLjz2u}|LpUMg50K`w`*Ui<8oxC&ZlWmCjwLY%8-x~_cn89!$l3|6s@;>sAX{uhN3b@wh?v%+tXsVkh#mTB9SM?xUh}A4;fcOvSFLnuZDn(GVQp|~0Vg\", \"i\": {\"c\": \"timestamp_val\", \"t\": \"scalar_smoke_v3\"}, \"v\": 3, \"ob\": [\"b04f4f4fc6b84f81b5b5b5b58f1fb437c31425bb5254907f79d48fe3ce87baeaee53f57dd34855b1bc24266860981de3b4bde2090939d44084203db03f7eb33c2f314b52edc1861f620c904aafa734f622dc0bb073713fe56690d1923604584ed1017af6983b68bd850316b9bce80a14fb46fe0ab0d1aba4f93d54c6e6942b7fffe9e6384a3be99fc10660c75658ac8eae9885925e10c9f63bba6945ed88703189e8a75505a94954b9f5ee67fa93bdeb07c24ed3b3429840f5407912c840a26ce5586095926d526364b2e3d31b354455bd0e84d3e1c79cf6ffb756b18b5123c71a02733ec3adf289cf31bf82a41a8d252ce1ba7dd0a2f7caee374324449655bfa5678a45dd86a802bcd38000d7f9c108922746fd52a22fc0e33daf754e812c5bbec1487fb8c72ff250ff7206259735dfd59eb9239ac5d187eea6ceea5fca7968b334419ae3c0e4bdfb9c8d3f36ff1bc5eff46f4c400ddce8ca3775aed3e841a5639b84536ad4e9c56f6d6dc785897b7c99fbee42d4f48421041ce95856fc37def27d255b9ca124eee5a465613cf19ec1f2b35fc8f6605651c95ac2bc3816e06f420fb39a7cf41ffc6901cf4cc3f32df7d60365d47fc3426de70cfe30b1ad831917d73d4d3bce20200f10acad134333402815c9c5ec93872aaabe8d94fa3bab253e19f4d26ca4d5f14b5df3f0c774a7fd34872e5dbaa51c76dd327d7da89d88b2d8048b983ca709482ffb0abfc8cf78cf95f0702f083d21dd8fedb27efe7e197b6dd4f56e2b3c1e01b8c40dd8005f4b1ac009bcbd91f550ad3ebe1068f4bb4bc1bedb6a9c1b9a906c13e8d1a61a50cd86d4324b98ef590fb61a032c57\"]}'::jsonb)::eql_v3.timestamp_ord)::jsonb))", + "Index Name": "scalar_smoke_v3_timestamp_val_ord_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4950, + "Plan Width": 54, + "Relation Name": "scalar_smoke_v3", + "Scan Direction": "Forward", + "Startup Cost": 0.91, + "Total Cost": 11558.27 + } + ], + "Startup Cost": 0.91, + "Total Cost": 24.26 + } + } + ], + "id": "SMOKE_V3/smoke/timestamp_ord/range_gt_ordered_10/10000", + "indexes_used": [ + "scalar_smoke_v3_timestamp_val_ord_idx" + ], + "parameters": [ + { + "c": "mBbLjz2u}|LpUMg50K`w`*Ui<8oxC&ZlWmCjwLY%8-x~_cn89!$l3|6s@;>sAX{uhN3b@wh?v%+tXsVkh#mTB9SM?xUh}A4;fcOvSFLnuZDn(GVQp|~0Vg", + "i": { + "c": "timestamp_val", + "t": "scalar_smoke_v3" + }, + "ob": [ + "b04f4f4fc6b84f81b5b5b5b58f1fb437c31425bb5254907f79d48fe3ce87baeaee53f57dd34855b1bc24266860981de3b4bde2090939d44084203db03f7eb33c2f314b52edc1861f620c904aafa734f622dc0bb073713fe56690d1923604584ed1017af6983b68bd850316b9bce80a14fb46fe0ab0d1aba4f93d54c6e6942b7fffe9e6384a3be99fc10660c75658ac8eae9885925e10c9f63bba6945ed88703189e8a75505a94954b9f5ee67fa93bdeb07c24ed3b3429840f5407912c840a26ce5586095926d526364b2e3d31b354455bd0e84d3e1c79cf6ffb756b18b5123c71a02733ec3adf289cf31bf82a41a8d252ce1ba7dd0a2f7caee374324449655bfa5678a45dd86a802bcd38000d7f9c108922746fd52a22fc0e33daf754e812c5bbec1487fb8c72ff250ff7206259735dfd59eb9239ac5d187eea6ceea5fca7968b334419ae3c0e4bdfb9c8d3f36ff1bc5eff46f4c400ddce8ca3775aed3e841a5639b84536ad4e9c56f6d6dc785897b7c99fbee42d4f48421041ce95856fc37def27d255b9ca124eee5a465613cf19ec1f2b35fc8f6605651c95ac2bc3816e06f420fb39a7cf41ffc6901cf4cc3f32df7d60365d47fc3426de70cfe30b1ad831917d73d4d3bce20200f10acad134333402815c9c5ec93872aaabe8d94fa3bab253e19f4d26ca4d5f14b5df3f0c774a7fd34872e5dbaa51c76dd327d7da89d88b2d8048b983ca709482ffb0abfc8cf78cf95f0702f083d21dd8fedb27efe7e197b6dd4f56e2b3c1e01b8c40dd8005f4b1ac009bcbd91f550ad3ebe1068f4bb4bc1bedb6a9c1b9a906c13e8d1a61a50cd86d4324b98ef590fb61a032c57" + ], + "v": 3 + } + ], + "query": "SELECT id, timestamp_val FROM scalar_smoke_v3 WHERE timestamp_val > $1 ORDER BY eql_v3.ord_term(timestamp_val) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 22, + "Plans": [ + { + "Alias": "scalar_smoke_v3", + "Async Capable": false, + "Filter": "(eql_v3_internal.ore_block_256((numeric_val)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbKnE{!RY3vlAhv2ADD_CO)TB4(d`uTfm $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 54, + "Plans": [ + { + "Alias": "scalar_smoke_v3", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((numeric_val)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbKnE{!RY3vlAhv2ADD_CO)TB4(d`uTfm $1 ORDER BY eql_v3.ord_term(numeric_val) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 22, + "Plans": [ + { + "Alias": "scalar_smoke_v3", + "Async Capable": false, + "Filter": "(eql_v3_internal.ore_block_256((bigint_val)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbJm%cIjoyB0-m9@XP?co2ES8rB4M&*xx|h^+!5+!SXJ`y%yYAUj $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 54, + "Plans": [ + { + "Alias": "scalar_smoke_v3", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((bigint_val)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbJm%cIjoyB0-m9@XP?co2ES8rB4M&*xx|h^+!5+!SXJ`y%yYAUj $1 ORDER BY eql_v3.ord_term(bigint_val) LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 22, + "Plans": [ + { + "Alias": "scalar_smoke_v3", + "Async Capable": false, + "Filter": "(eql_v3_internal.ore_block_256((double_val)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbK6@%aBki)P8=)nni_Kgb!x8oO=5&(_7M`eFVe?%(w-C>asx$+r~{m&>ZeAgK>!AP?1^Pk~v{X|S{wkqp~2<>6w4TX0hS{guFWd8%Y@bz*E~Uv^<^#1Q2)NxIzjOYXJFCv9j}(_#\", \"i\": {\"c\": \"double_val\", \"t\": \"scalar_smoke_v3\"}, \"v\": 3, \"ob\": [\"dda408150b0b0b0beab87098d44e580d0e970ee63829e3db916f1d6c3334661912fb0e3234ef1da6567c748dcf5604b35b760d33be8b8330e437638bb89d1a406672ca8eb23e8ab9b7f7e0c6ad3265578973a77f1084ab7dec17d88f0609bdf497f9fa4cdf745fcb8ec06e516ad224b7a5ad1828d872fe913b581f4f06c3a11ff8245f109700af74251dbd149f0b6198b9a191907d8670fbb5d8129716672181c865b883804c3dcdbabd90acbd08d5db4ca386f4e9dbefa9379494f7b7b522e71eafca142fb2ccee485c250da22c1f96ad8d3ad3c222d7bb72293978c319839a3bbe876e1794e63a351c21b1c7e696394ff563a4b30744a256fdcfd984b5912382f527d79b7d370f0f1b8bdae7536f713115379d4b638a0d89079a8b99091b21620436bf6f4bc98f64c85c308dac6ab486c9c58c289fcf98f5ed4b3c2dc3020d91bccf06626068dd685421252dae86c79cc60ea517b9d3a99b3c8d75a2fe1ae03d960ac2e25356168cfd1398aa4a1de0d9da348c74c924d25c57d69d99cc583b1527fff5d36e0c0aba0690cc3a4484a89cebe544b80ac952\"]}'::jsonb)::eql_v3.double_ord)::jsonb))", + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4950, + "Plan Width": 22, + "Relation Name": "scalar_smoke_v3", + "Startup Cost": 0.0, + "Total Cost": 9625.0 + } + ], + "Startup Cost": 0.0, + "Total Cost": 19.44 + } + } + ], + "id": "SMOKE_V3/smoke/double_ord/range_gt_10/10000", + "indexes_used": [], + "parameters": [ + { + "c": "mBbK6@%aBki)P8=)nni_Kgb!x8oO=5&(_7M`eFVe?%(w-C>asx$+r~{m&>ZeAgK>!AP?1^Pk~v{X|S{wkqp~2<>6w4TX0hS{guFWd8%Y@bz*E~Uv^<^#1Q2)NxIzjOYXJFCv9j}(_#", + "i": { + "c": "double_val", + "t": "scalar_smoke_v3" + }, + "ob": [ + "dda408150b0b0b0beab87098d44e580d0e970ee63829e3db916f1d6c3334661912fb0e3234ef1da6567c748dcf5604b35b760d33be8b8330e437638bb89d1a406672ca8eb23e8ab9b7f7e0c6ad3265578973a77f1084ab7dec17d88f0609bdf497f9fa4cdf745fcb8ec06e516ad224b7a5ad1828d872fe913b581f4f06c3a11ff8245f109700af74251dbd149f0b6198b9a191907d8670fbb5d8129716672181c865b883804c3dcdbabd90acbd08d5db4ca386f4e9dbefa9379494f7b7b522e71eafca142fb2ccee485c250da22c1f96ad8d3ad3c222d7bb72293978c319839a3bbe876e1794e63a351c21b1c7e696394ff563a4b30744a256fdcfd984b5912382f527d79b7d370f0f1b8bdae7536f713115379d4b638a0d89079a8b99091b21620436bf6f4bc98f64c85c308dac6ab486c9c58c289fcf98f5ed4b3c2dc3020d91bccf06626068dd685421252dae86c79cc60ea517b9d3a99b3c8d75a2fe1ae03d960ac2e25356168cfd1398aa4a1de0d9da348c74c924d25c57d69d99cc583b1527fff5d36e0c0aba0690cc3a4484a89cebe544b80ac952" + ], + "v": 3 + } + ], + "query": "SELECT id, double_val FROM scalar_smoke_v3 WHERE double_val > $1 LIMIT 10", + "rows_returned": 10 + }, + { + "explain": [ + { + "Plan": { + "Async Capable": false, + "Node Type": "Limit", + "Parallel Aware": false, + "Plan Rows": 10, + "Plan Width": 54, + "Plans": [ + { + "Alias": "scalar_smoke_v3", + "Async Capable": false, + "Index Cond": "(eql_v3_internal.ore_block_256((double_val)::jsonb) > eql_v3_internal.ore_block_256((('{\"c\": \"mBbK6@%aBki)P8=)nni_Kgb!x8oO=5&(_7M`eFVe?%(w-C>asx$+r~{m&>ZeAgK>!AP?1^Pk~v{X|S{wkqp~2<>6w4TX0hS{guFWd8%Y@bz*E~Uv^<^#1Q2)NxIzjOYXJFCv9j}(_#\", \"i\": {\"c\": \"double_val\", \"t\": \"scalar_smoke_v3\"}, \"v\": 3, \"ob\": [\"dda408150b0b0b0beab87098d44e580d0e970ee63829e3db916f1d6c3334661912fb0e3234ef1da6567c748dcf5604b35b760d33be8b8330e437638bb89d1a406672ca8eb23e8ab9b7f7e0c6ad3265578973a77f1084ab7dec17d88f0609bdf497f9fa4cdf745fcb8ec06e516ad224b7a5ad1828d872fe913b581f4f06c3a11ff8245f109700af74251dbd149f0b6198b9a191907d8670fbb5d8129716672181c865b883804c3dcdbabd90acbd08d5db4ca386f4e9dbefa9379494f7b7b522e71eafca142fb2ccee485c250da22c1f96ad8d3ad3c222d7bb72293978c319839a3bbe876e1794e63a351c21b1c7e696394ff563a4b30744a256fdcfd984b5912382f527d79b7d370f0f1b8bdae7536f713115379d4b638a0d89079a8b99091b21620436bf6f4bc98f64c85c308dac6ab486c9c58c289fcf98f5ed4b3c2dc3020d91bccf06626068dd685421252dae86c79cc60ea517b9d3a99b3c8d75a2fe1ae03d960ac2e25356168cfd1398aa4a1de0d9da348c74c924d25c57d69d99cc583b1527fff5d36e0c0aba0690cc3a4484a89cebe544b80ac952\"]}'::jsonb)::eql_v3.double_ord)::jsonb))", + "Index Name": "scalar_smoke_v3_double_val_ord_idx", + "Node Type": "Index Scan", + "Parallel Aware": false, + "Parent Relationship": "Outer", + "Plan Rows": 4950, + "Plan Width": 54, + "Relation Name": "scalar_smoke_v3", + "Scan Direction": "Forward", + "Startup Cost": 0.79, + "Total Cost": 10876.32 + } + ], + "Startup Cost": 0.79, + "Total Cost": 22.76 + } + } + ], + "id": "SMOKE_V3/smoke/double_ord/range_gt_ordered_10/10000", + "indexes_used": [ + "scalar_smoke_v3_double_val_ord_idx" + ], + "parameters": [ + { + "c": "mBbK6@%aBki)P8=)nni_Kgb!x8oO=5&(_7M`eFVe?%(w-C>asx$+r~{m&>ZeAgK>!AP?1^Pk~v{X|S{wkqp~2<>6w4TX0hS{guFWd8%Y@bz*E~Uv^<^#1Q2)NxIzjOYXJFCv9j}(_#", + "i": { + "c": "double_val", + "t": "scalar_smoke_v3" + }, + "ob": [ + "dda408150b0b0b0beab87098d44e580d0e970ee63829e3db916f1d6c3334661912fb0e3234ef1da6567c748dcf5604b35b760d33be8b8330e437638bb89d1a406672ca8eb23e8ab9b7f7e0c6ad3265578973a77f1084ab7dec17d88f0609bdf497f9fa4cdf745fcb8ec06e516ad224b7a5ad1828d872fe913b581f4f06c3a11ff8245f109700af74251dbd149f0b6198b9a191907d8670fbb5d8129716672181c865b883804c3dcdbabd90acbd08d5db4ca386f4e9dbefa9379494f7b7b522e71eafca142fb2ccee485c250da22c1f96ad8d3ad3c222d7bb72293978c319839a3bbe876e1794e63a351c21b1c7e696394ff563a4b30744a256fdcfd984b5912382f527d79b7d370f0f1b8bdae7536f713115379d4b638a0d89079a8b99091b21620436bf6f4bc98f64c85c308dac6ab486c9c58c289fcf98f5ed4b3c2dc3020d91bccf06626068dd685421252dae86c79cc60ea517b9d3a99b3c8d75a2fe1ae03d960ac2e25356168cfd1398aa4a1de0d9da348c74c924d25c57d69d99cc583b1527fff5d36e0c0aba0690cc3a4484a89cebe544b80ac952" + ], + "v": 3 + } + ], + "query": "SELECT id, double_val FROM scalar_smoke_v3 WHERE double_val > $1 ORDER BY eql_v3.ord_term(double_val) LIMIT 10", + "rows_returned": 10 + } + ], + "target_rows": "10000" +} \ No newline at end of file diff --git a/results/query/v3/scalar_smoke_rows_10000.json b/results/query/v3/scalar_smoke_rows_10000.json new file mode 100644 index 0000000..8ce49eb --- /dev/null +++ b/results/query/v3/scalar_smoke_rows_10000.json @@ -0,0 +1,12 @@ +{"reason":"benchmark-complete","id":"SMOKE_V3/smoke/date_ord/range_gt_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/SMOKE_V3/smoke_date_ord_range_gt_10_10000","iteration_count":[62,124,186,248,310,372,434,496,558,620],"measured_values":[87542209.0,208759708.0,264641542.0,353742042.0,469448583.0,526553709.0,652372875.0,707361042.0,831682833.0,912292625.0],"unit":"ns","throughput":[],"typical":{"estimate":1468541.6755760368,"lower_bound":1442267.470129494,"upper_bound":1491282.3164181376,"unit":"ns"},"mean":{"estimate":1476572.2747580644,"lower_bound":1435693.6229126344,"upper_bound":1530537.6739516128,"unit":"ns"},"median":{"estimate":1448909.4596774194,"lower_bound":1420799.0463709678,"upper_bound":1503163.3064516129,"unit":"ns"},"median_abs_dev":{"estimate":52173.32078744818,"lower_bound":2834.1980912152485,"upper_bound":109731.93489380396,"unit":"ns"},"slope":{"estimate":1468541.6755760368,"lower_bound":1442267.470129494,"upper_bound":1491282.3164181376,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"SMOKE_V3/smoke/date_ord/range_gt_ordered_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/SMOKE_V3/smoke_date_ord_range_gt_ordered_10_10000","iteration_count":[67,134,201,268,335,402,469,536,603,670],"measured_values":[87658459.0,177304167.0,260741375.0,350090959.0,472816958.0,526056958.0,661179792.0,739198875.0,787433250.0,911194333.0],"unit":"ns","throughput":[],"typical":{"estimate":1352431.6113975577,"lower_bound":1321713.254900405,"upper_bound":1381235.0341875213,"unit":"ns"},"mean":{"estimate":1340974.2644651742,"lower_bound":1315960.3438432836,"upper_bound":1369030.0152220149,"unit":"ns"},"median":{"estimate":1315882.4116915422,"lower_bound":1306309.5485074627,"upper_bound":1384878.278358209,"unit":"ns"},"median_abs_dev":{"estimate":21263.89323368447,"lower_bound":1697.4654060580033,"upper_bound":74994.07048799196,"unit":"ns"},"slope":{"estimate":1352431.6113975577,"lower_bound":1321713.254900405,"upper_bound":1381235.0341875213,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"SMOKE_V3/smoke/timestamp_ord/range_gt_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/SMOKE_V3/smoke_timestamp_ord_range_gt_10_10000","iteration_count":[96,192,288,384,480,576,672,768,864,960],"measured_values":[80919375.0,159411500.0,325666917.0,350156125.0,494908500.0,533419667.0,659432583.0,708109500.0,831270791.0,914970000.0],"unit":"ns","throughput":[],"typical":{"estimate":956830.8800865801,"lower_bound":936611.0502202039,"upper_bound":982066.8628089367,"unit":"ns"},"mean":{"estimate":949149.5172081679,"lower_bound":899802.1209852431,"upper_bound":1003035.26348669,"unit":"ns"},"median":{"estimate":939584.7803819445,"lower_bound":882463.8671875,"upper_bound":996589.1730324074,"unit":"ns"},"median_abs_dev":{"estimate":51471.1102744864,"lower_bound":13380.792513137916,"upper_bound":146154.77297164046,"unit":"ns"},"slope":{"estimate":956830.8800865801,"lower_bound":936611.0502202039,"upper_bound":982066.8628089367,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"SMOKE_V3/smoke/timestamp_ord/range_gt_ordered_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/SMOKE_V3/smoke_timestamp_ord_range_gt_ordered_10_10000","iteration_count":[136,272,408,544,680,816,952,1088,1224,1360],"measured_values":[86478542.0,215285958.0,259154458.0,344098459.0,470310667.0,516766542.0,707854584.0,735387917.0,802542791.0,940107500.0],"unit":"ns","throughput":[],"typical":{"estimate":679623.8693277311,"lower_bound":656110.6394117647,"upper_bound":703924.3027787881,"unit":"ns"},"mean":{"estimate":678638.6689405346,"lower_bound":649944.8817838542,"upper_bound":712478.5756548203,"unit":"ns"},"median":{"estimate":665790.1134089052,"lower_bound":634581.981617647,"upper_bound":717400.1228991597,"unit":"ns"},"median_abs_dev":{"estimate":44867.996664064965,"lower_bound":1912.0361462016874,"upper_bound":82903.0772636175,"unit":"ns"},"slope":{"estimate":679623.8693277311,"lower_bound":656110.6394117647,"upper_bound":703924.3027787881,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"SMOKE_V3/smoke/numeric_ord/range_gt_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/SMOKE_V3/smoke_numeric_ord_range_gt_10_10000","iteration_count":[90,180,270,360,450,540,630,720,810,900],"measured_values":[87400375.0,210208750.0,264853584.0,349260333.0,476047875.0,531695792.0,648501667.0,717683916.0,836897334.0,916814958.0],"unit":"ns","throughput":[],"typical":{"estimate":1017346.1087734487,"lower_bound":1000999.5066915655,"upper_bound":1031410.8399902523,"unit":"ns"},"mean":{"estimate":1021059.5275952382,"lower_bound":991310.1084656084,"upper_bound":1059468.3427991404,"unit":"ns"},"median":{"estimate":1007733.2516666667,"lower_bound":977868.5574074073,"upper_bound":1043625.946031746,"unit":"ns"},"median_abs_dev":{"estimate":38745.81194990215,"lower_bound":7984.993115737994,"upper_bound":76066.94553787513,"unit":"ns"},"slope":{"estimate":1017346.1087734487,"lower_bound":1000999.5066915655,"upper_bound":1031410.8399902523,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"SMOKE_V3/smoke/numeric_ord/range_gt_ordered_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/SMOKE_V3/smoke_numeric_ord_range_gt_ordered_10_10000","iteration_count":[127,254,381,508,635,762,889,1016,1143,1270],"measured_values":[84655250.0,179274541.0,283064750.0,452630875.0,417808125.0,602519667.0,639840583.0,771477541.0,871618167.0,952138125.0],"unit":"ns","throughput":[],"typical":{"estimate":753118.516637693,"lower_bound":728934.0056304786,"upper_bound":777215.1176971731,"unit":"ns"},"mean":{"estimate":744635.8197740907,"lower_bound":708304.0877015373,"upper_bound":786065.6273228346,"unit":"ns"},"median":{"estimate":746333.5793963254,"lower_bound":693153.7305961754,"upper_bound":775018.2563976378,"unit":"ns"},"median_abs_dev":{"estimate":49764.3500606006,"lower_bound":9529.793654828132,"upper_bound":105231.29133098375,"unit":"ns"},"slope":{"estimate":753118.516637693,"lower_bound":728934.0056304786,"upper_bound":777215.1176971731,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"SMOKE_V3/smoke/bigint_ord/range_gt_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/SMOKE_V3/smoke_bigint_ord_range_gt_10_10000","iteration_count":[114,228,342,456,570,684,798,912,1026,1140],"measured_values":[84193334.0,170961042.0,295158542.0,337217125.0,425872875.0,551261083.0,629367625.0,695211042.0,816235292.0,891090250.0],"unit":"ns","throughput":[],"typical":{"estimate":781992.9882889041,"lower_bound":767804.0125036263,"upper_bound":794203.1442556233,"unit":"ns"},"mean":{"estimate":777218.0835700362,"lower_bound":756399.9466130605,"upper_bound":801684.3231481481,"unit":"ns"},"median":{"estimate":771975.461622807,"lower_bound":744670.1853070175,"upper_bound":797309.2450918965,"unit":"ns"},"median_abs_dev":{"estimate":35883.04997903036,"lower_bound":7102.097678517852,"upper_bound":66247.22361123048,"unit":"ns"},"slope":{"estimate":781992.9882889041,"lower_bound":767804.0125036263,"upper_bound":794203.1442556233,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"SMOKE_V3/smoke/bigint_ord/range_gt_ordered_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/SMOKE_V3/smoke_bigint_ord_range_gt_ordered_10_10000","iteration_count":[158,316,474,632,790,948,1106,1264,1422,1580],"measured_values":[87145417.0,173195875.0,263649625.0,347975833.0,494198250.0,549560792.0,683360792.0,788305166.0,840710750.0,891175666.0],"unit":"ns","throughput":[],"typical":{"estimate":591038.396481999,"lower_bound":572348.1425878099,"upper_bound":611421.3602726387,"unit":"ns"},"mean":{"estimate":580851.0282328712,"lower_bound":562792.810038678,"upper_bound":599986.5888141703,"unit":"ns"},"median":{"estimate":571870.3542194093,"lower_bound":551553.2721518987,"upper_bound":617866.9005424954,"unit":"ns"},"median_abs_dev":{"estimate":30832.715271312416,"lower_bound":3279.2589590283096,"upper_bound":50982.6515449297,"unit":"ns"},"slope":{"estimate":591038.396481999,"lower_bound":572348.1425878099,"upper_bound":611421.3602726387,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"SMOKE_V3/smoke/double_ord/range_gt_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/SMOKE_V3/smoke_double_ord_range_gt_10_10000","iteration_count":[83,166,249,332,415,498,581,664,747,830],"measured_values":[84188250.0,169330125.0,256885583.0,394142583.0,430557458.0,551815750.0,598208500.0,729063958.0,807173083.0,897408417.0],"unit":"ns","throughput":[],"typical":{"estimate":1079404.4891879205,"lower_bound":1057255.3196667265,"upper_bound":1099312.3090998207,"unit":"ns"},"mean":{"estimate":1068814.892635303,"lower_bound":1039963.1338554217,"upper_bound":1102816.9210645438,"unit":"ns"},"median":{"estimate":1059020.4199464526,"lower_bound":1025865.001004016,"upper_bound":1097987.8885542168,"unit":"ns"},"median_abs_dev":{"estimate":50676.071529195586,"lower_bound":5833.356198605937,"upper_bound":90666.86877491963,"unit":"ns"},"slope":{"estimate":1079404.4891879205,"lower_bound":1057255.3196667265,"upper_bound":1099312.3090998207,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"SMOKE_V3/smoke/double_ord/range_gt_ordered_10/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/SMOKE_V3/smoke_double_ord_range_gt_ordered_10_10000","iteration_count":[145,290,435,580,725,870,1015,1160,1305,1450],"measured_values":[87918666.0,174261875.0,258526875.0,382877834.0,434975208.0,514912333.0,650132541.0,783107250.0,792667791.0,860725292.0],"unit":"ns","throughput":[],"typical":{"estimate":619165.8439946261,"lower_bound":598651.6770065126,"upper_bound":647674.0520367988,"unit":"ns"},"mean":{"estimate":617013.5603464696,"lower_bound":600619.3839139574,"upper_bound":635997.0120583745,"unit":"ns"},"median":{"estimate":603619.3224137931,"lower_bound":594314.6551724138,"upper_bound":640524.6709359606,"unit":"ns"},"median_abs_dev":{"estimate":14322.16778773067,"lower_bound":2351.703316111046,"upper_bound":47611.04968094188,"unit":"ns"},"slope":{"estimate":619165.8439946261,"lower_bound":598651.6770065126,"upper_bound":647674.0520367988,"unit":"ns"},"change":null} +{"reason":"benchmark-complete","id":"SMOKE_V3/smoke/boolean/select_back/10000","report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/SMOKE_V3/smoke_boolean_select_back_10000","iteration_count":[902,1804,2706,3608,4510,5412,6314,7216,8118,9020],"measured_values":[87744791.0,173941584.0,256566958.0,393146792.0,435570875.0,561824166.0,526215792.0,739957708.0,839847708.0,880949792.0],"unit":"ns","throughput":[],"typical":{"estimate":98764.6928096294,"lower_bound":92947.85162391956,"upper_bound":103000.17575436228,"unit":"ns"},"mean":{"estimate":98487.35317125965,"lower_bound":94182.59978724527,"upper_bound":102353.57694805195,"unit":"ns"},"median":{"estimate":97472.15643015521,"lower_bound":95696.50461936438,"upper_bound":103455.0022172949,"unit":"ns"},"median_abs_dev":{"estimate":5730.194793778686,"lower_bound":636.1036014563549,"upper_bound":10490.281305556287,"unit":"ns"},"slope":{"estimate":98764.6928096294,"lower_bound":92947.85162391956,"upper_bound":103000.17575436228,"unit":"ns"},"change":null} +{"reason":"group-complete","group_name":"SMOKE_V3","benchmarks":["SMOKE_V3/smoke/date_ord/range_gt_10/10000","SMOKE_V3/smoke/date_ord/range_gt_ordered_10/10000","SMOKE_V3/smoke/timestamp_ord/range_gt_10/10000","SMOKE_V3/smoke/timestamp_ord/range_gt_ordered_10/10000","SMOKE_V3/smoke/numeric_ord/range_gt_10/10000","SMOKE_V3/smoke/numeric_ord/range_gt_ordered_10/10000","SMOKE_V3/smoke/bigint_ord/range_gt_10/10000","SMOKE_V3/smoke/bigint_ord/range_gt_ordered_10/10000","SMOKE_V3/smoke/double_ord/range_gt_10/10000","SMOKE_V3/smoke/double_ord/range_gt_ordered_10/10000","SMOKE_V3/smoke/boolean/select_back/10000"],"report_directory":"/Users/dan/Projects/CipherStash/benches/target/criterion/reports/SMOKE_V3"} diff --git a/sql/indexes/category_encrypted_v3_10000000_down.sql b/sql/indexes/category_encrypted_v3_10000000_down.sql new file mode 100644 index 0000000..34c7c8c --- /dev/null +++ b/sql/indexes/category_encrypted_v3_10000000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS category_encrypted_v3_10000000_eq_btree_index; diff --git a/sql/indexes/category_encrypted_v3_10000000_up.sql b/sql/indexes/category_encrypted_v3_10000000_up.sql new file mode 100644 index 0000000..05154b4 --- /dev/null +++ b/sql/indexes/category_encrypted_v3_10000000_up.sql @@ -0,0 +1,2 @@ +CREATE INDEX category_encrypted_v3_10000000_eq_btree_index +ON category_encrypted_v3_10000000 (eql_v3.eq_term(value)); diff --git a/sql/indexes/category_encrypted_v3_1000000_down.sql b/sql/indexes/category_encrypted_v3_1000000_down.sql new file mode 100644 index 0000000..85eadeb --- /dev/null +++ b/sql/indexes/category_encrypted_v3_1000000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS category_encrypted_v3_1000000_eq_btree_index; diff --git a/sql/indexes/category_encrypted_v3_1000000_up.sql b/sql/indexes/category_encrypted_v3_1000000_up.sql new file mode 100644 index 0000000..28f778d --- /dev/null +++ b/sql/indexes/category_encrypted_v3_1000000_up.sql @@ -0,0 +1,6 @@ +-- EQL v3 equality index (public.text_eq): functional btree over eq_term +-- (hmac_256, DOMAIN over text). btree instead of v2's hash — see the +-- string index file for the rationale. + +CREATE INDEX category_encrypted_v3_1000000_eq_btree_index +ON category_encrypted_v3_1000000 (eql_v3.eq_term(value)); diff --git a/sql/indexes/category_encrypted_v3_100000_down.sql b/sql/indexes/category_encrypted_v3_100000_down.sql new file mode 100644 index 0000000..ebc7a5e --- /dev/null +++ b/sql/indexes/category_encrypted_v3_100000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS category_encrypted_v3_100000_eq_btree_index; diff --git a/sql/indexes/category_encrypted_v3_100000_up.sql b/sql/indexes/category_encrypted_v3_100000_up.sql new file mode 100644 index 0000000..0965356 --- /dev/null +++ b/sql/indexes/category_encrypted_v3_100000_up.sql @@ -0,0 +1,6 @@ +-- EQL v3 equality index (public.text_eq): functional btree over eq_term +-- (hmac_256, DOMAIN over text). btree instead of v2's hash — see the +-- string index file for the rationale. + +CREATE INDEX category_encrypted_v3_100000_eq_btree_index +ON category_encrypted_v3_100000 (eql_v3.eq_term(value)); diff --git a/sql/indexes/category_encrypted_v3_10000_down.sql b/sql/indexes/category_encrypted_v3_10000_down.sql new file mode 100644 index 0000000..fd88896 --- /dev/null +++ b/sql/indexes/category_encrypted_v3_10000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS category_encrypted_v3_10000_eq_btree_index; diff --git a/sql/indexes/category_encrypted_v3_10000_up.sql b/sql/indexes/category_encrypted_v3_10000_up.sql new file mode 100644 index 0000000..3aae55c --- /dev/null +++ b/sql/indexes/category_encrypted_v3_10000_up.sql @@ -0,0 +1,6 @@ +-- EQL v3 equality index (public.text_eq): functional btree over eq_term +-- (hmac_256, DOMAIN over text). btree instead of v2's hash — see the +-- string index file for the rationale. + +CREATE INDEX category_encrypted_v3_10000_eq_btree_index +ON category_encrypted_v3_10000 (eql_v3.eq_term(value)); diff --git a/sql/indexes/combo_encrypted_v3_1000000_down.sql b/sql/indexes/combo_encrypted_v3_1000000_down.sql new file mode 100644 index 0000000..0e66090 --- /dev/null +++ b/sql/indexes/combo_encrypted_v3_1000000_down.sql @@ -0,0 +1,3 @@ +DROP INDEX IF EXISTS combo_encrypted_v3_1000000_name_match_gin_index; +DROP INDEX IF EXISTS combo_encrypted_v3_1000000_age_ord_index; +DROP INDEX IF EXISTS combo_encrypted_v3_1000000_category_eq_btree_index; diff --git a/sql/indexes/combo_encrypted_v3_1000000_up.sql b/sql/indexes/combo_encrypted_v3_1000000_up.sql new file mode 100644 index 0000000..841a1a7 --- /dev/null +++ b/sql/indexes/combo_encrypted_v3_1000000_up.sql @@ -0,0 +1,11 @@ +-- EQL v3 combo indexes, mirroring the v2 combo set: bloom GIN on name, +-- ORE btree on age, equality btree on category (v2 used hash here). + +CREATE INDEX combo_encrypted_v3_1000000_name_match_gin_index +ON combo_encrypted_v3_1000000 USING GIN (eql_v3.match_term(name)); + +CREATE INDEX combo_encrypted_v3_1000000_age_ord_index +ON combo_encrypted_v3_1000000 (eql_v3.ord_term(age)); + +CREATE INDEX combo_encrypted_v3_1000000_category_eq_btree_index +ON combo_encrypted_v3_1000000 (eql_v3.eq_term(category)); diff --git a/sql/indexes/combo_encrypted_v3_100000_down.sql b/sql/indexes/combo_encrypted_v3_100000_down.sql new file mode 100644 index 0000000..873f725 --- /dev/null +++ b/sql/indexes/combo_encrypted_v3_100000_down.sql @@ -0,0 +1,3 @@ +DROP INDEX IF EXISTS combo_encrypted_v3_100000_name_match_gin_index; +DROP INDEX IF EXISTS combo_encrypted_v3_100000_age_ord_index; +DROP INDEX IF EXISTS combo_encrypted_v3_100000_category_eq_btree_index; diff --git a/sql/indexes/combo_encrypted_v3_100000_up.sql b/sql/indexes/combo_encrypted_v3_100000_up.sql new file mode 100644 index 0000000..c6532de --- /dev/null +++ b/sql/indexes/combo_encrypted_v3_100000_up.sql @@ -0,0 +1,11 @@ +-- EQL v3 combo indexes, mirroring the v2 combo set: bloom GIN on name, +-- ORE btree on age, equality btree on category (v2 used hash here). + +CREATE INDEX combo_encrypted_v3_100000_name_match_gin_index +ON combo_encrypted_v3_100000 USING GIN (eql_v3.match_term(name)); + +CREATE INDEX combo_encrypted_v3_100000_age_ord_index +ON combo_encrypted_v3_100000 (eql_v3.ord_term(age)); + +CREATE INDEX combo_encrypted_v3_100000_category_eq_btree_index +ON combo_encrypted_v3_100000 (eql_v3.eq_term(category)); diff --git a/sql/indexes/combo_encrypted_v3_10000_down.sql b/sql/indexes/combo_encrypted_v3_10000_down.sql new file mode 100644 index 0000000..1b0dc01 --- /dev/null +++ b/sql/indexes/combo_encrypted_v3_10000_down.sql @@ -0,0 +1,3 @@ +DROP INDEX IF EXISTS combo_encrypted_v3_10000_name_match_gin_index; +DROP INDEX IF EXISTS combo_encrypted_v3_10000_age_ord_index; +DROP INDEX IF EXISTS combo_encrypted_v3_10000_category_eq_btree_index; diff --git a/sql/indexes/combo_encrypted_v3_10000_up.sql b/sql/indexes/combo_encrypted_v3_10000_up.sql new file mode 100644 index 0000000..be7c7b4 --- /dev/null +++ b/sql/indexes/combo_encrypted_v3_10000_up.sql @@ -0,0 +1,11 @@ +-- EQL v3 combo indexes, mirroring the v2 combo set: bloom GIN on name, +-- ORE btree on age, equality btree on category (v2 used hash here). + +CREATE INDEX combo_encrypted_v3_10000_name_match_gin_index +ON combo_encrypted_v3_10000 USING GIN (eql_v3.match_term(name)); + +CREATE INDEX combo_encrypted_v3_10000_age_ord_index +ON combo_encrypted_v3_10000 (eql_v3.ord_term(age)); + +CREATE INDEX combo_encrypted_v3_10000_category_eq_btree_index +ON combo_encrypted_v3_10000 (eql_v3.eq_term(category)); diff --git a/sql/indexes/integer_encrypted_ope_v3_10000000_down.sql b/sql/indexes/integer_encrypted_ope_v3_10000000_down.sql new file mode 100644 index 0000000..dfadf44 --- /dev/null +++ b/sql/indexes/integer_encrypted_ope_v3_10000000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS integer_encrypted_ope_v3_10000000_ope_index; diff --git a/sql/indexes/integer_encrypted_ope_v3_10000000_up.sql b/sql/indexes/integer_encrypted_ope_v3_10000000_up.sql new file mode 100644 index 0000000..ae0ff8d --- /dev/null +++ b/sql/indexes/integer_encrypted_ope_v3_10000000_up.sql @@ -0,0 +1,2 @@ +CREATE INDEX integer_encrypted_ope_v3_10000000_ope_index +ON integer_encrypted_ope_v3_10000000 (eql_v3.ord_ope_term(value)); diff --git a/sql/indexes/integer_encrypted_ope_v3_1000000_down.sql b/sql/indexes/integer_encrypted_ope_v3_1000000_down.sql new file mode 100644 index 0000000..69af58b --- /dev/null +++ b/sql/indexes/integer_encrypted_ope_v3_1000000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS integer_encrypted_ope_v3_1000000_ope_index; diff --git a/sql/indexes/integer_encrypted_ope_v3_1000000_up.sql b/sql/indexes/integer_encrypted_ope_v3_1000000_up.sql new file mode 100644 index 0000000..ea26077 --- /dev/null +++ b/sql/indexes/integer_encrypted_ope_v3_1000000_up.sql @@ -0,0 +1,6 @@ +-- EQL v3 CLLW-OPE ordering index (public.integer_ord_ope): the fast path. +-- ord_ope_term -> eql_v3_internal.ope_cllw (DOMAIN over bytea), so this is +-- a NATIVE bytea btree — no custom comparator anywhere in the chain. + +CREATE INDEX integer_encrypted_ope_v3_1000000_ope_index +ON integer_encrypted_ope_v3_1000000 (eql_v3.ord_ope_term(value)); diff --git a/sql/indexes/integer_encrypted_ope_v3_100000_down.sql b/sql/indexes/integer_encrypted_ope_v3_100000_down.sql new file mode 100644 index 0000000..29adcc6 --- /dev/null +++ b/sql/indexes/integer_encrypted_ope_v3_100000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS integer_encrypted_ope_v3_100000_ope_index; diff --git a/sql/indexes/integer_encrypted_ope_v3_100000_up.sql b/sql/indexes/integer_encrypted_ope_v3_100000_up.sql new file mode 100644 index 0000000..10bffdc --- /dev/null +++ b/sql/indexes/integer_encrypted_ope_v3_100000_up.sql @@ -0,0 +1,6 @@ +-- EQL v3 CLLW-OPE ordering index (public.integer_ord_ope): the fast path. +-- ord_ope_term -> eql_v3_internal.ope_cllw (DOMAIN over bytea), so this is +-- a NATIVE bytea btree — no custom comparator anywhere in the chain. + +CREATE INDEX integer_encrypted_ope_v3_100000_ope_index +ON integer_encrypted_ope_v3_100000 (eql_v3.ord_ope_term(value)); diff --git a/sql/indexes/integer_encrypted_ope_v3_10000_down.sql b/sql/indexes/integer_encrypted_ope_v3_10000_down.sql new file mode 100644 index 0000000..b1364f1 --- /dev/null +++ b/sql/indexes/integer_encrypted_ope_v3_10000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS integer_encrypted_ope_v3_10000_ope_index; diff --git a/sql/indexes/integer_encrypted_ope_v3_10000_up.sql b/sql/indexes/integer_encrypted_ope_v3_10000_up.sql new file mode 100644 index 0000000..8ff525d --- /dev/null +++ b/sql/indexes/integer_encrypted_ope_v3_10000_up.sql @@ -0,0 +1,6 @@ +-- EQL v3 CLLW-OPE ordering index (public.integer_ord_ope): the fast path. +-- ord_ope_term -> eql_v3_internal.ope_cllw (DOMAIN over bytea), so this is +-- a NATIVE bytea btree — no custom comparator anywhere in the chain. + +CREATE INDEX integer_encrypted_ope_v3_10000_ope_index +ON integer_encrypted_ope_v3_10000 (eql_v3.ord_ope_term(value)); diff --git a/sql/indexes/integer_encrypted_v3_10000000_down.sql b/sql/indexes/integer_encrypted_v3_10000000_down.sql new file mode 100644 index 0000000..87395af --- /dev/null +++ b/sql/indexes/integer_encrypted_v3_10000000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS integer_encrypted_v3_10000000_ord_index; diff --git a/sql/indexes/integer_encrypted_v3_10000000_up.sql b/sql/indexes/integer_encrypted_v3_10000000_up.sql new file mode 100644 index 0000000..c6254d4 --- /dev/null +++ b/sql/indexes/integer_encrypted_v3_10000000_up.sql @@ -0,0 +1,2 @@ +CREATE INDEX integer_encrypted_v3_10000000_ord_index +ON integer_encrypted_v3_10000000 (eql_v3.ord_term(value)); diff --git a/sql/indexes/integer_encrypted_v3_1000000_down.sql b/sql/indexes/integer_encrypted_v3_1000000_down.sql new file mode 100644 index 0000000..bd28f72 --- /dev/null +++ b/sql/indexes/integer_encrypted_v3_1000000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS integer_encrypted_v3_1000000_ord_index; diff --git a/sql/indexes/integer_encrypted_v3_1000000_up.sql b/sql/indexes/integer_encrypted_v3_1000000_up.sql new file mode 100644 index 0000000..f33c6a3 --- /dev/null +++ b/sql/indexes/integer_encrypted_v3_1000000_up.sql @@ -0,0 +1,6 @@ +-- EQL v3 ORE ordering index (public.integer_ord): functional btree over the +-- ore_block_256 composite, compared by the custom plpgsql opclass. Build +-- time at scale is a named risk — captured by prepare:_table. + +CREATE INDEX integer_encrypted_v3_1000000_ord_index +ON integer_encrypted_v3_1000000 (eql_v3.ord_term(value)); diff --git a/sql/indexes/integer_encrypted_v3_100000_down.sql b/sql/indexes/integer_encrypted_v3_100000_down.sql new file mode 100644 index 0000000..5d54380 --- /dev/null +++ b/sql/indexes/integer_encrypted_v3_100000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS integer_encrypted_v3_100000_ord_index; diff --git a/sql/indexes/integer_encrypted_v3_100000_up.sql b/sql/indexes/integer_encrypted_v3_100000_up.sql new file mode 100644 index 0000000..4f3eac9 --- /dev/null +++ b/sql/indexes/integer_encrypted_v3_100000_up.sql @@ -0,0 +1,6 @@ +-- EQL v3 ORE ordering index (public.integer_ord): functional btree over the +-- ore_block_256 composite, compared by the custom plpgsql opclass. Build +-- time at scale is a named risk — captured by prepare:_table. + +CREATE INDEX integer_encrypted_v3_100000_ord_index +ON integer_encrypted_v3_100000 (eql_v3.ord_term(value)); diff --git a/sql/indexes/integer_encrypted_v3_10000_down.sql b/sql/indexes/integer_encrypted_v3_10000_down.sql new file mode 100644 index 0000000..09ff248 --- /dev/null +++ b/sql/indexes/integer_encrypted_v3_10000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS integer_encrypted_v3_10000_ord_index; diff --git a/sql/indexes/integer_encrypted_v3_10000_up.sql b/sql/indexes/integer_encrypted_v3_10000_up.sql new file mode 100644 index 0000000..a90530d --- /dev/null +++ b/sql/indexes/integer_encrypted_v3_10000_up.sql @@ -0,0 +1,6 @@ +-- EQL v3 ORE ordering index (public.integer_ord): functional btree over the +-- ore_block_256 composite, compared by the custom plpgsql opclass. Build +-- time at scale is a named risk — captured by prepare:_table. + +CREATE INDEX integer_encrypted_v3_10000_ord_index +ON integer_encrypted_v3_10000 (eql_v3.ord_term(value)); diff --git a/sql/indexes/json_ste_vec_small_encrypted_v3_10000000_down.sql b/sql/indexes/json_ste_vec_small_encrypted_v3_10000000_down.sql new file mode 100644 index 0000000..e6955e1 --- /dev/null +++ b/sql/indexes/json_ste_vec_small_encrypted_v3_10000000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS json_ste_vec_small_encrypted_v3_10000000_jsonb_array_index; diff --git a/sql/indexes/json_ste_vec_small_encrypted_v3_10000000_up.sql b/sql/indexes/json_ste_vec_small_encrypted_v3_10000000_up.sql new file mode 100644 index 0000000..cc26d8c --- /dev/null +++ b/sql/indexes/json_ste_vec_small_encrypted_v3_10000000_up.sql @@ -0,0 +1,12 @@ +-- EQL v3 whole-document containment index for the json ste_vec bench. +-- eql_v3.jsonb_contains(value, needle) inlines to +-- eql_v3.jsonb_array(value) @> eql_v3.jsonb_array(needle), so this GIN over +-- eql_v3.jsonb_array(value) serves both the contains/functional (whole-doc +-- needle) and field_eq/extractor (single-entry needle) scenarios. The +-- per-selector functional btrees for field_eq/field_order are built by the +-- bench at startup (benches/json_v3.rs), mirroring the v2 json bench. + +CREATE INDEX json_ste_vec_small_encrypted_v3_10000000_jsonb_array_index +ON json_ste_vec_small_encrypted_v3_10000000 USING GIN ( + eql_v3.jsonb_array(value) +); diff --git a/sql/indexes/json_ste_vec_small_encrypted_v3_1000000_down.sql b/sql/indexes/json_ste_vec_small_encrypted_v3_1000000_down.sql new file mode 100644 index 0000000..bd29875 --- /dev/null +++ b/sql/indexes/json_ste_vec_small_encrypted_v3_1000000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS json_ste_vec_small_encrypted_v3_1000000_jsonb_array_index; diff --git a/sql/indexes/json_ste_vec_small_encrypted_v3_1000000_up.sql b/sql/indexes/json_ste_vec_small_encrypted_v3_1000000_up.sql new file mode 100644 index 0000000..930b48e --- /dev/null +++ b/sql/indexes/json_ste_vec_small_encrypted_v3_1000000_up.sql @@ -0,0 +1,12 @@ +-- EQL v3 whole-document containment index for the json ste_vec bench. +-- eql_v3.jsonb_contains(value, needle) inlines to +-- eql_v3.jsonb_array(value) @> eql_v3.jsonb_array(needle), so this GIN over +-- eql_v3.jsonb_array(value) serves both the contains/functional (whole-doc +-- needle) and field_eq/extractor (single-entry needle) scenarios. The +-- per-selector functional btrees for field_eq/field_order are built by the +-- bench at startup (benches/json_v3.rs), mirroring the v2 json bench. + +CREATE INDEX json_ste_vec_small_encrypted_v3_1000000_jsonb_array_index +ON json_ste_vec_small_encrypted_v3_1000000 USING GIN ( + eql_v3.jsonb_array(value) +); diff --git a/sql/indexes/json_ste_vec_small_encrypted_v3_100000_down.sql b/sql/indexes/json_ste_vec_small_encrypted_v3_100000_down.sql new file mode 100644 index 0000000..6c18177 --- /dev/null +++ b/sql/indexes/json_ste_vec_small_encrypted_v3_100000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS json_ste_vec_small_encrypted_v3_100000_jsonb_array_index; diff --git a/sql/indexes/json_ste_vec_small_encrypted_v3_100000_up.sql b/sql/indexes/json_ste_vec_small_encrypted_v3_100000_up.sql new file mode 100644 index 0000000..0f13b5f --- /dev/null +++ b/sql/indexes/json_ste_vec_small_encrypted_v3_100000_up.sql @@ -0,0 +1,12 @@ +-- EQL v3 whole-document containment index for the json ste_vec bench. +-- eql_v3.jsonb_contains(value, needle) inlines to +-- eql_v3.jsonb_array(value) @> eql_v3.jsonb_array(needle), so this GIN over +-- eql_v3.jsonb_array(value) serves both the contains/functional (whole-doc +-- needle) and field_eq/extractor (single-entry needle) scenarios. The +-- per-selector functional btrees for field_eq/field_order are built by the +-- bench at startup (benches/json_v3.rs), mirroring the v2 json bench. + +CREATE INDEX json_ste_vec_small_encrypted_v3_100000_jsonb_array_index +ON json_ste_vec_small_encrypted_v3_100000 USING GIN ( + eql_v3.jsonb_array(value) +); diff --git a/sql/indexes/json_ste_vec_small_encrypted_v3_10000_down.sql b/sql/indexes/json_ste_vec_small_encrypted_v3_10000_down.sql new file mode 100644 index 0000000..2299d37 --- /dev/null +++ b/sql/indexes/json_ste_vec_small_encrypted_v3_10000_down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS json_ste_vec_small_encrypted_v3_10000_jsonb_array_index; diff --git a/sql/indexes/json_ste_vec_small_encrypted_v3_10000_up.sql b/sql/indexes/json_ste_vec_small_encrypted_v3_10000_up.sql new file mode 100644 index 0000000..53514d9 --- /dev/null +++ b/sql/indexes/json_ste_vec_small_encrypted_v3_10000_up.sql @@ -0,0 +1,12 @@ +-- EQL v3 whole-document containment index for the json ste_vec bench. +-- eql_v3.jsonb_contains(value, needle) inlines to +-- eql_v3.jsonb_array(value) @> eql_v3.jsonb_array(needle), so this GIN over +-- eql_v3.jsonb_array(value) serves both the contains/functional (whole-doc +-- needle) and field_eq/extractor (single-entry needle) scenarios. The +-- per-selector functional btrees for field_eq/field_order are built by the +-- bench at startup (benches/json_v3.rs), mirroring the v2 json bench. + +CREATE INDEX json_ste_vec_small_encrypted_v3_10000_jsonb_array_index +ON json_ste_vec_small_encrypted_v3_10000 USING GIN ( + eql_v3.jsonb_array(value) +); diff --git a/sql/indexes/string_encrypted_v3_10000000_down.sql b/sql/indexes/string_encrypted_v3_10000000_down.sql new file mode 100644 index 0000000..078938d --- /dev/null +++ b/sql/indexes/string_encrypted_v3_10000000_down.sql @@ -0,0 +1,3 @@ +DROP INDEX IF EXISTS string_encrypted_v3_10000000_eq_btree_index; +DROP INDEX IF EXISTS string_encrypted_v3_10000000_match_gin_index; +DROP INDEX IF EXISTS string_encrypted_v3_10000000_ord_index; diff --git a/sql/indexes/string_encrypted_v3_10000000_up.sql b/sql/indexes/string_encrypted_v3_10000000_up.sql new file mode 100644 index 0000000..f79648d --- /dev/null +++ b/sql/indexes/string_encrypted_v3_10000000_up.sql @@ -0,0 +1,9 @@ +-- See string_encrypted_v3_10000_up.sql for the index rationale. +CREATE INDEX string_encrypted_v3_10000000_eq_btree_index +ON string_encrypted_v3_10000000 (eql_v3.eq_term(value)); + +CREATE INDEX string_encrypted_v3_10000000_match_gin_index +ON string_encrypted_v3_10000000 USING GIN (eql_v3.match_term(value)); + +CREATE INDEX string_encrypted_v3_10000000_ord_index +ON string_encrypted_v3_10000000 (eql_v3.ord_term(value)); diff --git a/sql/indexes/string_encrypted_v3_1000000_down.sql b/sql/indexes/string_encrypted_v3_1000000_down.sql new file mode 100644 index 0000000..0da5a8b --- /dev/null +++ b/sql/indexes/string_encrypted_v3_1000000_down.sql @@ -0,0 +1,3 @@ +DROP INDEX IF EXISTS string_encrypted_v3_1000000_eq_btree_index; +DROP INDEX IF EXISTS string_encrypted_v3_1000000_match_gin_index; +DROP INDEX IF EXISTS string_encrypted_v3_1000000_ord_index; diff --git a/sql/indexes/string_encrypted_v3_1000000_up.sql b/sql/indexes/string_encrypted_v3_1000000_up.sql new file mode 100644 index 0000000..fd88d20 --- /dev/null +++ b/sql/indexes/string_encrypted_v3_1000000_up.sql @@ -0,0 +1,23 @@ +-- EQL v3 functional indexes for the string bench (public.text_search). +-- +-- eq_term -> eql_v3_internal.hmac_256 (DOMAIN over text): btree, NOT hash. +-- v2 used hash here; hash index builds degrade badly at scale (see the +-- benches/json.rs commentary and the native-pg derisk experiment), and +-- btree also serves GROUP BY. The comparison report flags the index-type +-- delta; a 10k-only hash datapoint disambiguates. +-- match_term -> eql_v3_internal.bloom_filter (DOMAIN over smallint[]): v3 +-- ships no GIN opclass, so this GIN relies on the base type's native +-- array_ops. Engagement is smoke-gated (verify:v3-plans) — if it does not +-- engage, that is a headline finding for the release. +-- ord_term -> eql_v3_internal.ore_block_256 (composite): custom btree +-- opclass with a plpgsql comparator; build time is captured by +-- prepare:_table into results/ingest/index_build_times.jsonl. + +CREATE INDEX string_encrypted_v3_1000000_eq_btree_index +ON string_encrypted_v3_1000000 (eql_v3.eq_term(value)); + +CREATE INDEX string_encrypted_v3_1000000_match_gin_index +ON string_encrypted_v3_1000000 USING GIN (eql_v3.match_term(value)); + +CREATE INDEX string_encrypted_v3_1000000_ord_index +ON string_encrypted_v3_1000000 (eql_v3.ord_term(value)); diff --git a/sql/indexes/string_encrypted_v3_100000_down.sql b/sql/indexes/string_encrypted_v3_100000_down.sql new file mode 100644 index 0000000..00c5958 --- /dev/null +++ b/sql/indexes/string_encrypted_v3_100000_down.sql @@ -0,0 +1,3 @@ +DROP INDEX IF EXISTS string_encrypted_v3_100000_eq_btree_index; +DROP INDEX IF EXISTS string_encrypted_v3_100000_match_gin_index; +DROP INDEX IF EXISTS string_encrypted_v3_100000_ord_index; diff --git a/sql/indexes/string_encrypted_v3_100000_up.sql b/sql/indexes/string_encrypted_v3_100000_up.sql new file mode 100644 index 0000000..84bb500 --- /dev/null +++ b/sql/indexes/string_encrypted_v3_100000_up.sql @@ -0,0 +1,23 @@ +-- EQL v3 functional indexes for the string bench (public.text_search). +-- +-- eq_term -> eql_v3_internal.hmac_256 (DOMAIN over text): btree, NOT hash. +-- v2 used hash here; hash index builds degrade badly at scale (see the +-- benches/json.rs commentary and the native-pg derisk experiment), and +-- btree also serves GROUP BY. The comparison report flags the index-type +-- delta; a 10k-only hash datapoint disambiguates. +-- match_term -> eql_v3_internal.bloom_filter (DOMAIN over smallint[]): v3 +-- ships no GIN opclass, so this GIN relies on the base type's native +-- array_ops. Engagement is smoke-gated (verify:v3-plans) — if it does not +-- engage, that is a headline finding for the release. +-- ord_term -> eql_v3_internal.ore_block_256 (composite): custom btree +-- opclass with a plpgsql comparator; build time is captured by +-- prepare:_table into results/ingest/index_build_times.jsonl. + +CREATE INDEX string_encrypted_v3_100000_eq_btree_index +ON string_encrypted_v3_100000 (eql_v3.eq_term(value)); + +CREATE INDEX string_encrypted_v3_100000_match_gin_index +ON string_encrypted_v3_100000 USING GIN (eql_v3.match_term(value)); + +CREATE INDEX string_encrypted_v3_100000_ord_index +ON string_encrypted_v3_100000 (eql_v3.ord_term(value)); diff --git a/sql/indexes/string_encrypted_v3_10000_down.sql b/sql/indexes/string_encrypted_v3_10000_down.sql new file mode 100644 index 0000000..fe45e17 --- /dev/null +++ b/sql/indexes/string_encrypted_v3_10000_down.sql @@ -0,0 +1,3 @@ +DROP INDEX IF EXISTS string_encrypted_v3_10000_eq_btree_index; +DROP INDEX IF EXISTS string_encrypted_v3_10000_match_gin_index; +DROP INDEX IF EXISTS string_encrypted_v3_10000_ord_index; diff --git a/sql/indexes/string_encrypted_v3_10000_up.sql b/sql/indexes/string_encrypted_v3_10000_up.sql new file mode 100644 index 0000000..f0128ff --- /dev/null +++ b/sql/indexes/string_encrypted_v3_10000_up.sql @@ -0,0 +1,23 @@ +-- EQL v3 functional indexes for the string bench (public.text_search). +-- +-- eq_term -> eql_v3_internal.hmac_256 (DOMAIN over text): btree, NOT hash. +-- v2 used hash here; hash index builds degrade badly at scale (see the +-- benches/json.rs commentary and the native-pg derisk experiment), and +-- btree also serves GROUP BY. The comparison report flags the index-type +-- delta; a 10k-only hash datapoint disambiguates. +-- match_term -> eql_v3_internal.bloom_filter (DOMAIN over smallint[]): v3 +-- ships no GIN opclass, so this GIN relies on the base type's native +-- array_ops. Engagement is smoke-gated (verify:v3-plans) — if it does not +-- engage, that is a headline finding for the release. +-- ord_term -> eql_v3_internal.ore_block_256 (composite): custom btree +-- opclass with a plpgsql comparator; build time is captured by +-- prepare:_table into results/ingest/index_build_times.jsonl. + +CREATE INDEX string_encrypted_v3_10000_eq_btree_index +ON string_encrypted_v3_10000 (eql_v3.eq_term(value)); + +CREATE INDEX string_encrypted_v3_10000_match_gin_index +ON string_encrypted_v3_10000 USING GIN (eql_v3.match_term(value)); + +CREATE INDEX string_encrypted_v3_10000_ord_index +ON string_encrypted_v3_10000 (eql_v3.ord_term(value)); diff --git a/sql/plaintext_baselines.sql b/sql/plaintext_baselines.sql new file mode 100644 index 0000000..032fafb --- /dev/null +++ b/sql/plaintext_baselines.sql @@ -0,0 +1,56 @@ +-- Plaintext baseline tables for the v3 encrypted-vs-plaintext comparison +-- (the docs/marketing "overhead vs native Postgres" story). Same tiers as +-- the encrypted tables; populated by pure SQL (`prepare:integer_plaintext`, +-- `prepare:json_small_plaintext`) — no encryption client involved. +-- +-- string_plaintext_ and category_plaintext_ already exist in +-- sql/schema.sql (shared with the v2 benches). + +CREATE TABLE IF NOT EXISTS integer_plaintext_10000 ( + id SERIAL PRIMARY KEY, + value INT NOT NULL +); + +CREATE TABLE IF NOT EXISTS integer_plaintext_100000 ( + id SERIAL PRIMARY KEY, + value INT NOT NULL +); + +CREATE TABLE IF NOT EXISTS integer_plaintext_1000000 ( + id SERIAL PRIMARY KEY, + value INT NOT NULL +); + +-- Small JSON documents shaped like FakeJsonSmall (first_name, last_name, +-- age, email) so the containment / field-eq scenarios compare like shapes. +CREATE TABLE IF NOT EXISTS json_small_plaintext_10000 ( + id SERIAL PRIMARY KEY, + value JSONB NOT NULL +); + +CREATE TABLE IF NOT EXISTS json_small_plaintext_100000 ( + id SERIAL PRIMARY KEY, + value JSONB NOT NULL +); + +CREATE TABLE IF NOT EXISTS json_small_plaintext_1000000 ( + id SERIAL PRIMARY KEY, + value JSONB NOT NULL +); + +-- 10M tier plaintext baselines (CIP-3361 chart band). +CREATE TABLE IF NOT EXISTS string_plaintext_10000000 ( + id SERIAL PRIMARY KEY, + value TEXT NOT NULL +); + +CREATE TABLE IF NOT EXISTS integer_plaintext_10000000 ( + id SERIAL PRIMARY KEY, + value INT NOT NULL +); + +CREATE TABLE IF NOT EXISTS json_small_plaintext_10000000 ( + id SERIAL PRIMARY KEY, + value JSONB NOT NULL +); + diff --git a/sql/schema_v3.sql b/sql/schema_v3.sql new file mode 100644 index 0000000..c424048 --- /dev/null +++ b/sql/schema_v3.sql @@ -0,0 +1,204 @@ +-- EQL v3 bench tables. Parallel to sql/schema.sql (the v2 tables, which stay +-- untouched as the regression baseline) — same row-count tiers, same shapes, +-- but columns are eql_v3 domain types instead of the eql_v2_encrypted +-- composite. Installed by `mise run setup-db-v3` after the v3 bundle. +-- +-- Domain choice per table (a v3 column is exactly ONE domain — capability is +-- encoded in the type, unlike v2's single catch-all): +-- +-- * string_*: public.text_search (hm + ob + bf) — the only v3 domain that +-- carries both equality and match terms, matching v2's unique+match +-- string config. Requires the ingest config to add an ORE index on top +-- of v2's unique+match (from_v2 fails closed on a missing `ob`); rows +-- are correspondingly wider than their v2 siblings — noted in the report. +-- * integer_*: public.integer_ord — the default ordering domain (ORE +-- block term, custom btree opclass), v2 ORE bench parity. +-- * integer_*_ope: public.integer_ord_ope — the new CLLW-OPE fast path +-- (hex term, native bytea btree). Real `op` terms from +-- cipherstash-client >= 0.38.1 (Index::new_ope, CIP-3280/CIP-3348). +-- * category_*: public.text_eq (hm only) — GROUP BY / equality parity. +-- * combo_*: per-column domains mirroring the v2 combo configs. +-- * json_*: public.json — the SteVec document domain. +-- +-- Tiers stop at 1M for the v3 pass (10M deferred; see plan). + +-- Unsuffixed base tables: targets for the hyperfine ingest benchmarks +-- (`bench:v3:ingest:*`), which TRUNCATE + refill per run. The tiered +-- variants below serve the query benches. +CREATE TABLE IF NOT EXISTS string_encrypted_v3 ( + id SERIAL PRIMARY KEY, + value public.text_search NOT NULL +); + +CREATE TABLE IF NOT EXISTS integer_encrypted_v3 ( + id SERIAL PRIMARY KEY, + value public.integer_ord NOT NULL +); + +CREATE TABLE IF NOT EXISTS integer_encrypted_ope_v3 ( + id SERIAL PRIMARY KEY, + value public.integer_ord_ope NOT NULL +); + +CREATE TABLE IF NOT EXISTS category_encrypted_v3 ( + id SERIAL PRIMARY KEY, + value public.text_eq NOT NULL +); + +CREATE TABLE IF NOT EXISTS combo_encrypted_v3 ( + id SERIAL PRIMARY KEY, + name public.text_search NOT NULL, + age public.integer_ord NOT NULL, + category public.text_eq NOT NULL +); + +CREATE TABLE IF NOT EXISTS json_ste_vec_small_encrypted_v3 ( + id SERIAL PRIMARY KEY, + value public.json NOT NULL +); + +-- String: equality + match + ordering (text_search). +CREATE TABLE IF NOT EXISTS string_encrypted_v3_10000 ( + id SERIAL PRIMARY KEY, + value public.text_search NOT NULL +); + +CREATE TABLE IF NOT EXISTS string_encrypted_v3_100000 ( + id SERIAL PRIMARY KEY, + value public.text_search NOT NULL +); + +CREATE TABLE IF NOT EXISTS string_encrypted_v3_1000000 ( + id SERIAL PRIMARY KEY, + value public.text_search NOT NULL +); + +-- Integer: ORE ordering (default `_ord` domain). +CREATE TABLE IF NOT EXISTS integer_encrypted_v3_10000 ( + id SERIAL PRIMARY KEY, + value public.integer_ord NOT NULL +); + +CREATE TABLE IF NOT EXISTS integer_encrypted_v3_100000 ( + id SERIAL PRIMARY KEY, + value public.integer_ord NOT NULL +); + +CREATE TABLE IF NOT EXISTS integer_encrypted_v3_1000000 ( + id SERIAL PRIMARY KEY, + value public.integer_ord NOT NULL +); + +-- Integer OPE: the v3 fast ordering path (native bytea btree over the +-- hex-decoded `op` term — no custom comparator anywhere in the chain). +CREATE TABLE IF NOT EXISTS integer_encrypted_ope_v3_10000 ( + id SERIAL PRIMARY KEY, + value public.integer_ord_ope NOT NULL +); + +CREATE TABLE IF NOT EXISTS integer_encrypted_ope_v3_100000 ( + id SERIAL PRIMARY KEY, + value public.integer_ord_ope NOT NULL +); + +CREATE TABLE IF NOT EXISTS integer_encrypted_ope_v3_1000000 ( + id SERIAL PRIMARY KEY, + value public.integer_ord_ope NOT NULL +); + +-- Category: low-cardinality equality (GROUP BY scenarios). Same ~250-bucket +-- generator as v2; shares the v2 category_plaintext_* baselines. +CREATE TABLE IF NOT EXISTS category_encrypted_v3_10000 ( + id SERIAL PRIMARY KEY, + value public.text_eq NOT NULL +); + +CREATE TABLE IF NOT EXISTS category_encrypted_v3_100000 ( + id SERIAL PRIMARY KEY, + value public.text_eq NOT NULL +); + +CREATE TABLE IF NOT EXISTS category_encrypted_v3_1000000 ( + id SERIAL PRIMARY KEY, + value public.text_eq NOT NULL +); + +-- Combo: three encrypted columns per row (composite-predicate scenarios). +CREATE TABLE IF NOT EXISTS combo_encrypted_v3_10000 ( + id SERIAL PRIMARY KEY, + name public.text_search NOT NULL, + age public.integer_ord NOT NULL, + category public.text_eq NOT NULL +); + +CREATE TABLE IF NOT EXISTS combo_encrypted_v3_100000 ( + id SERIAL PRIMARY KEY, + name public.text_search NOT NULL, + age public.integer_ord NOT NULL, + category public.text_eq NOT NULL +); + +CREATE TABLE IF NOT EXISTS combo_encrypted_v3_1000000 ( + id SERIAL PRIMARY KEY, + name public.text_search NOT NULL, + age public.integer_ord NOT NULL, + category public.text_eq NOT NULL +); + +-- JSON SteVec (small documents — 4 flat fields). +CREATE TABLE IF NOT EXISTS json_ste_vec_small_encrypted_v3_10000 ( + id SERIAL PRIMARY KEY, + value public.json NOT NULL +); + +CREATE TABLE IF NOT EXISTS json_ste_vec_small_encrypted_v3_100000 ( + id SERIAL PRIMARY KEY, + value public.json NOT NULL +); + +CREATE TABLE IF NOT EXISTS json_ste_vec_small_encrypted_v3_1000000 ( + id SERIAL PRIMARY KEY, + value public.json NOT NULL +); + +-- New-family smoke table (10k only): one column per v3 scalar family the v2 +-- benches never covered. Catches CHECK/operator/inlining breakage per +-- family; not intended to produce tier curves. `boolean` is storage-only by +-- design (two-value cardinality — any index would leak the plaintext), so it +-- gets insert/select-back coverage only. +CREATE TABLE IF NOT EXISTS scalar_smoke_v3 ( + id SERIAL PRIMARY KEY, + date_val public.date_ord NOT NULL, + timestamp_val public.timestamp_ord NOT NULL, + numeric_val public.numeric_ord NOT NULL, + bigint_val public.bigint_ord NOT NULL, + double_val public.double_ord NOT NULL, + boolean_val public.boolean NOT NULL +); + +-- 10M tier (added for CIP-3361's 10k -> 10M flat-latency chart; the +-- other families stay capped at 1M). +CREATE TABLE IF NOT EXISTS string_encrypted_v3_10000000 ( + id SERIAL PRIMARY KEY, + value public.text_search NOT NULL +); + +CREATE TABLE IF NOT EXISTS integer_encrypted_v3_10000000 ( + id SERIAL PRIMARY KEY, + value public.integer_ord NOT NULL +); + +CREATE TABLE IF NOT EXISTS integer_encrypted_ope_v3_10000000 ( + id SERIAL PRIMARY KEY, + value public.integer_ord_ope NOT NULL +); + +CREATE TABLE IF NOT EXISTS json_ste_vec_small_encrypted_v3_10000000 ( + id SERIAL PRIMARY KEY, + value public.json NOT NULL +); + +CREATE TABLE IF NOT EXISTS category_encrypted_v3_10000000 ( + id SERIAL PRIMARY KEY, + value public.text_eq NOT NULL +); diff --git a/src/bin/decrypt_probe.rs b/src/bin/decrypt_probe.rs new file mode 100644 index 0000000..6095d04 --- /dev/null +++ b/src/bin/decrypt_probe.rs @@ -0,0 +1,47 @@ +//! Decrypt probe: sample and decrypt one row from an encrypted bench table. +//! +//! Diagnoses credential/workspace/keyset issues without running a full +//! bench — e.g. "which workspace was this table encrypted under?" (run with +//! CS_WORKSPACE_ID= per candidate) or "has the scoped-cipher TTL +//! behaviour changed?". Works against both v2 (`eql_v2_encrypted`) and v3 +//! (`eql_v3.*` domain) tables — pass `--v3` for v3. +//! +//! Usage: +//! decrypt_probe [--v3] +//! +//! Prints the decrypted sample on success; exits non-zero on failure. + +use anyhow::{Context, Result}; +use dbbenches::{init_scoped_cipher, sample_plaintext_string, v3::sample_plaintext_string_v3}; +use sqlx::postgres::PgPoolOptions; +use std::env; + +#[tokio::main] +async fn main() -> Result<()> { + dbbenches::init_tracing(); + + let args: Vec = env::args().collect(); + let table = args + .get(1) + .context("usage: decrypt_probe
[--v3]")? + .clone(); + let is_v3 = args.iter().any(|a| a == "--v3"); + + let database_url = + env::var("DATABASE_URL").context("DATABASE_URL environment variable must be set")?; + let pool = PgPoolOptions::new() + .max_connections(1) + .connect(&database_url) + .await?; + + let cipher = init_scoped_cipher().await?; + + let sample = if is_v3 { + sample_plaintext_string_v3(&pool, cipher, &table).await? + } else { + sample_plaintext_string(&pool, cipher, &table).await? + }; + + println!("decrypt OK: {} -> {:?}", table, sample); + Ok(()) +} diff --git a/src/bin/encrypt_category_v3.rs b/src/bin/encrypt_category_v3.rs new file mode 100644 index 0000000..ac9ccdf --- /dev/null +++ b/src/bin/encrypt_category_v3.rs @@ -0,0 +1,43 @@ +//! v3 sibling of `encrypt_category`: low-cardinality categorical strings +//! (`CAT_001`..`CAT_250`) into `category_encrypted_v3_*` as +//! `public.text_eq` payloads (hm only — GROUP BY / equality scenarios). +//! +//! Environment variables: DATABASE_URL, NUM_RECORDS, TABLE_SUFFIX, +//! V3_CONVERT_ONLY, CS_CLIENT_ID / CS_CLIENT_KEY / CS_WORKSPACE_CRN. + +use anyhow::Result; +use cipherstash_client::{ + eql::Identifier, + schema::{column::Index, ColumnConfig, ColumnType}, +}; +use dbbenches::{v3::TargetDomain, FakeCategory, IngestOptionsBuilder}; +use std::env; + +#[tokio::main] +async fn main() -> Result<()> { + dbbenches::init_tracing(); + + let num_records: i32 = env::var("NUM_RECORDS") + .unwrap_or_else(|_| "10000".to_string()) + .parse() + .expect("NUM_RECORDS must be a valid integer"); + + let table_suffix = env::var("TABLE_SUFFIX").unwrap_or_default(); + let table_name = format!("category_encrypted_v3{}", table_suffix); + + IngestOptionsBuilder::new("encrypt_category_v3") + .num_records(num_records) + .batch_size(1000) + .identifier(Identifier::new(&table_name, "value")) + .column_config( + ColumnConfig::build("value") + .casts_as(ColumnType::Text) + .add_index(Index::new_unique()), + ) + .convert_to_v3(TargetDomain::parse("text_eq").expect("text_eq is a v3 domain")) + .build()? + .ingest::(FakeCategory) + .await?; + + Ok(()) +} diff --git a/src/bin/encrypt_combo_v3.rs b/src/bin/encrypt_combo_v3.rs new file mode 100644 index 0000000..3a88ea3 --- /dev/null +++ b/src/bin/encrypt_combo_v3.rs @@ -0,0 +1,132 @@ +//! v3 sibling of `encrypt_combo`: three-column rows (`name`, `age`, +//! `category`) into `combo_encrypted_v3_*`, with per-column v3 targets: +//! +//! * `name` → public.text_search (unique+match+ore config; see +//! encrypt_string_v3 for why ORE is added) +//! * `age` → public.integer_ord +//! * `category` → public.text_eq +//! +//! Environment variables: DATABASE_URL, NUM_RECORDS, TABLE_SUFFIX, +//! CS_CLIENT_ID / CS_CLIENT_KEY / CS_WORKSPACE_CRN. + +use anyhow::{Context, Result}; +use cipherstash_client::{ + encryption::Plaintext, + eql::{encrypt_eql, EqlCiphertext, EqlOperation, EqlOutput, Identifier, PreparedPlaintext}, + schema::{column::Index, ColumnConfig, ColumnType}, +}; +use dbbenches::{init_scoped_cipher, v3::to_v3_stored, FakeCategory}; +use fake::{faker::name::raw::Name, locales::EN, Fake}; +use sqlx::{postgres::PgPoolOptions, types::Json, QueryBuilder}; +use std::borrow::Cow; +use std::env; + +#[tokio::main] +async fn main() -> Result<()> { + dbbenches::init_tracing(); + + let database_url = + env::var("DATABASE_URL").context("DATABASE_URL environment variable must be set")?; + let num_records: i32 = env::var("NUM_RECORDS") + .unwrap_or_else(|_| "10000".to_string()) + .parse() + .expect("NUM_RECORDS must be a valid integer"); + let table_suffix = env::var("TABLE_SUFFIX").unwrap_or_default(); + let table_name = format!("combo_encrypted_v3{}", table_suffix); + let batch_size: usize = 1000; + + let pool = PgPoolOptions::new() + .max_connections(5) + .connect(&database_url) + .await?; + + let scoped_cipher = init_scoped_cipher().await?; + + let name_config = ColumnConfig::build("name") + .casts_as(ColumnType::Text) + .add_index(Index::new_unique()) + .add_index(Index::new_match()) + .add_index(Index::new_ore()); + let age_config = ColumnConfig::build("age") + .casts_as(ColumnType::Int) + .add_index(Index::new_ore()); + let category_config = ColumnConfig::build("category") + .casts_as(ColumnType::Text) + .add_index(Index::new_unique()); + + let name_ident = Identifier::new(&table_name, "name"); + let age_ident = Identifier::new(&table_name, "age"); + let category_ident = Identifier::new(&table_name, "category"); + + for batch_start in (0..num_records).step_by(batch_size) { + let batch_end = (batch_start + batch_size as i32).min(num_records); + let batch_count = batch_end - batch_start; + + let mut prepared = Vec::with_capacity((batch_count * 3) as usize); + for _ in 0..batch_count { + let name: String = Name(EN).fake(); + let age: i32 = (18..=90).fake(); + let category: String = FakeCategory.fake(); + + prepared.push(PreparedPlaintext::new( + Cow::Borrowed(&name_config), + name_ident.clone(), + Plaintext::new(name), + EqlOperation::Store, + )); + prepared.push(PreparedPlaintext::new( + Cow::Borrowed(&age_config), + age_ident.clone(), + Plaintext::new(age), + EqlOperation::Store, + )); + prepared.push(PreparedPlaintext::new( + Cow::Borrowed(&category_config), + category_ident.clone(), + Plaintext::new(category), + EqlOperation::Store, + )); + } + + let out = encrypt_eql(scoped_cipher.clone(), prepared, &Default::default()).await?; + + let ciphertexts: Vec = out + .into_iter() + .map(|o| match o { + EqlOutput::Store(ct) => ct, + EqlOutput::Query(_) => { + unreachable!("storage batch must yield EqlOutput::Store") + } + }) + .collect(); + + // encrypt_eql preserves input order; chunks of 3 reassemble per-row + // (name, age, category) tuples, each converted to its column's v3 + // domain payload. + let rows = ciphertexts + .chunks_exact(3) + .map(|c| { + Ok(( + to_v3_stored(&c[0], "text_search")?, + to_v3_stored(&c[1], "integer_ord")?, + to_v3_stored(&c[2], "text_eq")?, + )) + }) + .collect::>>()?; + + QueryBuilder::new(format!( + "INSERT INTO {} (name, age, category) ", + table_name + )) + .push_values(rows, |mut b, (name, age, category)| { + b.push_bind(Json(name)); + b.push_bind(Json(age)); + b.push_bind(Json(category)); + }) + .build() + .execute(&pool) + .await?; + } + + Ok(()) +} diff --git a/src/bin/encrypt_int_ope_v3.rs b/src/bin/encrypt_int_ope_v3.rs new file mode 100644 index 0000000..0911cbc --- /dev/null +++ b/src/bin/encrypt_int_ope_v3.rs @@ -0,0 +1,49 @@ +//! Random i32s into `integer_encrypted_ope_v3_*` as `public.integer_ord_ope` +//! payloads — the v3 CLLW-OPE fast ordering path (native bytea btree). +//! +//! cipherstash-client 0.38.1 emits the scalar OPE-CLLW `op` term for +//! columns configured with `Index::new_ope()` (CIP-3280/CIP-3348), so this +//! is REAL OPE ciphertext end-to-end — the earlier synthetic-op workaround +//! is retired, and ciphertext sizes / client-side term-generation cost are +//! now representative. +//! +//! Environment variables: DATABASE_URL, NUM_RECORDS, TABLE_SUFFIX, +//! V3_CONVERT_ONLY, CS_CLIENT_ID / CS_CLIENT_KEY / CS_WORKSPACE_CRN. + +use anyhow::Result; +use cipherstash_client::{ + eql::Identifier, + schema::{column::Index, ColumnConfig, ColumnType}, +}; +use dbbenches::{v3::TargetDomain, IngestOptionsBuilder}; +use fake::Faker; +use std::env; + +#[tokio::main] +async fn main() -> Result<()> { + dbbenches::init_tracing(); + + let num_records: i32 = env::var("NUM_RECORDS") + .unwrap_or_else(|_| "10000".to_string()) + .parse() + .expect("NUM_RECORDS must be a valid integer"); + + let table_suffix = env::var("TABLE_SUFFIX").unwrap_or_default(); + let table_name = format!("integer_encrypted_ope_v3{}", table_suffix); + + IngestOptionsBuilder::new("encrypt_int_ope_v3") + .num_records(num_records) + .batch_size(1000) + .identifier(Identifier::new(&table_name, "value")) + .column_config( + ColumnConfig::build("value") + .casts_as(ColumnType::Int) + .add_index(Index::new_ope()), + ) + .convert_to_v3(TargetDomain::parse("integer_ord_ope").expect("integer_ord_ope is a v3 domain")) + .build()? + .ingest::(Faker) + .await?; + + Ok(()) +} diff --git a/src/bin/encrypt_int_v3.rs b/src/bin/encrypt_int_v3.rs new file mode 100644 index 0000000..e0b519d --- /dev/null +++ b/src/bin/encrypt_int_v3.rs @@ -0,0 +1,43 @@ +//! v3 sibling of `encrypt_int`: random i32s into `integer_encrypted_v3_*` +//! as `public.integer_ord` payloads (ORE block term, custom btree opclass). +//! +//! Environment variables: DATABASE_URL, NUM_RECORDS, TABLE_SUFFIX, +//! V3_CONVERT_ONLY, CS_CLIENT_ID / CS_CLIENT_KEY / CS_WORKSPACE_CRN. + +use anyhow::Result; +use cipherstash_client::{ + eql::Identifier, + schema::{column::Index, ColumnConfig, ColumnType}, +}; +use dbbenches::{v3::TargetDomain, IngestOptionsBuilder}; +use fake::Faker; +use std::env; + +#[tokio::main] +async fn main() -> Result<()> { + dbbenches::init_tracing(); + + let num_records: i32 = env::var("NUM_RECORDS") + .unwrap_or_else(|_| "10000".to_string()) + .parse() + .expect("NUM_RECORDS must be a valid integer"); + + let table_suffix = env::var("TABLE_SUFFIX").unwrap_or_default(); + let table_name = format!("integer_encrypted_v3{}", table_suffix); + + IngestOptionsBuilder::new("encrypt_int_v3") + .num_records(num_records) + .batch_size(1000) + .identifier(Identifier::new(&table_name, "value")) + .column_config( + ColumnConfig::build("value") + .casts_as(ColumnType::Int) + .add_index(Index::new_ore()), + ) + .convert_to_v3(TargetDomain::parse("integer_ord").expect("integer_ord is a v3 domain")) + .build()? + .ingest::(Faker) + .await?; + + Ok(()) +} diff --git a/src/bin/encrypt_scalar_smoke_v3.rs b/src/bin/encrypt_scalar_smoke_v3.rs new file mode 100644 index 0000000..e2909af --- /dev/null +++ b/src/bin/encrypt_scalar_smoke_v3.rs @@ -0,0 +1,149 @@ +//! Populate `scalar_smoke_v3` — one column per v3 scalar family the v2 +//! benches never covered (date, timestamp, numeric, bigint, double, +//! boolean). Smoke coverage only: catches per-family CHECK/conversion +//! breakage, not tier curves. +//! +//! Encrypts each family through the pinned v2 client (ORE index for the +//! ordered families, no index for boolean) and converts to the family's +//! `_ord` domain (`boolean` is storage-only). A conversion failure aborts +//! with the family name — e.g. if the v2 client cannot emit `ob` for a type, +//! that is a release-relevant finding, not something to paper over. +//! +//! Environment variables: DATABASE_URL, NUM_RECORDS (default 10000), +//! CS_CLIENT_ID / CS_CLIENT_KEY / CS_WORKSPACE_CRN. + +use anyhow::{Context, Result}; +use chrono::{Duration, TimeZone, Utc}; +use cipherstash_client::{ + encryption::Plaintext, + eql::{encrypt_eql, EqlCiphertext, EqlOperation, EqlOutput, Identifier, PreparedPlaintext}, + schema::{column::Index, ColumnConfig, ColumnType}, +}; +use dbbenches::{init_scoped_cipher, v3::to_v3_stored}; +use fake::Fake; +use rust_decimal::Decimal; +use sqlx::{postgres::PgPoolOptions, types::Json, QueryBuilder}; +use std::borrow::Cow; +use std::env; + +const TABLE: &str = "scalar_smoke_v3"; +const FAMILIES: [&str; 6] = [ + "date_ord", + "timestamp_ord", + "numeric_ord", + "bigint_ord", + "double_ord", + "boolean", +]; + +#[tokio::main] +async fn main() -> Result<()> { + dbbenches::init_tracing(); + + let database_url = + env::var("DATABASE_URL").context("DATABASE_URL environment variable must be set")?; + let num_records: i32 = env::var("NUM_RECORDS") + .unwrap_or_else(|_| "10000".to_string()) + .parse() + .expect("NUM_RECORDS must be a valid integer"); + let batch_size: usize = 1000; + + let pool = PgPoolOptions::new() + .max_connections(5) + .connect(&database_url) + .await?; + + let scoped_cipher = init_scoped_cipher().await?; + + let ord = |name: &str, ty: ColumnType| { + ColumnConfig::build(name) + .casts_as(ty) + .add_index(Index::new_ore()) + }; + let configs = [ + ord("date_val", ColumnType::Date), + ord("timestamp_val", ColumnType::Timestamp), + ord("numeric_val", ColumnType::Decimal), + ord("bigint_val", ColumnType::BigInt), + ord("double_val", ColumnType::Float), + // boolean is storage-only by design (two-value cardinality — any + // searchable index leaks the plaintext). + ColumnConfig::build("boolean_val").casts_as(ColumnType::Boolean), + ]; + let idents: Vec = configs + .iter() + .map(|c| Identifier::new(TABLE, &c.name)) + .collect(); + + let epoch = Utc.with_ymd_and_hms(2000, 1, 1, 0, 0, 0).unwrap(); + + for batch_start in (0..num_records).step_by(batch_size) { + let batch_end = (batch_start + batch_size as i32).min(num_records); + let batch_count = batch_end - batch_start; + + let mut prepared = Vec::with_capacity((batch_count * 6) as usize); + for _ in 0..batch_count { + let days: i64 = (0..10_000).fake(); + let secs: i64 = (0..800_000_000).fake(); + let values: [Plaintext; 6] = [ + Plaintext::NaiveDate(Some((epoch + Duration::days(days)).date_naive())), + Plaintext::Timestamp(Some(epoch + Duration::seconds(secs))), + Plaintext::Decimal(Some(Decimal::new((0..10_000_000i64).fake(), 2))), + Plaintext::BigInt(Some((0..i64::MAX).fake())), + Plaintext::Float(Some((0.0..1_000_000.0f64).fake())), + Plaintext::Boolean(Some((0..2).fake::() == 1)), + ]; + for ((config, ident), value) in configs.iter().zip(&idents).zip(values) { + prepared.push(PreparedPlaintext::new( + Cow::Borrowed(config), + ident.clone(), + value, + EqlOperation::Store, + )); + } + } + + let out = encrypt_eql(scoped_cipher.clone(), prepared, &Default::default()).await?; + + let ciphertexts: Vec = out + .into_iter() + .map(|o| match o { + EqlOutput::Store(ct) => ct, + EqlOutput::Query(_) => { + unreachable!("storage batch must yield EqlOutput::Store") + } + }) + .collect(); + + let rows = ciphertexts + .chunks_exact(6) + .map(|chunk| { + chunk + .iter() + .zip(FAMILIES) + .map(|(ct, family)| { + to_v3_stored(ct, family).with_context(|| { + format!("v3 conversion failed for family `{}`", family) + }) + }) + .collect::>>() + }) + .collect::>>()?; + + QueryBuilder::new(format!( + "INSERT INTO {} (date_val, timestamp_val, numeric_val, bigint_val, double_val, boolean_val) ", + TABLE + )) + .push_values(rows, |mut b, row| { + for v in row { + b.push_bind(Json(v)); + } + }) + .build() + .execute(&pool) + .await?; + } + + println!("scalar_smoke_v3: inserted {} rows across {:?}", num_records, FAMILIES); + Ok(()) +} diff --git a/src/bin/encrypt_ste_vec_small_v3.rs b/src/bin/encrypt_ste_vec_small_v3.rs new file mode 100644 index 0000000..987a885 --- /dev/null +++ b/src/bin/encrypt_ste_vec_small_v3.rs @@ -0,0 +1,61 @@ +//! v3 sibling of `encrypt_ste_vec_small`: small JSON documents (4 flat +//! fields) into `json_ste_vec_small_encrypted_v3_*` as `public.json` +//! (SteVec document) payloads. +//! +//! SteVecMode::Standard is load-bearing: Standard emits `oc` (CLLW-ORE) +//! per orderable entry, which is one of the two per-entry terms +//! (`hm` XOR `oc`) the `from_v2` SteVec conversion accepts. Compat mode +//! emits `op`, which the v3 document entry shape does not carry. +//! +//! Environment variables: DATABASE_URL, NUM_RECORDS, BATCH_SIZE, +//! TABLE_SUFFIX, V3_CONVERT_ONLY, CS_* credentials. + +use anyhow::Result; +use cipherstash_client::{ + eql::Identifier, + schema::{ + column::{ArrayIndexMode, Index, IndexType, SteVecMode}, + ColumnConfig, ColumnType, + }, +}; +use dbbenches::{v3::TargetDomain, FakeJsonSmall, IngestOptionsBuilder, WrappedJson}; +use std::env; + +#[tokio::main] +async fn main() -> Result<()> { + dbbenches::init_tracing(); + + let num_records: i32 = env::var("NUM_RECORDS") + .unwrap_or_else(|_| "10000".to_string()) + .parse() + .expect("NUM_RECORDS must be a valid integer"); + + let batch_size: usize = env::var("BATCH_SIZE") + .unwrap_or_else(|_| "1000".to_string()) + .parse() + .expect("BATCH_SIZE must be a valid integer"); + + let table_suffix = env::var("TABLE_SUFFIX").unwrap_or_default(); + let table_name = format!("json_ste_vec_small_encrypted_v3{}", table_suffix); + + IngestOptionsBuilder::new("encrypt_ste_vec_small_v3") + .num_records(num_records) + .batch_size(batch_size) + .identifier(Identifier::new(&table_name, "value")) + .column_config( + ColumnConfig::build("value") + .casts_as(ColumnType::Json) + .add_index(Index::new(IndexType::SteVec { + prefix: "value".to_string(), + term_filters: Default::default(), + array_index_mode: ArrayIndexMode::default(), + mode: SteVecMode::Standard, + })), + ) + .convert_to_v3(TargetDomain::parse("json").expect("json is a v3 domain")) + .build()? + .ingest::(FakeJsonSmall) + .await?; + + Ok(()) +} diff --git a/src/bin/encrypt_string_v3.rs b/src/bin/encrypt_string_v3.rs new file mode 100644 index 0000000..db24314 --- /dev/null +++ b/src/bin/encrypt_string_v3.rs @@ -0,0 +1,52 @@ +//! v3 sibling of `encrypt_string`: random English names into +//! `string_encrypted_v3_*` as `public.text_search` payloads. +//! +//! The config adds `Index::new_ore()` on top of v2's unique+match: v3 has no +//! hm+bf domain — `text_search` (the only equality+match domain) also +//! requires the ORE term `ob`, and `from_v2` fails closed on a missing term. +//! v3 string rows are therefore wider than their v2 siblings; the comparison +//! report flags this when reading ingest deltas. +//! +//! Environment variables: DATABASE_URL, NUM_RECORDS, TABLE_SUFFIX, +//! V3_CONVERT_ONLY (encrypt+convert without inserting — used to decompose +//! conversion overhead), CS_CLIENT_ID / CS_CLIENT_KEY / CS_WORKSPACE_CRN. + +use anyhow::Result; +use cipherstash_client::{ + eql::Identifier, + schema::{column::Index, ColumnConfig, ColumnType}, +}; +use dbbenches::{v3::TargetDomain, IngestOptionsBuilder}; +use fake::{faker::name::raw::Name, locales::EN}; +use std::env; + +#[tokio::main] +async fn main() -> Result<()> { + dbbenches::init_tracing(); + + let num_records: i32 = env::var("NUM_RECORDS") + .unwrap_or_else(|_| "10000".to_string()) + .parse() + .expect("NUM_RECORDS must be a valid integer"); + + let table_suffix = env::var("TABLE_SUFFIX").unwrap_or_default(); + let table_name = format!("string_encrypted_v3{}", table_suffix); + + IngestOptionsBuilder::new("encrypt_string_v3") + .num_records(num_records) + .batch_size(1000) + .identifier(Identifier::new(&table_name, "value")) + .column_config( + ColumnConfig::build("value") + .casts_as(ColumnType::Text) + .add_index(Index::new_unique()) + .add_index(Index::new_match()) + .add_index(Index::new_ore()), + ) + .convert_to_v3(TargetDomain::parse("text_search").expect("text_search is a v3 domain")) + .build()? + .ingest::>(Name(EN)) + .await?; + + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs index 50af3e2..15a4525 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,8 @@ impl EqlV2Encrypted { self.data.0 } } +pub mod v3; + use stack_profile::ProfileStore; use std::borrow::Cow; use std::env; @@ -151,6 +153,10 @@ pub struct IngestOptions { pub batch_size: usize, pub identifier: Identifier, pub column_config: ColumnConfig, + /// When set, every storage payload is converted v2→v3 for this target + /// domain (via `eql_bindings::from_v2`) before the INSERT — the v3 + /// ingest path. `None` binds the client's v2 ciphertext as-is. + pub eql_target: Option, } pub struct IngestOptionsBuilder { @@ -159,6 +165,7 @@ pub struct IngestOptionsBuilder { batch_size: Option, identifier: Option, column_config: Option, + eql_target: Option, } impl IngestOptionsBuilder { @@ -172,9 +179,19 @@ impl IngestOptionsBuilder { batch_size: None, identifier: None, column_config: None, + eql_target: None, } } + /// Convert every storage payload v2→v3 for `target` before the INSERT + /// (the v3 ingest path). See [`IngestOptions::eql_target`]. + /// API shape adopted from PR #21 (versioning as configuration on the + /// single ingest pipeline, typed target resolved at the call site). + pub fn convert_to_v3(mut self, target: v3::TargetDomain) -> Self { + self.eql_target = Some(target); + self + } + pub fn num_records(mut self, num_records: i32) -> Self { self.num_records = Some(num_records); self @@ -202,6 +219,7 @@ impl IngestOptionsBuilder { batch_size: self.batch_size.unwrap_or(Self::DEFAULT_BATCH_SIZE), identifier: self.identifier.context("identifier is required")?, column_config: self.column_config.context("column_config is required")?, + eql_target: self.eql_target, }) } } @@ -261,20 +279,60 @@ impl IngestOptions { let out = encrypt_eql(scoped_cipher.clone(), prepared, &Default::default()).await?; - QueryBuilder::new(format!("INSERT INTO {} (value) ", self.identifier.table())) - .push_values(out, |mut b, v| { - // Every PreparedPlaintext above used EqlOperation::Store, so - // encrypt_eql yields only EqlOutput::Store. cipherstash-client - // splits the storage and query payload shapes (since - // 0.34.1-alpha.9) — unwrap the storage ciphertext for binding. - let EqlOutput::Store(ciphertext) = v else { - unreachable!("storage batch must yield EqlOutput::Store"); - }; - b.push_bind(Json(ciphertext)); - }) - .build() - .execute(&pool) - .await?; + match self.eql_target { + // v2 path: bind the client's storage ciphertext as-is. + // Every PreparedPlaintext above used EqlOperation::Store, so + // encrypt_eql yields only EqlOutput::Store. cipherstash-client + // splits the storage and query payload shapes (since + // 0.34.1-alpha.9) — unwrap the storage ciphertext for binding. + None => { + QueryBuilder::new(format!( + "INSERT INTO {} (value) ", + self.identifier.table() + )) + .push_values(out.into_iter(), |mut b, v| { + let EqlOutput::Store(ciphertext) = v else { + unreachable!("storage batch must yield EqlOutput::Store"); + }; + b.push_bind(Json(ciphertext)); + }) + .build() + .execute(&pool) + .await?; + } + // v3 path: convert each storage payload to the target domain + // before binding. The conversion is deliberately inside the + // measured path — v3 ingest cost for the intended consumer IS + // "encrypt + convert + insert". `V3_CONVERT_ONLY=1` skips the + // INSERT so the conversion overhead is attributable when + // comparing against the v2 ingest numbers. + Some(target) => { + let converted = out + .into_iter() + .map(|v| { + let EqlOutput::Store(ciphertext) = v else { + unreachable!("storage batch must yield EqlOutput::Store"); + }; + v3::to_v3_stored_target(&ciphertext, target) + }) + .collect::>>()?; + + if env::var("V3_CONVERT_ONLY").is_ok_and(|v| v == "1") { + continue; + } + + QueryBuilder::new(format!( + "INSERT INTO {} (value) ", + self.identifier.table() + )) + .push_values(converted.into_iter(), |mut b, v| { + b.push_bind(Json(v)); + }) + .build() + .execute(&pool) + .await?; + } + } } let result = json!({ @@ -698,7 +756,19 @@ pub fn write_metadata_file( target_rows: &str, scenarios: Vec, ) -> Result<()> { - let dir = std::path::PathBuf::from("results/query"); + write_metadata_file_in("results/query", prefix, target_rows, scenarios) +} + +/// [`write_metadata_file`] with an explicit output directory — the v3 +/// benches keep their sidecars under `results/query/v3/` so the committed +/// v2 results stay untouched as the regression baseline. +pub fn write_metadata_file_in( + dir: &str, + prefix: &str, + target_rows: &str, + scenarios: Vec, +) -> Result<()> { + let dir = std::path::PathBuf::from(dir); std::fs::create_dir_all(&dir)?; let path = dir.join(format!("{}_metadata_{}.json", prefix, target_rows)); let payload = serde_json::json!({ diff --git a/src/v3.rs b/src/v3.rs new file mode 100644 index 0000000..531c81a --- /dev/null +++ b/src/v3.rs @@ -0,0 +1,289 @@ +//! EQL v3 harness plumbing. +//! +//! The pinned cipherstash-client (0.38.1) emits EQL **v2.3** wire +//! payloads. EQL v3 replaced the single `eql_v2_encrypted` composite with +//! per-capability jsonb DOMAIN types (`public.text_search`, +//! `public.integer_ord`, …), and ships a supported conversion path in the +//! `eql-bindings` crate (`from_v2`) that names these benches as a consumer. +//! Everything v3-specific in the bench harness funnels through this module: +//! +//! * stored payloads: client v2 encrypt → [`to_v3_stored`] → bind as jsonb +//! (every v3 domain CHECK accepts its own converted payload — the +//! converter strict-parses through the domain's binding struct before +//! returning). +//! * query parameters: **also stored-shape**. `from_v2_query` deliberately +//! supports only the SteVec containment needle ([`to_v3_query_json`]); +//! no v3 scalar *query* wire shape exists because every scalar domain +//! CHECK requires the ciphertext `c` that v2 query payloads omit. So +//! scalar needles are encrypted with `EqlOperation::Store` and converted +//! whole ([`encrypt_stored_v3`]). The v3 operator surface is built for +//! this: each domain wires `= / < / …` overloads with `RIGHTARG = jsonb` +//! that cast the bound parameter to the domain. +//! * decryption: v3 rows carry the same record ciphertext `c` the v2 +//! client wrote — [`v3_row_to_v2_ciphertext`] rebuilds a minimal v2 +//! envelope so the pinned client's `decrypt_eql` can decrypt v3 rows +//! (needle sampling, `_decrypt` scenarios). + +use crate::{extract_indexes_used, EqlV2Encrypted}; +use anyhow::{Context, Result}; +use cipherstash_client::{ + encryption::{Plaintext, ScopedCipher}, + eql::{decrypt_eql, encrypt_eql, EqlCiphertext, EqlOperation, EqlOutput, PreparedPlaintext}, + AutoStrategy, +}; +use eql_bindings::from_v2::{from_v2, from_v2_query}; +// Re-exported so ingest binaries can name their conversion target as a +// typed TargetDomain at the builder call site (IngestOptionsBuilder:: +// convert_to_v3) without depending on eql-bindings directly. +pub use eql_bindings::from_v2::TargetDomain; +use serde_json::{json, Value}; +use sqlx::postgres::{PgTypeInfo, PgTypeKind, PgValueRef}; +use sqlx::types::Json; +use std::borrow::Cow; +use std::fmt::Debug; +use std::sync::Arc; + +/// Parse an unqualified v3 domain name (`"text_search"`, `"integer_ord"`, +/// `"json"`, …) with an anyhow-friendly error. +fn parse_target(target: &str) -> Result { + TargetDomain::parse(target) + .with_context(|| format!("unknown v3 target domain `{}`", target)) +} + +/// Convert a STORED v2.3 ciphertext into the v3 payload for `target`. +/// +/// The returned `Value` has already passed `eql-bindings`' strict parse +/// through the target domain's binding struct, so the corresponding domain +/// CHECK is guaranteed to accept it at INSERT/cast time. +pub fn to_v3_stored(v2: &EqlCiphertext, target: &str) -> Result { + to_v3_stored_target(v2, parse_target(target)?) +} + +/// [`to_v3_stored`] with an already-resolved [`TargetDomain`] — the hot-loop +/// form used by the ingest pipeline (`IngestOptionsBuilder::convert_to_v3`), +/// where the target is parsed once at the builder call site. +pub fn to_v3_stored_target(v2: &EqlCiphertext, target: TargetDomain) -> Result { + let v2_value = serde_json::to_value(v2).context("serialize v2 ciphertext")?; + from_v2(&v2_value, target) + .with_context(|| format!("from_v2 conversion to `{:?}` failed", target)) +} + +/// Convert a v2 SteVec QUERY payload into the v3 SteVec containment-needle +/// JSON (the `{"sv":[…]}` shape fed to `eql_v3.jsonb_contains(value, $1)` — +/// alpha.3 dropped the dedicated `jsonb_query` type; the needle is a plain +/// jsonb value). +pub fn to_v3_query_json(v2_query: &Value) -> Result { + from_v2_query(v2_query, TargetDomain::Json) + .context("from_v2_query conversion to `json` failed") +} + +/// Rebuild a minimal v2 envelope from a v3 stored payload so the pinned +/// client's `decrypt_eql` can decrypt it. +/// +/// Scalars carry the record ciphertext at `c`; SteVec documents carry it on +/// the FIRST `sv` entry (`sv[0].c` — the root-selector entry, mirroring +/// upstream `SteVec::into_root_ciphertext`; conversion preserves entry order +/// verbatim so this invariant survives the v2→v3 round trip). +pub fn v3_row_to_v2_ciphertext(v3: &Value) -> Result { + let obj = v3 + .as_object() + .context("v3 payload is not a JSON object")?; + let c = match obj.get("c") { + Some(c) => c.clone(), + None => obj + .get("sv") + .and_then(Value::as_array) + .and_then(|sv| sv.first()) + .and_then(|entry| entry.get("c")) + .cloned() + .context("v3 payload has neither `c` nor `sv[0].c`")?, + }; + let i = obj.get("i").cloned().unwrap_or_else(|| json!({})); + let v2 = json!({ "v": 2, "k": "ct", "i": i, "c": c }); + serde_json::from_value(v2).context("rebuilt v2 envelope did not parse as EqlCiphertext") +} + +/// Encrypt one plaintext with `EqlOperation::Store` and convert to the v3 +/// stored payload for `target`. This is how ALL v3 scalar query needles are +/// produced (see module docs — no scalar query wire shape exists). +pub async fn encrypt_stored_v3( + cipher: Arc>, + column_config: &cipherstash_client::schema::ColumnConfig, + identifier: &cipherstash_client::eql::Identifier, + plaintext: impl Into, + target: &str, +) -> Result<Value> { + let prepared = PreparedPlaintext::new( + Cow::Owned(column_config.clone()), + identifier.clone(), + plaintext.into(), + EqlOperation::Store, + ); + let mut out = encrypt_eql(cipher, vec![prepared], &Default::default()).await?; + let EqlOutput::Store(ciphertext) = out.remove(0) else { + unreachable!("EqlOperation::Store yields EqlOutput::Store"); + }; + to_v3_stored(&ciphertext, target) +} + +/// Decoded `SELECT value` cell from an `eql_v3.*` domain column. +/// +/// v3 domains are DOMAINs over jsonb, so the wire representation is plain +/// jsonb — only the reported type OID differs (Postgres reports the domain's +/// OID in RowDescription). `compatible` therefore accepts jsonb itself plus +/// any domain whose base type is jsonb-compatible. +/// +/// The v2 harness needed `EqlV2Encrypted` to avoid a `value::jsonb` cast +/// being folded into ORDER BY sort keys; v3 has no bare `ORDER BY value` +/// scenario (ordering always goes through an extractor function), but +/// decoding the domain directly keeps the SELECT list identical to v2's. +#[derive(Debug)] +pub struct EqlV3Encrypted(pub Json<Value>); + +impl EqlV3Encrypted { + pub fn into_value(self) -> Value { + self.0 .0 + } +} + +impl sqlx::Type<sqlx::Postgres> for EqlV3Encrypted { + fn type_info() -> PgTypeInfo { + <Json<Value> as sqlx::Type<sqlx::Postgres>>::type_info() + } + + fn compatible(ty: &PgTypeInfo) -> bool { + if <Json<Value> as sqlx::Type<sqlx::Postgres>>::compatible(ty) { + return true; + } + matches!( + ty.kind(), + PgTypeKind::Domain(base) + if <Json<Value> as sqlx::Type<sqlx::Postgres>>::compatible(base) + ) + } +} + +impl<'r> sqlx::Decode<'r, sqlx::Postgres> for EqlV3Encrypted { + fn decode(value: PgValueRef<'r>) -> Result<Self, sqlx::error::BoxDynError> { + let json = <Json<Value> as sqlx::Decode<'r, sqlx::Postgres>>::decode(value)?; + Ok(EqlV3Encrypted(json)) + } +} + +/// Sample a plaintext string from a v3 encrypted table by decrypting the +/// first row — the v3 sibling of [`crate::sample_plaintext_string`]. +pub async fn sample_plaintext_string_v3( + pool: &sqlx::PgPool, + cipher: Arc<ScopedCipher<AutoStrategy>>, + table_name: &str, +) -> Result<String> { + let row: (EqlV3Encrypted,) = + sqlx::query_as(&format!("SELECT value FROM {} LIMIT 1", table_name)) + .fetch_one(pool) + .await + .with_context(|| format!("sample query failed against {}", table_name))?; + + let ciphertext = v3_row_to_v2_ciphertext(&row.0.into_value())?; + let decrypted = decrypt_eql(cipher, vec![ciphertext], &Default::default()) + .await + .context("sample decrypt failed")?; + + let pt = decrypted + .into_iter() + .next() + .ok_or_else(|| anyhow::anyhow!("decrypt_eql returned empty Vec for {}", table_name))?; + match &pt { + Plaintext::Text(Some(s)) => Ok(s.clone()), + other => anyhow::bail!("expected Text sample from {}, got {:?}", table_name, other), + } +} + +/// A bench query against an `eql_v3.*` column: stored-shape jsonb parameter +/// bound at `$1`, mirroring [`crate::EncryptedQuery`]'s surface so the v3 +/// bench files read like their v2 siblings. +pub struct V3EncryptedQuery { + pub param: Value, + pub statement: String, + scoped_cipher: Arc<ScopedCipher<AutoStrategy>>, +} + +impl V3EncryptedQuery { + pub fn new( + param: Value, + statement: impl Into<String>, + scoped_cipher: Arc<ScopedCipher<AutoStrategy>>, + ) -> Self { + Self { + param, + statement: statement.into(), + scoped_cipher, + } + } + + pub async fn execute(&self, pool: &sqlx::PgPool) -> Result<Vec<(i32, EqlV3Encrypted)>> { + let results: Vec<(i32, EqlV3Encrypted)> = sqlx::query_as(&self.statement) + .bind(Json(&self.param)) + .fetch_all(pool) + .await?; + Ok(results) + } + + pub async fn execute_and_decrypt<T>(&self, pool: &sqlx::PgPool) -> Result<Vec<T>> + where + T: TryFrom<Plaintext>, + <T as TryFrom<Plaintext>>::Error: Debug, + { + let results = self.execute(pool).await?; + let ciphertexts = results + .into_iter() + .map(|(_, value)| v3_row_to_v2_ciphertext(&value.into_value())) + .collect::<Result<Vec<_>>>()?; + + let decrypted = decrypt_eql( + Arc::clone(&self.scoped_cipher), + ciphertexts, + &Default::default(), + ) + .await? + .into_iter() + .map(|pt| T::try_from(pt).expect("failed to convert plaintext")) + .collect(); + + Ok(decrypted) + } + + /// `EXPLAIN (FORMAT JSON)` with the parameter bound — same startup + /// metadata capture as the v2 harness. + pub async fn explain(&self, pool: &sqlx::PgPool) -> Result<Value> { + let explain_sql = format!("EXPLAIN (FORMAT JSON) {}", self.statement); + let row: (Json<Value>,) = sqlx::query_as(&explain_sql) + .bind(Json(&self.param)) + .fetch_one(pool) + .await?; + Ok(row.0 .0) + } + + pub fn parameter_json(&self) -> Result<Value> { + Ok(self.param.clone()) + } + + /// Convenience for the startup metadata pass: EXPLAIN + one real + /// execution, returning (explain, indexes_used, rows_returned). + pub async fn capture_metadata( + &self, + pool: &sqlx::PgPool, + ) -> Result<(Value, Vec<String>, u64)> { + let explain = self.explain(pool).await?; + let indexes_used = extract_indexes_used(&explain); + let rows = self.execute(pool).await?.len() as u64; + Ok((explain, indexes_used, rows)) + } +} + + +/// Convert a stored v2 row (as decoded by [`EqlV2Encrypted`]) to the v3 +/// payload — used by cross-version correctness checks that read a v2 table +/// and probe the v3 table with the same logical value. +pub fn v2_row_to_v3_stored(row: EqlV2Encrypted, target: &str) -> Result<Value> { + to_v3_stored(&row.into_ciphertext(), target) +} diff --git a/v3-regressions-report.md b/v3-regressions-report.md new file mode 100644 index 0000000..bf7aa7a --- /dev/null +++ b/v3-regressions-report.md @@ -0,0 +1,460 @@ +# EQL v3 Regression Analysis — Scenario Deep-Dives + +> **UPDATE (2026-07-08): suite pinned to the `eql-3.0.0-alpha.3` release.** +> `mise run setup-db-v3` now installs the released bundle, which moved the +> per-domain types `eql_v3.* → public.*` and inlined the `jsonb_entry` CHECK +> (the fix this doc's `field_eq`/`combo` deep-dives trace — alpha.3's source +> cites `cipherstash/benches#23`). The JSON bench was also rewritten to query +> through the named EQL JSON functions (`eql_v3.jsonb_contains`, +> `eql_v3.jsonb_path_query_first`, …) rather than raw `jsonb` operators, and +> **re-ingested + re-run against alpha.3 at 10k/100k/1M** (results in +> `results/query/v3/json_*`). The non-JSON `eql_v3.*`-typed numbers below are +> still from the pre-release alpha.2-equivalent build and are **pending a full +> re-baseline against alpha.3** (deferred). +> +> **STATUS (2026-07-04): both fixes merged upstream and verified end-to-end.** +> EQL PRs [#357](https://github.com/cipherstash/encrypt-query-language/pull/357) +> (plpgsql opclass helpers, issue #353) and +> [#358](https://github.com/cipherstash/encrypt-query-language/pull/358) +> (inline `jsonb_entry` CHECK + plpgsql `jsonb_query` validator, issue #354) +> are merged to `eql_v3`. The bench DB was patched to the release-tip SQL +> surface (verified object-identical to a fresh tip install) and the affected +> families re-run at all tiers. 1M results: +> +> | Scenario | v2 | v3 pre-fix | v3 now | +> |---|---|---|---| +> | ORE/range_lt_ordered_10 | 0.513 ms | 0.736 ms (+43%) | **0.548 ms (+6.8%)** | +> | COMBO/bloom_ore_order_limit | 16.64 ms | 22.70 ms (+36%) | **14.21 ms (−14.6%)** | +> | JSON/field_eq/functional | 0.106 ms | 0.130 ms (+19%) | **0.109 ms (+3.4%)** | +> | JSON/field_order/functional | 0.357 ms | 0.520 ms (+45%) | **0.272 ms (−23.7%)** | +> +> Flagged regressions across all 96 scenario/tier pairs: 14 → **3** (bloom +> GIN at two tiers — array_ops vs v2's dedicated opclass, small absolute +> deltas — and the ordered scan's residual at 10k only, consistent with the +> stored-shape query needle cost tracked as issue #356 / CIP-3383). The open +> items are the design-level issues: #355 (text domain gap) and #356 +> (k="q" query payloads). +> +> **Final adjudication (same-day v2 re-measurement, 2026-07-04):** the last +> three flags vs the May baseline (eql_cast@10M, both GROUP BY@10M) are +> cross-session drift — the May-measured v2 numbers sit ±8–19% from a +> same-day v2 run at the 10M tier. Against SAME-DAY v2: eql_cast −3.3% +> (v3 faster), top_n GROUP BY −0.7%, low-cardinality GROUP BY +6.4%. +> **v3 is regression-clean vs same-day v2** apart from documented +> semantics-changed items (e.g. eql_hash's hash→btree trade) and +> sub-threshold small-tier deltas tracked by CIP-3383. + +Companion to the auto-generated [`report/V3_COMPARISON.md`](report/V3_COMPARISON.md). +That report flags *what* moved; this document works through flagged scenarios one +at a time — the exact queries both versions ran, what actually differs between +them, and the most likely causes of the delta, with supporting evidence from the +recorded plans and related scenarios. + +Methodology reminders (details in `report/V3_COMPARISON.md`): + +- v2 numbers are the committed EQL 2.3 baseline results; v3 numbers were produced + on the same machine (M1 Max, native PG 17, port 5400) on 2026-07-03/04. +- Every query and bound parameter quoted here comes from the metadata sidecars + the benches write at startup (`results/query/**/*_metadata_*.json`), which + also capture `EXPLAIN (FORMAT JSON)` and the indexes the planner used. +- The v2 tables were truncated after the workspace re-login, so v2 queries can + no longer be re-executed interactively; v2 evidence is the recorded sidecars. + +--- + +## COMBO/combo/bloom_ore_order_limit + +*"Find the 10 youngest customers whose first name matches a pattern"* — bloom +filter + ORE ORDER BY + LIMIT, the composite-predicate shape from §6 of the EQL +query-performance guide. + +### Timings + +| Tier | v2 median | v3 median | Δ | +|---|---|---|---| +| 10k | 0.287 ms | 0.525 ms | +82.8% | +| 100k | 2.083 ms | 2.780 ms | +33.5% | +| 1M | 16.643 ms | 22.703 ms | +36.4% | + +### The queries + +**v2** (`combo_encrypted_<N>`, columns `name`/`age`/`category` all `eql_v2_encrypted`): + +```sql +SELECT id FROM combo_encrypted_1000000 +WHERE name LIKE $1 +ORDER BY eql_v2.ore_block_u64_8_256(age) LIMIT 10 +``` + +Bound parameter: a v2 **query** payload, bloom-only — keys `{v, k, i, bf}`, no +ciphertext. Produced by `EqlOperation::Query` against the match index. + +**v3** (`combo_encrypted_v3_<N>`, `name eql_v3.text_search`, `age eql_v3.integer_ord`): + +```sql +SELECT id FROM combo_encrypted_v3_1000000 +WHERE name @> $1 +ORDER BY eql_v3.ord_term(age) LIMIT 10 +``` + +Bound parameter: a full v3 **stored** payload — keys `{v, i, c, hm, ob, bf}`. +No v3 scalar query wire shape exists (every domain CHECK requires the +ciphertext `c`), so the needle is "Bob" encrypted with `EqlOperation::Store` +and converted via `eql-bindings::from_v2`. + +Both versions engaged their bloom GIN (`..._name_gin_index` / +`..._name_match_gin_index` in `indexes_used`) at every tier, and both returned +10 rows. + +### What changed between the scenarios + +1. **Operator: `LIKE` → `@>`.** EQL v3 removed the `~~` operator; bloom + matching is exposed only as containment. Semantically identical (needle + bloom bits ⊆ value bloom bits), but a different operator entry inlining to + `eql_v3.match_term(name) @> eql_v3.match_term($1::eql_v3.text_search)`, + giving the planner a different expression tree. +2. **Parameter shape: bloom-only query payload → full stored envelope.** The + v3 needle carries a ciphertext and two extra index terms, and the + `::eql_v3.text_search` cast runs the domain CHECK on it in-plan. More bytes + per execution, and the RHS `match_term()` extracts `bf` out of a larger + jsonb. +3. **ORDER BY extractor: `eql_v2.ore_block_u64_8_256(age)` → + `eql_v3.ord_term(age)`.** The v3 term is the `eql_v3_internal.ore_block_256` + composite whose comparisons run through the custom btree operator class with + a **plpgsql comparator** (`compare_ore_block_256_terms`). Every comparison + in the top-10 sort over the bloom-matched rows pays a plpgsql call; the v2 + ORE type's comparison path was cheaper. +4. **Wider `name` rows.** `text_search` requires the ORE term (`ob`), which + v2's unique+match config didn't carry — more heap bytes per row scanned. + +### Likely cause, ranked + +> **Update (validated):** the primary cause turned out to be the LANGUAGE +> sql extraction helpers in the ORE opclass path, not the comparator — see +> the attribution + patch experiments under Issue 3. With a logic-identical +> plpgsql swap of two helper functions, this scenario went from 22.70 ms to +> **13.97 ms at 1M — 16% faster than v2**. The analysis below is preserved +> as the pre-experiment reasoning. + +**Primary suspect: the v3 ORE comparator in the sort (change 3).** The +standalone ordered-scan scenario isolates exactly this code path +(`ORE/ore/range_lt_ordered_10`: index scan whose descent/order comparisons go +through the same opclass), and it shows a stable, size-independent penalty of +the same magnitude: + +| Tier | v2 ORE ordered | v3 ORE ordered | v3 OPE ordered (native bytea btree) | +|---|---|---|---| +| 10k | 0.481 ms | 0.760 ms | 0.118 ms | +| 100k | 0.502 ms | 0.735 ms | 0.119 ms | +| 1M | 0.513 ms | 0.736 ms | 0.118 ms | + +The +33–36% at 100k/1M on this combo scenario tracks the +43–46% on the pure +ordered scan. In the combo shape the sort input is the bloom-matched row set +(a Top-N sort over ~thousands of rows at 1M), so ~N·log(10) plpgsql comparator +calls land directly on the critical path. + +**Secondary: parameter size + domain-cast CHECK (change 2)** — a fixed +per-execution cost, which is why the *relative* delta is largest at 10k +(+82.8%), where the query is fastest and fixed costs weigh most. + +**Minor: wider rows (change 4)** — more heap I/O per bloom-matched row; small +at these tiers. + +The `@>`-vs-`LIKE` operator change itself (change 1) is likely noise: both +inline to the same bloom-containment expression shape and both engaged the GIN. +The standalone match scenarios (`MATCH/match/eql_cast_*`) sit at −6% to +7% at +100k/1M, so the operator swap alone does not explain a +36%. + +### How to confirm / follow up + +- **Isolate the comparator:** add a combo variant ordering by an OPE age column + (`eql_v3.ord_ope_term`). The pure-scan evidence (0.118 ms flat) predicts the + variant would land at or below the v2 number — if so, the regression is + attributable to the ORE opclass, not the combo shape. +- **Upstream fix candidates:** a C-level or SQL-inlinable comparator for + `ore_block_256` in EQL v3, or steering ordered workloads to `_ord_ope` + domains — cipherstash-client 0.38.1 emits the `op` term via `Index::new_ope()` (CIP-3348, adopted 2026-07-04). +- Related finding, same root: the ORE index **build** at 1M took 44 s vs 1 s + for OPE (`results/ingest/index_build_times.jsonl`). + +--- + +## JSON/json/field_eq/functional + +Per-selector functional equality on an encrypted JSON field, via the +extractor recipe. Flagged at +18.9…+20.6% across tiers (e.g. 100k: +0.11 → 0.13 ms). + +### The queries + +**v2** (`json_ste_vec_small_encrypted_<N>`): + +```sql +SELECT id FROM json_ste_vec_small_encrypted_100000 +WHERE eql_v2.eq_term(value -> '<sel>'::text) + = eql_v2.eq_term($1::jsonb::eql_v2.ste_vec_entry) LIMIT 10 +``` + +**v3** (`json_ste_vec_small_encrypted_v3_<N>`): + +```sql +SELECT id FROM json_ste_vec_small_encrypted_v3_100000 +WHERE eql_v3.eq_term(value -> '<sel>'::text) + = eql_v3.eq_term($1::jsonb::eql_v3.jsonb_entry) LIMIT 10 +``` + +Same shape, same needle construction, and — important — **the same index +type in both versions**: a per-selector btree on `eq_term(value -> sel)`, +built at bench startup (the v2 json bench had already moved off hash after +the hash-build derisk work; only `EXACT/eql_hash` changed index type between +versions). Both versions' sidecars show the btree engaged. Index type is +ruled out for this scenario. + +### Attribution (same protocol as the ORE experiments; 100k, 200 warmed runs) + +| | v2 (0.0109 ms/query in-DB) | v3 (0.0286 ms/query in-DB) | +|---|---|---| +| `eq_term` | 0.0055 ms | 0.0058 ms | +| `is_valid_ste_vec_entry_payload` | — | **0.0180 ms (1 call/query)** | + +`eq_term` costs are identical. The entire in-DB delta is one new call per +query: the **`eql_v3.jsonb_entry` domain CHECK** evaluated when the needle +is cast. The absolute delta (+0.018 ms) matches the criterion-level +regression (+0.02 ms) almost exactly. + +### Root cause — third instance of the non-inlinable LANGUAGE sql pattern + +- v2's `ste_vec_entry` domain CHECK is an **inline expression** + (`jsonb_typeof(VALUE) = 'object' AND VALUE ? 's' AND …`) — evaluated + directly by the executor, no function call. +- v3's `jsonb_entry` domain CHECK is + `CHECK (eql_v3_internal.is_valid_ste_vec_entry_payload(VALUE))` — a + LANGUAGE sql function, and domain constraints are another context where + SQL functions **cannot be inlined**, so every cast pays the per-call + SQL-function executor (~18 µs). + +Fix: inline the validation expression directly into the CHECK constraint +(as v2 did, and as the generated scalar domains already do). See issue 4. + +### Related: btree vs hash for `EXACT/eql_hash` (where the index type DID change) + +Direct A/B on `string_encrypted_v3_100000` (create hash on +`eq_term(value)`, drop btree, time, restore): btree 0.0115 ms → hash +0.0076 ms → btree restored 0.0113 ms per lookup. Hash is genuinely ~35% +faster in-DB for the point lookup, but the absolute difference (0.004 ms) +covers only a fraction of that scenario's criterion delta (~0.015–0.02 ms); +the rest is the stored-shape query needle (issue 1). The btree choice remains +correct for build-time reasons (hash builds degrade badly at scale). + +--- + +*Further scenarios to be added as triage continues.* + +--- + +## Issues + +Candidate EQL v3 issues surfaced by this analysis, to be filed in Linear. + +### 1. Add a `k = "q"` query payload variant (no `c` field) for scalar domains + +**Problem:** v3 has no scalar query wire shape. Every scalar domain CHECK +requires the ciphertext key `c`, and the `RIGHTARG = jsonb` operator overloads +cast the bound parameter to the domain — so a query needle must be a full +stored envelope even though `c` plays no part in any comparison. Consequences: + +- Clients must run full encryption (record ciphertext + every required term) + just to build a WHERE-clause parameter; v2 generated only the one term the + predicate needed. +- Every scalar query ships a larger parameter and evaluates the domain CHECK + on it in-plan (e.g. `{v, i, c, hm, ob, bf}` for `text_search` vs v2's + bloom-only `{v, k, i, bf}`). +- `eql-bindings::from_v2_query` deliberately refuses scalar targets + (`UnsupportedQueryTarget`) rather than invent a shape ahead of this design. + +**Proposal (from team discussion 2026-07-03):** add a `k = "q"` payload +variant with no `c` field — either accepted by the existing domains' CHECKs +(`c` required only when `k != "q"`) or as parallel `*_query` domain types the +comparison wrappers accept on the RHS (the pattern `eql_v3.jsonb_query` +already establishes for SteVec needles). `from_v2_query` can then support +scalar targets, and the bench harness's stored-shape query needle workaround +(`src/v3.rs` module docs) goes away. + +**Evidence:** parameter shapes recorded in +`results/query/v3/*_metadata_*.json`; fixed per-execution overhead visible as +the inflated small-tier deltas (e.g. COMBO bloom_ore_order_limit +82.8% at 10k +vs +36.4% at 1M). + +### 2. No hm+bf-only text domain — `text_search` forces the ORE term + +**Problem:** the only v3 text domain with both equality and match capability +(`text_search`) also requires `ob`. A v2 unique+match column migrating to v3 +must start generating ORE terms, capping string ingest at ORE-generation speed: +**9,649 → 1,278 rec/s (−87%)** at the 10k batch size. Rows are also wider. + +**Proposal:** add an hm+bf domain (e.g. `text_eq_match`) to the catalog, or +document the cost as an accepted trade-off of the v3 type system. + +**Evidence:** `report/V3_COMPARISON.md` ingest table; +`results/ingest/v3/encrypt_string_v3_combined.json`. + +### 3. `ore_block_256` opclass path overhead — SQL-language helpers regressed vs v2; whole chain trails OPE + +**Problem (two distinct layers, per the attribution experiment below):** + +- **v2→v3 ordered-scan regression (+43–46%, + `ORE/ore/range_lt_ordered_10`: 0.51 → 0.74 ms):** NOT the comparator — + per-query comparator time is equal across versions. The measured driver is + the term-extraction helpers (`jsonb_array_to_bytea_array`, + `jsonb_array_to_ore_block_256`), rewritten from v2's plpgsql to + LANGUAGE sql in v3: in the opclass call path they cannot inline and pay + the per-call SQL-function executor — 3.5× v2's per-call cost for + identical logic. The stored-shape query needle's domain-cast CHECK (issue 1) + contributes fixed per-query overhead on top. +- **ORE-vs-OPE gap (0.74 vs 0.12 ms; index build 44 s vs 1 s at 1M):** the + comparator+extraction machinery as a whole — ~0.4–0.5 ms of tracked + function self-time per query on either ORE version, vs zero function + calls on the fully-inlined OPE path + (`results/ingest/index_build_times.jsonl`). + +**Proposal:** (a) quick win for the regression — revert the opclass-path +helpers to plpgsql (LANGUAGE sql buys nothing where inlining is impossible) +or cache the decoded bytea representation. **Validated locally**: a +logic-identical language-only swap of the two helpers eliminated the entire +regression (0.32 → 0.19 ms/query, marginally faster than v2 on the same +harness; see the A→B→A experiment in the COMBO section). (b) structural — a +C-level decode+compare for `ore_block_256`, and/or position `_ord_ope` as +the recommended ordering path now that cipherstash-client 0.38.1 emits the `op` term (CIP-3348) +— the OPE benches show 0.118 ms flat at every tier, ~1.2× plaintext. + +**Evidence:** `report/v3/ore_vs_ope_*.png`; ordered-scan table in the COMBO +section above; function-level attribution experiment below. + +### 4. `jsonb_entry` domain CHECK calls a non-inlinable SQL function — and the pattern is systemic + +**Problem:** `eql_v3.jsonb_entry`'s CHECK is +`eql_v3_internal.is_valid_ste_vec_entry_payload(VALUE)` — a LANGUAGE sql +function. Domain constraints cannot inline SQL functions, so every cast to +`jsonb_entry` (e.g. the needle in every `field_eq` query) pays ~18 µs of +SQL-function-executor overhead. Measured: this one call is the ENTIRE +v2→v3 regression on `JSON/json/field_eq/functional` (+19%); v2's +`ste_vec_entry` CHECK was an inline expression and cost nothing +measurable. + +**Proposal:** inline the validation expression directly into the CHECK +constraint (v2's approach; the generated scalar domains already do this). +More broadly: **audit every LANGUAGE sql function reachable from a +non-inlinable context** — domain CHECK constraints, btree operator-class +support paths, and any function invoked from plpgsql — this is the third +confirmed instance of the pattern (with the two `ore_block_256` extraction +helpers of issue 3), and "LANGUAGE sql for inlineability" is v3's global +strategy, so more instances likely exist. + +**Evidence:** attribution tables in the field_eq section of this report; +`pg_get_constraintdef` comparison of `ste_vec_entry` (v2) vs `jsonb_entry` +(v3). + +#### Experiment: function-level attribution (`track_functions`), v2 vs v3 vs OPE + +Protocol: `SET track_functions = 'all'`, warm the query in one session, +`pg_stat_reset()`, run the bench-shaped query 10× in a fresh session, read +`pg_stat_user_functions` (per-query = totals / 10). Query: +`WHERE value < <needle> ORDER BY <extractor>(value) LIMIT 10` against the +1M tables, needle inlined as a literal. The v2 table was repopulated for +this (the v2 SQL surface was still installed; only the data had been +truncated). + +Per-query self-time, grouped: + +| | v2 ORE (median 0.513 ms) | v3 ORE (median 0.736 ms) | v3 OPE (median 0.118 ms) | +|---|---|---|---| +| comparator chain (`compare_*_term*`) | 0.200 ms (15.6 calls) | 0.192 ms (15.7 calls) | — | +| extraction chain (`*_to_bytea_array`, `*ore_block*`, `has_*`) | 0.179 ms (10.1 calls) | 0.264 ms (11.1 calls) | — | +| — of which `jsonb_array_to_bytea_array` | 0.046 ms | **0.160 ms** | — | +| **total tracked** | **≈ 0.40 ms** | **≈ 0.47 ms** | **0 (no calls at all)** | + +Three separate conclusions, one per comparison: + +1. **The comparator does NOT explain the v2→v3 regression.** Per-query + comparator time is equal across versions (0.200 vs 0.192 ms, same call + counts) — consistent with the near-identical plpgsql bodies (v3 only adds + deriving the block count N from the ciphertext length plus a + well-formedness check). +2. **The v3 extraction chain is measurably slower (+0.085 ms/query), led by + `jsonb_array_to_bytea_array` at 3.5× the per-call cost.** The two + implementations have identical logic; the difference is the language: + v2's is **plpgsql**, v3's is **LANGUAGE sql**. In the opclass call path a + SQL function cannot be inlined and goes through the per-call SQL-function + executor, which is substantially slower than a cached plpgsql plan — v3's + inline-everything strategy backfires in the one context where inlining is + impossible. Tracked deltas cover ~0.09 ms of the ~0.22 ms bench delta; + the remainder is untracked per-call fmgr overhead and the needle's + domain-cast CHECK (v3 binds a stored envelope; v2 bound a terms-only + query payload — issue 1). +3. **The comparator+extraction machinery IS why both ORE paths trail OPE.** + The OPE run tracks zero function calls — `ord_ope_term` → `ope_cllw` → + native bytea comparison inlines completely — and it runs at 0.118 ms + flat vs ~0.4–0.5 ms of tracked function time on either ORE path. + +Upstream implications: (a) for the v2→v3 regression specifically, revert the +opclass-path helpers (`jsonb_array_to_bytea_array`, +`jsonb_array_to_ore_block_256`) to plpgsql — LANGUAGE sql buys nothing where +inlining can't happen — or cache the decoded representation; (b) for the +larger ORE-vs-OPE gap, a C-level decode+compare or steering ordered +workloads to `_ord_ope` (client 0.38.1 emits `op`; adopted). + +#### Validation: language-only swap of the helpers (A→B→A) + +To test the hypothesis directly, both helpers were `CREATE OR REPLACE`d +locally with **logic-identical plpgsql** versions (no other change), timed +with a fixed harness (100 warmed executions of the bench-shaped query via a +plpgsql loop, `clock_timestamp()` wall time), then restored: + +| variant | ms/query (harness) | +|---|---| +| v2 ORE (reference) | 0.199–0.209 | +| v3 ORE, shipped LANGUAGE sql helpers | 0.318–0.322 | +| **v3 ORE, plpgsql helpers** | **0.188–0.191** | +| v3 ORE, originals restored | 0.322 | + +The language-only swap **eliminates the entire v2→v3 ordered-scan +regression** — patched v3 is marginally *faster* than v2 on the same +harness. Attribution after the swap: `jsonb_array_to_bytea_array` self-time +0.160 → 0.052 ms/query (v2's plpgsql equivalent: 0.046), comparator +unchanged (0.155 vs 0.152), call counts identical. Restoring the shipped +definitions returned timing to 0.322 ms. + +Conclusion: **confirmed** — the v2→v3 ORE ordered-scan regression is caused +by the opclass-path helper functions being LANGUAGE sql, which cannot inline +when called from the btree support machinery and pay per-call SQL-function +executor overhead. The fix is a two-function language change (or better, +caching/C-level decode). Note the harness numbers exclude client/protocol +overhead, so absolute values sit below the criterion medians (0.513/0.736 +ms); the *gap* is what transfers. + +#### End-to-end validation: real criterion benches with the patch (1M rows) + +Same patch applied, then the actual `bench:v3:query:ore` and +`bench:v3:query:combo` criterion runs (full sqlx/bound-parameter path); +functions and committed result files restored afterwards. + +| Scenario | v2 | v3 shipped | v3 patched | patch effect | +|---|---|---|---|---| +| ORE/range_lt_ordered_10 | 0.513 ms | 0.736 ms | **0.553 ms** | **−24.9%** | +| COMBO/bloom_ore_order_limit | 16.643 ms | 22.703 ms | **13.969 ms** | **−38.5%** | +| ORE/range_{gt,lt}_{10,100} | — | — | — | −4.6…−8.3% | +| COMBO/filtered_group_by (control, no ORE ordering) | 6.396 ms | 5.303 ms | 5.438 ms | +2.6% (noise) | +| COMBO/top_n_filtered_group_by (control) | 5.287 ms | 5.339 ms | 5.342 ms | +0.1% (noise) | + +- The ordered scan lands within 8% of v2 (residual consistent with the + stored-shape query needle, issue 1, and wider payloads). +- **COMBO/bloom_ore_order_limit doesn't just recover — it beats v2 by 16%** + (13.97 vs 16.64 ms): the Top-N sort over the bloom-matched set pays the + extraction chain per compared row, so the helper fix has multiplied + effect there. +- The no-ordering COMBO controls are unmoved (±2.6%), confirming the effect + is specific to the ORE opclass path. + +This also resolves the COMBO scenario's cause ranking (above): the +"comparator in the sort" framing was wrong — the validated driver is the +LANGUAGE sql extraction helpers invoked throughout the ORE ordering path.