summaryrefslogtreecommitdiff
path: root/sql/optimizer_costs.h
blob: 3b2300b901944984b50330dfc69cdac799c2180d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#ifndef OPTIMIZER_COSTS_INCLUDED
#define OPTIMIZER_COSTS_INCLUDED
/*
   Copyright (c) 2022, MariaDB AB

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; version 2 of
   the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335  USA
*/

/*
  This file defines costs structures and cost functions used by the optimizer
*/


/*
  OPTIMIZER_COSTS stores cost variables for each engine. They are stored
  in linked_optimizer_costs (pointed to by handlerton) and TABLE_SHARE.
*/

#define OPTIMIZER_COST_UNDEF -1.0
struct OPTIMIZER_COSTS
{
  double disk_read_cost;
  double index_block_copy_cost;
  double key_cmp_cost;
  double key_copy_cost;
  double key_lookup_cost;
  double key_next_find_cost;
  double disk_read_ratio;
  double row_copy_cost;
  double row_lookup_cost;
  double row_next_find_cost;
  double rowid_cmp_cost;
  double rowid_copy_cost;
  double initialized;   // Set if default or connected with handlerton
};

/* Default optimizer costs */
extern OPTIMIZER_COSTS default_optimizer_costs;
/*
  These are used to avoid taking mutex while creating tmp tables
  These are created once after the server is started so they are
  not dynamic.
*/
extern OPTIMIZER_COSTS heap_optimizer_costs, tmp_table_optimizer_costs;

/*
  Interface to the engine cost variables. See optimizer_defaults.h for
  the default values.
*/

#define DISK_READ_RATIO        costs->disk_read_ratio
#define KEY_LOOKUP_COST        costs->key_lookup_cost
#define ROW_LOOKUP_COST        costs->row_lookup_cost
#define INDEX_BLOCK_COPY_COST  costs->index_block_copy_cost
#define KEY_COPY_COST          costs->key_copy_cost
#define ROW_COPY_COST          costs->row_copy_cost
#define ROW_COPY_COST_THD(THD) default_optimizer_costs.row_copy_cost
#define KEY_NEXT_FIND_COST     costs->key_next_find_cost
#define ROW_NEXT_FIND_COST     costs->row_next_find_cost
#define KEY_COMPARE_COST       costs->key_cmp_cost
#define SORT_INDEX_CMP_COST    default_optimizer_costs.key_cmp_cost
#define DISK_READ_COST         costs->disk_read_cost
#define DISK_READ_COST_THD(thd) default_optimizer_costs.disk_read_cost

/* Cost of comparing two rowids. This is set relative to KEY_COMPARE_COST */
#define ROWID_COMPARE_COST          costs->rowid_cmp_cost
#define ROWID_COMPARE_COST_THD(THD) default_optimizer_costs.rowid_cmp_cost

/* Cost of comparing two rowids. This is set relative to KEY_COPY_COST */
#define ROWID_COPY_COST             costs->rowid_copy_cost

/* Engine unrelated costs. Stored in THD so that the user can change them */
#define WHERE_COST              optimizer_where_cost
#define WHERE_COST_THD(THD)     ((THD)->variables.optimizer_where_cost)
#define TABLE_SCAN_SETUP_COST   optimizer_scan_setup_cost
#define TABLE_SCAN_SETUP_COST_THD(THD) (THD)->variables.optimizer_scan_setup_cost
#define INDEX_SCAN_SETUP_COST   optimizer_scan_setup_cost/2
/* Cost for doing duplicate removal in test_quick_select */
#define DUPLICATE_REMOVAL_COST  default_optimizer_costs.key_copy_cost

/* Default fill factors of an (b-tree) index block is assumed to be 0.75 */
#define INDEX_BLOCK_FILL_FACTOR_DIV 3
#define INDEX_BLOCK_FILL_FACTOR_MUL 4

/*
   These constants impact the cost of QSORT and priority queue sorting,
   scaling the "n * log(n)" operations cost proportionally.
   These factors are < 1.0 to scale down the sorting cost to be comparable
   to 'read a row' = 1.0, (or 0.55 with default caching).
   A factor of 0.1 makes the cost of get_pq_sort_cost(10, 10, false) =0.52
   (Reading 10 rows into a priority queue of 10 elements).

   One consenquence if this factor is too high is that priority_queue will
   not use addon fields (to solve the sort without having to do an extra
   re-read of rows) even if the number of LIMIT is low.
*/
#define QSORT_SORT_SLOWNESS_CORRECTION_FACTOR    (0.1)
#define PQ_SORT_SLOWNESS_CORRECTION_FACTOR       (0.1)

/*
  Creating a record from the join cache is faster than getting a row from
  the engine. JOIN_CACHE_ROW_COPY_COST_FACTOR is the factor used to
  take this into account. This is multiplied with ROW_COPY_COST.
*/
#define JOIN_CACHE_ROW_COPY_COST_FACTOR(thd) 1.0

/*
  cost1 is better that cost2 only if cost1 + COST_EPS < cost2
  The main purpose of this is to ensure we use the first index or plan
  when there are identical plans. Without COST_EPS some plans in the
  test suite would vary depending on floating point calculations done
  in different paths.
*/
#define COST_EPS  0.0000001

#define COST_MAX (DBL_MAX * (1.0 - DBL_EPSILON))

static inline double COST_ADD(double c, double d)
{
  DBUG_ASSERT(c >= 0);
  DBUG_ASSERT(d >= 0);
  return (COST_MAX - (d) > (c) ? (c) + (d) : COST_MAX);
}

static inline double COST_MULT(double c, double f)
{
  DBUG_ASSERT(c >= 0);
  DBUG_ASSERT(f >= 0);
  return (COST_MAX / (f) > (c) ? (c) * (f) : COST_MAX);
}

OPTIMIZER_COSTS *get_optimizer_costs(const LEX_CSTRING *cache_name);
OPTIMIZER_COSTS *create_optimizer_costs(const char *name, size_t length);
OPTIMIZER_COSTS *get_or_create_optimizer_costs(const char *name,
                                               size_t length);
bool create_default_optimizer_costs();
void copy_tmptable_optimizer_costs();
void free_all_optimizer_costs();
struct TABLE;

extern "C"
{
  typedef int (*process_optimizer_costs_t) (const LEX_CSTRING *,
                                            const OPTIMIZER_COSTS *,
                                            TABLE *);
  bool process_optimizer_costs(process_optimizer_costs_t func, TABLE *param);
}


#endif /* OPTIMIZER_COSTS_INCLUDED */