mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-10-12 06:52:34 +00:00
fix: pass through native DataFusion optimizer options
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
This commit is contained in:
@@ -7,9 +7,9 @@ Query options adjust selected behavior for a connection or request; they are not
|
||||
| `query.parallelism` | `query_parallelism`, `query.parallelism` | Integer `1`–`1024`; server default `0` means automatic CPU-based parallelism. This is not a resource-pool limit. |
|
||||
| `query.allow_query_fallback` | `query_fallback`, `allow_query_fallback`, `query.allow_query_fallback` (legacy `ALLOW_QUERY_FALLBACK` syntax / `query_fallback` hint also work) | `true` or `false` |
|
||||
| `query.enable_remote_dynamic_filter_pushdown` | canonical name | `true` or `false` |
|
||||
| `datafusion.optimizer.*` | canonical name | Boolean; only `repartition_joins`, `repartition_aggregations`, `repartition_sorts`, `repartition_windows`, `enable_round_robin_repartition`, `prefer_existing_sort`, `prefer_hash_join`, `join_reordering`, `enable_topk_aggregation`, and `enable_dynamic_filter_pushdown` are supported. |
|
||||
| `datafusion.optimizer.*` | canonical name | Keys, types, defaults, and validation come from the linked DataFusion version (for example, numeric `max_passes` and Boolean `filter_null_join_keys`). |
|
||||
|
||||
Use `SET query_parallelism = 4` or `SET query.parallelism TO 4`; `SHOW VARIABLES query.parallelism` works in MySQL and PostgreSQL, which also accepts `SHOW query.parallelism`. `SHOW VARIABLES <option>` reports the effective value. Unspecified options inherit engine settings; defaults are automatic parallelism, fallback `false`, remote dynamic-filter pushdown `true`, and DataFusion optimizer switches `true` except `prefer_existing_sort` (`false`). DataFusion options are an inline Boolean allowlist applied through existing `ConfigOptions`, not arbitrary DataFusion configuration. Invalid values for recognized options and unsupported names are errors; unknown third-party MySQL/PostgreSQL initialization settings retain existing tolerance.
|
||||
Use `SET query_parallelism = 4` or `SET query.parallelism TO 4`; `SHOW VARIABLES query.parallelism` works in MySQL and PostgreSQL, which also accepts `SHOW query.parallelism`. `SHOW VARIABLES <option>` reports the effective value. Unspecified options inherit engine settings; defaults are automatic parallelism, fallback `false`, and remote dynamic-filter pushdown `true`. Invalid values and unsupported names are errors; unknown third-party MySQL/PostgreSQL initialization settings retain existing tolerance.
|
||||
|
||||
HTTP `X-Greptime-Hints` (for example, `query.parallelism=4`) and gRPC `x-greptime-hints` request metadata set request options; gRPC hints are not a protobuf `Hints` field. The Rust Flight client offers `Database::sql_with_hint` and `flight_request().with_hints`. Hints override session `SET`, including within a multi-statement HTTP request. SQL `SET` lasts for its connection only; `SET LOCAL` transaction-scoped restoration is not implemented.
|
||||
|
||||
|
||||
@@ -324,7 +324,13 @@ impl QueryEngineState {
|
||||
.build()
|
||||
})?);
|
||||
let options = query_ctx.extensions();
|
||||
for (key, value) in &options {
|
||||
const MASTER: &str = "datafusion.optimizer.enable_dynamic_filter_pushdown";
|
||||
// The master switch cascades to children, so apply explicit child overrides afterward.
|
||||
for (key, value) in options
|
||||
.get_key_value(MASTER)
|
||||
.into_iter()
|
||||
.chain(options.iter().filter(|(key, _)| key.as_str() != MASTER))
|
||||
{
|
||||
if key.starts_with("datafusion.") {
|
||||
state
|
||||
.config_mut()
|
||||
|
||||
@@ -865,7 +865,7 @@ pub fn show_query_option(
|
||||
return Ok(None);
|
||||
};
|
||||
let context = engine.engine_context(query_ctx.clone())?;
|
||||
let value = match canonical {
|
||||
let value = match canonical.as_str() {
|
||||
"query.allow_query_fallback" => context
|
||||
.state()
|
||||
.config_options()
|
||||
|
||||
@@ -14,37 +14,22 @@
|
||||
|
||||
use crate::session_config::{Error, InvalidConfigValueSnafu};
|
||||
|
||||
/// Returns the canonical name for a supported option key.
|
||||
pub fn canonical_query_option_name(key: &str) -> Option<&'static str> {
|
||||
/// Returns a canonical query option alias or a DataFusion optimizer option name.
|
||||
pub fn canonical_query_option_name(key: &str) -> Option<String> {
|
||||
let key = key.to_ascii_lowercase();
|
||||
match key.as_str() {
|
||||
"query_parallelism" | "query.parallelism" => Some("query.parallelism"),
|
||||
"query_parallelism" | "query.parallelism" => Some("query.parallelism".to_string()),
|
||||
"query_fallback" | "allow_query_fallback" | "query.allow_query_fallback" => {
|
||||
Some("query.allow_query_fallback")
|
||||
Some("query.allow_query_fallback".to_string())
|
||||
}
|
||||
"query.enable_remote_dynamic_filter_pushdown" => {
|
||||
Some("query.enable_remote_dynamic_filter_pushdown")
|
||||
Some("query.enable_remote_dynamic_filter_pushdown".to_string())
|
||||
}
|
||||
_ => DATAFUSION_OPTIONS
|
||||
.iter()
|
||||
.find(|name| **name == key)
|
||||
.copied(),
|
||||
_ if key.starts_with("datafusion.optimizer.") => Some(key),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
const DATAFUSION_OPTIONS: &[&str] = &[
|
||||
"datafusion.optimizer.repartition_joins",
|
||||
"datafusion.optimizer.repartition_aggregations",
|
||||
"datafusion.optimizer.repartition_sorts",
|
||||
"datafusion.optimizer.repartition_windows",
|
||||
"datafusion.optimizer.enable_round_robin_repartition",
|
||||
"datafusion.optimizer.prefer_existing_sort",
|
||||
"datafusion.optimizer.prefer_hash_join",
|
||||
"datafusion.optimizer.join_reordering",
|
||||
"datafusion.optimizer.enable_topk_aggregation",
|
||||
"datafusion.optimizer.enable_dynamic_filter_pushdown",
|
||||
];
|
||||
|
||||
/// Validate a query option, returning its canonical name and normalized value.
|
||||
pub fn parse_query_option(key: &str, value: &str) -> Result<Option<(String, String)>, Error> {
|
||||
let key_lower = key.to_ascii_lowercase();
|
||||
@@ -87,9 +72,15 @@ pub fn parse_query_option(key: &str, value: &str) -> Result<Option<(String, Stri
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let normalized = value.to_ascii_lowercase();
|
||||
let mut options = datafusion_common::config::ConfigOptions::default();
|
||||
if let Err(error) = options.set(canonical, &normalized) {
|
||||
let set_result = options.set(&canonical, value).or_else(|error| {
|
||||
if value.eq_ignore_ascii_case("true") || value.eq_ignore_ascii_case("false") {
|
||||
options.set(&canonical, &value.to_ascii_lowercase())
|
||||
} else {
|
||||
Err(error)
|
||||
}
|
||||
});
|
||||
if let Err(error) = set_result {
|
||||
return InvalidConfigValueSnafu {
|
||||
name: key,
|
||||
value,
|
||||
@@ -97,7 +88,22 @@ pub fn parse_query_option(key: &str, value: &str) -> Result<Option<(String, Stri
|
||||
}
|
||||
.fail();
|
||||
}
|
||||
normalized
|
||||
match options
|
||||
.entries()
|
||||
.into_iter()
|
||||
.find(|entry| entry.key == canonical)
|
||||
.and_then(|entry| entry.value)
|
||||
{
|
||||
Some(value) => value,
|
||||
None => {
|
||||
return InvalidConfigValueSnafu {
|
||||
name: key,
|
||||
value,
|
||||
hint: "No matching DataFusion configuration entry",
|
||||
}
|
||||
.fail();
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(Some((canonical.to_string(), normalized)))
|
||||
Ok(Some((canonical, normalized)))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user