Class: Benedictus::Heuristics::ExpensivePerRowScan
- Defined in:
- lib/benedictus/heuristics/expensive_per_row_scan.rb
Overview
Flags scan nodes whose per-row cost is anomalously high — usually a sign that correlated subplans (or expensive filter functions) are multiplying the work the scan does for every outer row.
A normal Seq Scan tends to cost ~0.05 per row; anything above ~1.0 is almost always doing something extra (a SubPlan running per row, a SECURITY DEFINER UDF in a filter, etc.).
Constant Summary collapse
- DEFAULT_THRESHOLD =
1.0- SCAN_TYPES =
["Seq Scan", "Index Scan", "Index Only Scan", "Bitmap Heap Scan"].freeze
Class Method Summary collapse
Instance Method Summary collapse
- #apply(node) ⇒ Object
-
#initialize(threshold: DEFAULT_THRESHOLD) ⇒ ExpensivePerRowScan
constructor
A new instance of ExpensivePerRowScan.
Methods inherited from Base
Constructor Details
#initialize(threshold: DEFAULT_THRESHOLD) ⇒ ExpensivePerRowScan
Returns a new instance of ExpensivePerRowScan.
20 21 22 23 |
# File 'lib/benedictus/heuristics/expensive_per_row_scan.rb', line 20 def initialize(threshold: DEFAULT_THRESHOLD) super() @threshold = threshold end |
Class Method Details
.config_key ⇒ Object
16 17 18 |
# File 'lib/benedictus/heuristics/expensive_per_row_scan.rb', line 16 def self.config_key :per_row_cost_threshold end |
Instance Method Details
#apply(node) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/benedictus/heuristics/expensive_per_row_scan.rb', line 25 def apply(node) return [] unless SCAN_TYPES.include?(node.node_type) return [] unless node.plan_rows&.positive? return [] unless node.total_cost && node.startup_cost per_row = (node.total_cost - node.startup_cost) / node.plan_rows.to_f return [] if per_row < @threshold subplans = subplan_children(node) [ warning( severity: subplans.any? ? :critical : :warning, code: :expensive_per_row_scan, message: (node, per_row, subplans), suggestion: build_suggestion(subplans) ) ] end |