Philip Oliva
03/30/2026, 8:20 PMRocky
03/30/2026, 8:21 PMpipeline_dop) based on the total number of "drivers" (fragment instances) currently running on a node.
To enable this feature, you should set query_queue_driver_low_water and query_queue_driver_high_water to 0. Setting them to 0 tells StarRocks to automatically calculate sane thresholds based on your hardware.
Here is the breakdown of sane values based on your CPU counts:
Case 1: 94 CPU Cores
* pipeline_dop: Set to 0 (default) for adaptive parallelism.
* max_pipeline_dop: Set to 47 (half of the physical cores). While the default is 64, capping it at half the core count is a standard best practice to prevent a single large query from starving others.
* query_queue_driver_low_water: Set to 0. Internally, this calculates to $94 \times 8 = \mathbf{752}$.
* query_queue_driver_high_water: Set to 0. Internally, this calculates to $94 \times 16 = \mathbf{1504}$.
Case 2: 60 CPU Cores
* pipeline_dop: Set to 0.
* max_pipeline_dop: Set to 30.
* query_queue_driver_low_water: Set to 0. Internally, this calculates to $60 \times 8 = \mathbf{480}$.
* query_queue_driver_high_water: Set to 0. Internally, this calculates to $60 \times 16 = \mathbf{960}$.
How these values work together:
1. Drivers: Each query consists of fragments. The number of "drivers" a query produces on a BE is num_fragments * pipeline_dop.
2. Low Watermark: When the total drivers running on a BE exceed this limit, StarRocks begins to automatically reduce the pipeline_dop for incoming queries to maintain system stability.
3. High Watermark: This is a stricter limit. StarRocks attempts to keep the total driver count below this value. If the load is very high, incoming queries will have their DOP significantly reduced or may be queued if query queues are fully enabled.
Implementation Checklist
To activate these limits, ensure you have the following set:
sql
-- Enable the query queue for SELECT statements
SET GLOBAL enable_query_queue_select = true;
-- Set the watermarks to 0 to use the core-based auto-calculation
SET GLOBAL query_queue_driver_low_water = 0;
SET GLOBAL query_queue_driver_high_water = 0;
-- Cap the maximum parallelism (using the 94 CPU example)
SET GLOBAL max_pipeline_dop = 47;
Recommendation: Start with the 0 (auto-calculated) values. If you notice that CPU utilization remains consistently low even under load, you can manually increase these values (e.g., $10 \times$ cores for low, $20 \times$ cores for high). If the system becomes unresponsive or experiences high scheduling latency, reduce them.
References
• administration/management/resource_management/query_queues.md
• faq/resource_isolation_faq.md
• administration/management/monitor_manage_big_queries.mdPhilip Oliva
03/30/2026, 8:24 PMpipeline_dop: Set to 0 (default) for adaptive parallelism.
* max_pipeline_dop: Set to 47 (half of the physical cores). While the default is 64, capping it at half the core count is a standard best practice to prevent a single large query from starving others.
* query_queue_driver_low_water: Set to 0. Internally, this calculates to $94 \times 8 = \mathbf{752}$.
* query_queue_driver_high_water: Set to 0. Internally, this calculates to $94 \times 16 = \mathbf{1504}$.Rocky
03/30/2026, 8:25 PMquery_queue_concurrency_limit
* Recommended Value: 100
* Reasoning: Even with dynamic parallelism (controlled by your "water" settings), it is a best practice to set a hard "backstop" for the number of concurrent queries. For a 94-core machine, 100 is a standard production-grade limit.
* Setting it to 0 (the default) allows an unlimited number of queries to enter the system. Under extreme spikes, this can lead to massive context switching or memory exhaustion, even if each query is running with low parallelism.
* A limit of 100 ensures that the FE stops sending new queries once the BE is already handling significant concurrent work, placing them in the queue instead.
2. query_queue_cpu_used_permille_limit
* Recommended Value: 900 (representing 90%)
* Reasoning: This is the "CPU trigger" for the query queue.
* By setting it to 900, you tell StarRocks to start queuing new queries as soon as the BE's total CPU usage hits 90%.
* This leaves a 10% headroom for the operating system, background tasks (like compaction and tablet cloning), and the existing running queries to finish without causing the BE to become unresponsive or triggering heartbeat timeouts.
* If you are in a very latency-sensitive environment, you might lower this to 800 (80%), but 900 is the standard recommendation for balancing utilization and stability.
──────────
Summary of your Case 1 Configuration:
Variable | Recommended Value | Note
pipeline_dop | 0 | Adaptive parallelism.
max_pipeline_dop | 47 | Capped at 50% of cores.
query_queue_driver_low_water | 0 | Auto-calculated to 752 ($94 \times 8$).
query_queue_driver_high_water | 0 | Auto-calculated to 1504 ($94 \times 16$).
query_queue_concurrency_limit | 100 | Prevents excessive concurrent query overhead.
query_queue_cpu_used_permille_limit | 900 | Triggers queueing at 90% CPU usage.
Pro Tip: Don't forget to also set query_queue_mem_used_pct_limit to 0.9 (90%). This ensures that queries queue up if memory usage is high, which is often a more frequent cause of BE crashes than CPU saturation.
References
• administration/management/FE_configuration.md
• administration/management/resource_management/query_queues.md
• sql-reference/System_variable.md
• faq/resource_isolation_faq.mdPhilip Oliva
03/30/2026, 9:00 PM0 (auto-calculated) values. If you notice that CPU utilization remains consistently low even under load, you can manually increase these values (e.g., $10 \times$ cores for low, $20 \times$ cores for high). If the system becomes unresponsive or experiences high scheduling latency, reduce them."
I am now seeing low cpu so what did you mean by this?Rocky
03/30/2026, 9:00 PMpipeline_exec_thread_pool_thread_num: The number of threads in the pipeline execution thread pool. (Default: 0, which means it equals the number of CPU cores).
* pipeline_scan_thread_pool_thread_num: The number of threads for scanning data. (Default: 0, which means it equals the number of CPU cores).
* concurrency_limit: The maximum number of concurrent queries allowed (often set within a Resource Group).
2. Why increase them for "Low CPU"?
If your CPU usage is low (e.g., below 50%) but your query latency is high or queries are queuing, it indicates a "thread starvation" or "concurrency bottleneck":
* I/O Wait: If your queries are reading from slow storage (like HDFS or S3) or disks with high latency, threads spend a lot of time waiting. If you only have as many threads as cores (the default), a core sits idle while its single thread waits for data.
* Under-scheduling: By increasing the thread count to $10\times$ or $20\times$ your cores, you allow the operating system to schedule other "ready" threads onto the CPU while some are blocked waiting for I/O. This effectively "saturates" the CPU.
3. What do "Low" and "High" mean here?
In the tuning guide, "low" and "high" refer to the concurrency level or workload intensity:
* Low (e.g., $10 \times$ cores): A conservative starting point for increasing concurrency. For a 16-core machine, you might set the thread pool to 160. Use this if you want to improve throughput but are worried about system stability.
* High (e.g., $20 \times$ cores): A more aggressive setting for very high-concurrency environments (like thousands of small, short-lived queries). For a 16-core machine, this would be 320 threads.
How to adjust them:
You can modify these in your be.conf file and restart the BE, or sometimes via SQL for specific session variables:
* To increase execution threads (BE config):
properties
pipeline_exec_thread_pool_thread_num = 160 # Example for a 16-core BE
* To increase scan threads (BE config):
properties
pipeline_scan_thread_pool_thread_num = 160
* To increase Resource Group concurrency (SQL):
sql
ALTER RESOURCE GROUP your_group_name WITH ('concurrency_limit' = '160');
Warning: As the recommendation notes, if you increase these too high, you might see high scheduling latency (the CPU spends too much time switching between threads) or the system might become unresponsive. Monitor your cpu_util and query_latency closely after making changes!
References
• administration/management/BE_configuration.md
• faq/Others.mdPhilip Oliva
03/30/2026, 9:05 PMpipeline_dop) based on the total number of "drivers" (fragment instances) currently running on a node.
To enable this feature, you should set query_queue_driver_low_water and query_queue_driver_high_water to 0. Setting them to 0 tells StarRocks to automatically calculate sane thresholds based on your hardware.
Here is the breakdown of sane values based on your CPU counts:
Case 1: 94 CPU Cores
* pipeline_dop: Set to 0 (default) for adaptive parallelism.
* max_pipeline_dop: Set to 47 (half of the physical cores). While the default is 64, capping it at half the core count is a standard best practice to prevent a single large query from starving others.
* query_queue_driver_low_water: Set to 0. Internally, this calculates to $94 \times 8 = \mathbf{752}$.
* query_queue_driver_high_water: Set to 0. Internally, this calculates to $94 \times 16 = \mathbf{1504}$.
Case 2: 60 CPU Cores
* pipeline_dop: Set to 0.
* max_pipeline_dop: Set to 30.
* query_queue_driver_low_water: Set to 0. Internally, this calculates to $60 \times 8 = \mathbf{480}$.
* query_queue_driver_high_water: Set to 0. Internally, this calculates to $60 \times 16 = \mathbf{960}$.
How these values work together:
1. Drivers: Each query consists of fragments. The number of "drivers" a query produces on a BE is num_fragments * pipeline_dop.
2. Low Watermark: When the total drivers running on a BE exceed this limit, StarRocks begins to automatically reduce the pipeline_dop for incoming queries to maintain system stability.
3. High Watermark: This is a stricter limit. StarRocks attempts to keep the total driver count below this value. If the load is very high, incoming queries will have their DOP significantly reduced or may be queued if query queues are fully enabled.
Implementation Checklist
To activate these limits, ensure you have the following set:
sql
-- Enable the query queue for SELECT statements
SET GLOBAL enable_query_queue_select = true;
-- Set the watermarks to 0 to use the core-based auto-calculation
SET GLOBAL query_queue_driver_low_water = 0;
SET GLOBAL query_queue_driver_high_water = 0;
-- Cap the maximum parallelism (using the 94 CPU example)
SET GLOBAL max_pipeline_dop = 47;
Recommendation: Start with the 0 (auto-calculated) values. If you notice that CPU utilization remains consistently low even under load, you can manually increase these values (e.g., $10 \times$ cores for low, $20 \times$ cores for high). If the system becomes unresponsive or experiences high scheduling latency, reduce them."
What did you mean by "Start with the 0 (auto-calculated) values. If you notice that CPU utilization remains consistently low even under load, you can manually increase these values (e.g., $10 \times$ cores for low, $20 \times$ cores for high). "???Rocky
03/30/2026, 9:05 PM0, StarRocks uses a built-in heuristic:
* Low Watermark: CPU cores * 8
* High Watermark: CPU cores * 16
A "driver" is a single execution thread for a query fragment. If a query has 4 fragments and a pipeline_dop of 10, it creates 40 drivers on a BE.
The reason the default is 8x/16x is that StarRocks' Pipeline Engine is designed to be highly efficient. Usually, having 8 to 16 times more "tasks" (drivers) than physical cores is the "sweet spot"—it's enough work to keep the CPU busy even if some drivers are briefly waiting for data, but not so much that the system wastes all its time switching between tasks (context switching).
2. What I meant by "Manually Increase if CPU is Low"
In some workloads, your drivers might spend a significant amount of time waiting (e.g., waiting for data from disk/S3 or waiting for network transfers from other nodes) rather than actively calculating.
If your drivers are "light" or IO-bound:
1. The system might hit the High Watermark (e.g., 1,504 drivers on a 94-core machine).
2. Once hit, StarRocks will start "throttling" new queries by forcing them to run with a lower pipeline_dop or making them wait in the queue.
3. The Problem: Because those 1,504 drivers are mostly waiting for IO/Network, your actual CPU utilization might only be at 40% or 50%.
In this specific scenario, your system is "throttling" itself based on the number of drivers, even though you still have plenty of "raw" CPU power left to give.
3. When to use 10x / 20x
If you see your CPU usage is low while queries are being queued or having their DOP reduced, you can increase the "density" of work:
* Increase Low Water to 10x: (e.g., $94 \times 10 = 940$)
* Increase High Water to 20x: (e.g., $94 \times 20 = 1880$)
The Goal: By raising the ceiling, you allow more drivers to run simultaneously. This fills the "gaps" where CPUs were idle, pushing your utilization up (e.g., from 50% to 80%) and increasing the overall throughput of the cluster.
Summary Checklist
* Start with 0: Let the system use the 8x/16x defaults.
* Monitor: Watch top or your dashboard for BE CPU utilization during peak load.
* Action:
* CPU is 90%+: Your watermarks are perfect. Don't touch them.
* CPU is < 60% but queries are queuing: Increase the watermarks to 10x (low) / 20x (high) to let more work in.
* CPU is 100% and system feels "laggy": Your watermarks might be too high (causing context-switching overhead); try reducing them.
References
• administration/management/resource_management/query_queues.md
• faq/resource_isolation_faq.md
• administration/management/monitoring/metrics.md
• sql-reference/System_variable.md
• administration/management/FE_configuration.mdPhilip Oliva
03/30/2026, 9:08 PMRocky
03/30/2026, 9:08 PMquery_queue_driver_low_water to a value of 940, you should set the variable directly to 940.
Here is how the variable works based on the StarRocks documentation:
* If set to 0: StarRocks uses a default multiplier: avg_be_cpu_cores * 8.
* If set to a value greater than 0: The value is used directly as the limit.
* If set to -1 (default): The feature is disabled.
Therefore:
* If you set query_queue_driver_low_water = 940, the low water mark will be exactly 940 drivers.
* If you set query_queue_driver_low_water = 10, the low water mark will be exactly 10 drivers, which is likely much lower than you intended.
There is no setting that allows you to provide a custom multiplier (like 10x cores) directly; you must calculate the desired number of drivers and set that absolute value.
How to set it:
You can set this as a global variable:
sql
SET GLOBAL query_queue_driver_low_water = 940;
Context on Drivers:
In StarRocks, a "driver" represents a concurrent fragment of a query on a single BE. The total number of drivers for a query is num_fragments * pipeline_dop. The query_queue_driver_low_water and query_queue_driver_high_water variables are used to dynamically adjust pipeline_dop for new queries to ensure the system isn't overloaded while maintaining high throughput.
References
• administration/management/resource_management/query_queues.md
• administration/management/monitoring/metrics.mdPhilip Oliva
03/30/2026, 9:19 PMRocky
03/30/2026, 9:20 PMquery_queue_v2_cpu_costs_per_slot is 1000000000 (1 billion).
Key Details:
* Type: Long
* Unit: Planner CPU cost units.
* Description: This parameter defines the CPU cost threshold per slot. When Query Queue V2 is enabled, StarRocks estimates the number of slots a query requires by dividing the query's total planner CPU cost by this value.
* Behavior:
* The result is clamped between 1 and the total available slots.
* Increasing this value reduces the number of slots allocated per query (making queries "cheaper" in terms of slot consumption).
* Decreasing this value increases the number of slots allocated per query (making queries "more expensive").
* Introduced in: v3.3.4, v3.4.0, and v3.5.0.
References
• administration/management/FE_configuration.md
• faq/resource_isolation_faq.md
• sql-reference/System_variable.mdPhilip Oliva
03/30/2026, 9:36 PMquery_queue_driver_low_water = 940 will increase adaptive dop values?Rocky
03/30/2026, 9:36 PMquery_queue_driver_low_water value will generally result in higher adaptive DOP (Degree of Parallelism) values when the cluster is under load.
Here is how the logic works in StarRocks (starting from v3.1.4):
1. The Relationship
StarRocks uses query_queue_driver_low_water as a threshold to decide when to start "throttling" or reducing the parallelism (pipeline_dop) of new incoming queries.
* Below the Low Water Mark: The system tries to give queries a higher pipeline_dop to ensure better performance for individual queries.
* Above the Low Water Mark: As the number of running drivers (tasks) in the cluster increases beyond this value, StarRocks begins to dynamically decrease the pipeline_dop for new queries to prevent the system from becoming overloaded and to ensure more queries can run concurrently without context-switching overhead.
2. Why setting it to 940 increases DOP
By setting query_queue_driver_low_water = 940, you are raising the "ceiling" for high-performance execution:
_ If your previous limit was lower (e.g., the default is often avg_be_cpu_cores _ 8), the system would have started lowering query DOP much sooner.
* With the value at 940, the system will maintain higher pipeline_dop values for more concurrent queries before it starts the adaptive reduction process.
Summary of impact:
* Higher Throughput/Parallelism: Individual queries will maintain a higher DOP even as the system load grows toward that 940 driver mark.
* Resource Trade-off: While this "increases" DOP, be mindful that setting it too high relative to your CPU cores can lead to high CPU contention if too many drivers are fighting for the same physical cores.
Important Note: To make full use of this, ensure pipeline_dop is set to 0 (the default in recent versions), which allows StarRocks to manage the parallelism adaptively. If you hardcode pipeline_dop to a specific non-zero number, this adaptive logic is bypassed.
References
• administration/management/resource_management/query_queues.md
• administration/management/monitoring/metrics.md
• faq/resource_isolation_faq.md
• sql-reference/System_variable.mdPhilip Oliva
03/30/2026, 9:38 PMquery_queue_driver_low_water vs query_queue_driver_high_water ?Rocky
03/30/2026, 9:38 PMquery_queue_driver_low_water and query_queue_driver_high_water are global session variables used to dynamically adjust query concurrency (pipeline_dop) based on the current workload on Backend (BE) nodes.
These variables help optimize resource utilization by preventing the system from being overwhelmed by too many concurrent tasks (drivers) while ensuring that hardware resources are fully used when the load is light.
Key Concepts
* Driver: A "driver" represents the concurrent execution unit of a query fragment on a single BE. The total number of drivers for a query on a BE is calculated as: num_drivers = num_fragments * pipeline_dop.
* Purpose: These settings allow StarRocks to automatically lower the pipeline_dop of incoming queries as the system becomes busier, rather than using a fixed concurrency for every query.
──────────
1. query_queue_driver_low_water
This variable defines the lower threshold for concurrent drivers.
* Function: When the number of currently running drivers on a BE exceeds this "low water" mark, StarRocks starts to gradually reduce the pipeline_dop (degree of parallelism) for new incoming queries. The more the load exceeds this limit, the more aggressively the parallelism is reduced.
* Default: -1 (disabled).
* Setting to 0: If set to 0, it defaults to avg_be_cpu_cores * 8.
* Custom Value: You can set a specific integer to define your own threshold.
2. query_queue_driver_high_water
This variable defines the upper limit (ceiling) for concurrent drivers.
* Function: StarRocks aims to keep the total number of running drivers below this "high water" mark. If the load reaches this level, incoming queries will be significantly throttled in terms of their pipeline_dop to prevent resource exhaustion or excessive scheduling overhead.
* Default: -1 (disabled).
* Setting to 0: If set to 0, it defaults to avg_be_cpu_cores * 16.
* Custom Value: You can set a specific integer to define your own ceiling.
──────────
Summary Table
Variable | Default | Default if set to 0 | Action
query_queue_driver_low_water | -1 | CPU Cores * 8 | Start reducing pipeline_dop for new queries.
query_queue_driver_high_water | -1 | CPU Cores * 16 | Harder limit to restrain the total number of running drivers.
How to use them?
You can enable this dynamic adjustment by setting the variables in your session or globally:
sql
-- Enable dynamic concurrency adjustment
SET GLOBAL query_queue_driver_low_water = 0;
SET GLOBAL query_queue_driver_high_water = 0;
By using these, you ensure that during peak times, queries use fewer resources individually to allow more queries to run, while during quiet times, a single query can scale up to use more CPU cores for faster execution.
References
• administration/management/resource_management/query_queues.md
• administration/management/monitoring/metrics.mdPhilip Oliva
03/30/2026, 9:40 PMRocky
03/30/2026, 9:40 PMPhilip Oliva
03/30/2026, 9:41 PMRocky
03/30/2026, 9:41 PMquery_queue_driver_low_water and query_queue_driver_high_water settings, you are referring to the thresholds used to dynamically manage query concurrency.
Here is the breakdown of how many drivers there are and what controls them:
1. How many drivers are there?
The number of drivers for a single query on a single BE is calculated as:
*`num_drivers = num_fragments * pipeline_dop`*
* num_fragments: The number of query plan fragments assigned to that BE.
* pipeline_dop: The degree of parallelism for the pipeline engine.
The total number of drivers running on a BE is the sum of num_drivers for all currently executing queries on that node.
2. What are the default watermarks?
The "watermarks" define the target range for the total number of drivers on a BE. If you set these variables to 0, StarRocks uses defaults based on your hardware:
* query_queue_driver_low_water: Default is *`avg_be_cpu_cores * 8`*.
* query_queue_driver_high_water: Default is *`avg_be_cpu_cores * 16`*.
_Note: avg_be_cpu_cores is the average number of CPU cores across all BE nodes in your cluster._
3. What is the number of drivers controlled by?
The number of drivers is controlled by StarRocks' dynamic adjustment logic:
* Dynamic Adjustment: When a new query arrives, StarRocks checks the current number of running drivers. If the count exceeds the low water mark, it begins to automatically reduce the pipeline_dop of new queries.
* High Water Limit: StarRocks attempts to keep the total number of running drivers below the high water mark to prevent resource exhaustion and excessive scheduling overhead.
* Queueing: If resources are still too pressured, the query queue will hold incoming queries in a "Pending" state until the driver count drops.
4. Is that a setting?
Yes, these are global session variables that you can configure:
Variable | Default | Description
query_queue_driver_low_water | -1 | The lower limit for concurrent drivers. If set to 0, it defaults to CPU cores * 8.
query_queue_driver_high_water | -1 | The upper limit for concurrent drivers. If set to 0, it defaults to CPU cores * 16.
You can adjust these settings using the SET command:
sql
-- Example: Manually setting the high water mark to 256 drivers
SET GLOBAL query_queue_driver_high_water = 256;
By default, these are set to -1 (disabled). They only take effect when set to 0 (auto-calculate based on cores) or a specific positive integer.
References
• administration/management/resource_management/query_queues.md
• administration/management/monitoring/metrics.mdPhilip Oliva
03/30/2026, 11:30 PMpipeline_dop can only be adaptive when set to 0? If its set to 3 it won't go from 3 to max_pipeline_dop?Rocky
03/30/2026, 11:30 PMpipeline_dop to a specific value greater than 0 (like 3), you are effectively disabling the adaptive parallelism for that session or query. The system will use that fixed value directly and will ignore the max_pipeline_dop setting.
Here is the breakdown of the behavior:
* When pipeline_dop = 0 (Default/Adaptive): The system automatically calculates the degree of parallelism (DOP) based on the number of CPU cores and the query's complexity. In this mode, it uses max_pipeline_dop as an upper bound (default is 64).
* When pipeline_dop > 0 (Fixed): The system uses the value you provided (e.g., 3) as a hard limit for the pipeline instances. It will not scale up to max_pipeline_dop even if resources are available.
Why would you set it manually?
Usually, you only set pipeline_dop to a fixed value (like 1) in high-concurrency scenarios where you want to restrict each individual query from consuming too many resources, ensuring that the system can handle more simultaneous requests.
If you want the system to be flexible and scale between 1 and a specific maximum, you should leave pipeline_dop at 0 and adjust max_pipeline_dop instead.
References
• sql-reference/System_variable.md
• knowledge/usage/best-practice.md
• faq/resource_isolation_faq.md
• administration/management/BE_configuration.md