MySQL 8.2.0
Source Code Documentation
table_histograms.h
Go to the documentation of this file.
1#ifndef HISTOGRAMS_TABLE_HISTOGRAMS_INCLUDED
2#define HISTOGRAMS_TABLE_HISTOGRAMS_INCLUDED
3
4/* Copyright (c) 2022, Oracle and/or its affiliates.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License, version 2.0,
8 as published by the Free Software Foundation.
9
10 This program is also distributed with certain software (including
11 but not limited to OpenSSL) that is licensed under separate terms,
12 as designated in a particular file or component or in included license
13 documentation. The authors of MySQL hereby grant you an additional
14 permission to link the program and your derivative works with the
15 separately licensed software that they have included with MySQL.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License, version 2.0, for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
25
26#include <array>
27#include <cassert>
28
29#include "map_helpers.h" // mem_root_unordered_map
30#include "my_alloc.h" // MEM_ROOT
31
33#include "sql/psi_memory_key.h"
34
35/*
36The Table_histograms_collection holds a reference-counted collection of
37Table_histograms objects.
38
39Table_histograms_collection memory management
40---------------------------------------------
41
42Each TABLE_SHARE has a pointer to a Table_histograms_collection that is
43allocated on the TABLE_SHARE MEM_ROOT when prepare_share() is called from
44dd_table_share.cc:open_table_def().
45
46The Table_histograms_collection is destroyed (its destructor is invoked) when
47TABLE_SHARE::destroy() is called. The TABLE_SHARE MEM_ROOT also frees its memory
48so the Table_histograms_collection object is also freed.
49
50Table_histograms_collection and its managing of Table_histograms
51----------------------------------------------------------------
52
53The Table_histograms objects in the Table_histograms_collection each represent a
54snapshot of the histograms on a table. The state of this collection is
55manipulated through three methods:
56
57insert(): Inserts a Table_histograms object and marks it current, removing the
58current object if it has a reference count of zero.
59
60acquire(): Returns a pointer to the current Table_histograms object and
61increments its reference count.
62
63release(): Releases a Table_histograms object back by decreasing its reference
64count. Removes the object if it has a reference count of zero and is
65non-current.
66
67A Table_histograms object is inserted into the collection when the TABLE_SHARE
68is first opened (not found in the table definition cache) in
69sql_base.cc:get_table_share(). An updated Table_histograms object is inserted
70following a successful ANALYZE TABLE UPDATE/DROP HISTOGRAM command. This happens
71in sql_admin.cc:update_share_histograms().
72
73TABLE objects acquire() a pointer to a Table_histograms object from the
74Table_histograms_collection when a table is first opened through
75table.cc:open_table_from_share(). This is the only place where acquire() is
76called.
77
78TABLE objects release() the pointer to the Table_histograms object back to the
79Table_histograms_collection when the TABLE is destroyed and freed in
80sql_base.cc:intern_close_table. If an error happens after a Table_histograms
81object has been acquired during open_table_from_share() we also make sure to
82release() it back. Finally histograms are released back in a few code paths that
83perform ad-hoc opening of tables in connection with the REPAIR statement.
84
85Table_histograms_collection concurrency
86---------------------------------------
87
88Because multiple threads can be attempting to insert/acquire/release
89Table_histograms from the Table_histograms_collection on a single TABLE_SHARE we
90require some concurrency control.
91
92In order to protect the Table_histograms_collection from concurrent modification
93we make sure to lock/unlock the LOCK_open mutex around certain operations. The
94mutex protection is performed outside of the object (each object does not have
95its own mutex), and must be seen in the context of the lifetime of the
96TABLE_SHARE.
97
98We do not use mutex protection when setting up or tearing down the TABLE_SHARE
99object, because the appropriate protection should already be in place. For
100example, for the insert() in sql_base.cc:get_table_share() we do not use mutex
101protection since we are in the process of constructing the TABLE_SHARE.
102
103-- insert() in sql_admin.cc:update_share_histograms(): protected by LOCK_open.
104
105-- acquire() in table.cc:open_table_from_share(): protected by LOCK_open.
106
107-- release() in sql_base.cc:intern_close_table(): protected by LOCK_open.
108
109With respect to performance, for the insert() and release() operations we are
110able to re-use existing lock/unlock pairs, but for the acquire() operation we
111take out an additional lock. Since this lock is global and central to a lot of
112server operations, we would have to benchmark to see if it is better to
113introduce a new lock.
114
115Table_histograms memory management
116----------------------------------
117
118Table_histograms objects are allocated on a MEM_ROOT that is a member of the
119object itself. We create a Table_histograms object through the factory method
120Table_histograms::create() which allocates a new Table_histograms object and
121returns a pointer to it. It is the responsibility of the caller to ensure that
122the destructor of this object is invoked which will free its memory.
123
124When we want to insert() a new Table_histograms object in the
125Table_histograms_collection on a TABLE_SHARE we first call
126Table_histograms::create() to create an empty Table_histograms object. Next we
127fill it with histograms by retrieving histograms from the data dictionary and
128calling Table_histograms::insert_histogram() which copies the histogram to the
129MEM_ROOT on the Table_histograms object. Finally we insert() the object into the
130Table_histograms_collection which transfers ownership/lifetime responsibility
131from the calling code to the collection.
132*/
133
134/**
135 The Table_histograms class represents a snapshot of the collection of
136 histograms associated with a table. Table_histograms contains a reference
137 counter to keep track of the number of TABLE objects that point to it.
138
139 Table_histogram objects are created using the static factory method create().
140 The object itself and everything it points to (including its MEM_ROOT) is
141 allocated on its own MEM_ROOT. Table_histogram objects are destroyed/freed by
142 calling destroy() that clears the MEM_ROOT.
143*/
145 public:
146 /**
147 Factory method to create Table_histogram objects. Allocates a
148 Table_histogram object on its own MEM_ROOT and returns a pointer.
149 Should be matched by a call to destroy().
150
151 @param psi_key performance schema instrumentation memory key to track all
152 memory used by the object.
153 @return A pointer to a Table_histograms object if construction was
154 successful, returns nullptr otherwise.
155 */
156 static Table_histograms *create(PSI_memory_key psi_key) noexcept;
157
158 private:
159 Table_histograms() = default;
160
161 public:
167
168 /**
169 Destroys the object and frees memory.
170 */
171 void destroy();
172
173 /**
174 Perform a lookup in the local collection of histograms for a histogram on
175 a given field.
176
177 @param field_index Index of the field to find a histogram for.
178
179 @return Pointer to a histogram or nullptr if no histogram was found.
180 */
181 const histograms::Histogram *find_histogram(unsigned int field_index) const;
182
183 /**
184 Copies the given histogram onto the local MEM_ROOT and inserts the copy
185 into the local collection of histograms.
186
187 @param field_index Index of the field to insert a histogram for.
188 @param histogram Pointer to the histogram to be copied and inserted.
189 @return False if success, true on error.
190 */
191 bool insert_histogram(unsigned int field_index,
192 const histograms::Histogram *histogram);
193
195
196 private:
199 *m_histograms{nullptr};
200
201 // The following members are only intended to be manipulated by the
202 // Table_histograms_collection that the Table_histograms object is inserted
203 // into.
204
205 /// The number of TABLE objects referencing this object.
206 int reference_count() const { return m_reference_counter; }
209 assert(m_reference_counter > 0);
211 }
212
213 /// The index of this object in the Table_histograms_collection.
214 int get_index() const { return m_index; }
215 void set_index(int index) { m_index = index; }
216
218 size_t m_index{0};
219};
220
222/**
223 The Table_histograms_collection manages a collection of reference-counted
224 snapshots of histogram statistics (Table_histograms objects) for a table. It
225 is intended to live on the TABLE_SHARE and provide TABLE objects with
226 reference-counted access to Table_histogram objects through the acquire() and
227 release() methods. The motivation for this class is to decouple the lifetime
228 of histogram statistics from the lifetime of the TABLE_SHARE, so that we
229 avoid having to invalidate the TABLE_SHARE when updating/dropping histograms.
230
231 Multiple threads can be opening/closing tables concurrently. Member functions
232 on the Table_histograms_collection should be protected by holding LOCK_open.
233
234 When the TABLE_SHARE is initialized and whenever the histograms associated
235 with a table are updated, we create a new Table_histograms object, insert it
236 into the collection, and mark it current.
237*/
239 public:
243 delete;
246 delete;
248
249 /**
250 Acquire a pointer to the most recently inserted Table_histograms object.
251 Increments the reference counter on the returned Table_histograms object.
252
253 @return Pointer to the current Table_histograms object or nullptr if none
254 exists.
255 */
256 const Table_histograms *acquire();
257
258 /**
259 Release a previously acquired Table_histograms object, decreasing its
260 reference count. If the reference count of a non-current Table_histograms
261 object reaches zero we delete it. This frees up memory and makes room for a
262 new Table_histograms object in the collection.
263
264 @param histograms Pointer to a Table_histograms object to be released.
265 */
267
268 /**
269 Attempt to insert the supplied Table_histograms object into the collection.
270 The insertion will fail if the collection is full. If the insertion succeeds
271 we mark the object as current and take ownership. The previous current
272 object is deleted if it has a reference count of zero
273
274 @param histograms Pointer to the Table_histograms object to be inserted.
275
276 @return False if the insertion took place, true otherwise.
277 */
279
280 /**
281 Count the total number of TABLE objects referencing Table_histograms objects
282 in the collection. Primarily used for testing.
283
284 @return The sum of Table_histogram reference counters. Zero if the
285 collection is empty.
286 */
287 int total_reference_count() const;
288
289 /**
290 Counts the number of Table_histograms objects in the collection. Primarily
291 used for testing.
292
293 @return The count of non-null pointers to Table_histograms objects in the
294 collection.
295 */
296 size_t size() const;
297
298 private:
299 /**
300 Frees a Table_histograms object from the collection and sets its pointer to
301 nullptr.
302
303 @param idx Index of the Table_histograms object to free.
304 */
305 void free_table_histograms(size_t idx) {
306 m_table_histograms[idx]->destroy();
307 m_table_histograms[idx] = nullptr;
308 }
309
310 std::array<Table_histograms *, kMaxNumberOfTableHistogramsInCollection>
313};
314
315#endif
The Table_histograms_collection manages a collection of reference-counted snapshots of histogram stat...
Definition: table_histograms.h:238
Table_histograms_collection & operator=(Table_histograms_collection &&)=delete
void free_table_histograms(size_t idx)
Frees a Table_histograms object from the collection and sets its pointer to nullptr.
Definition: table_histograms.h:305
size_t size() const
Counts the number of Table_histograms objects in the collection.
Definition: table_histograms.cc:149
std::array< Table_histograms *, kMaxNumberOfTableHistogramsInCollection > m_table_histograms
Definition: table_histograms.h:311
Table_histograms_collection()
Definition: table_histograms.cc:99
int total_reference_count() const
Count the total number of TABLE objects referencing Table_histograms objects in the collection.
Definition: table_histograms.cc:157
const Table_histograms * acquire()
Acquire a pointer to the most recently inserted Table_histograms object.
Definition: table_histograms.cc:112
void release(const Table_histograms *histograms)
Release a previously acquired Table_histograms object, decreasing its reference count.
Definition: table_histograms.cc:120
size_t m_current_index
Definition: table_histograms.h:312
~Table_histograms_collection()
Definition: table_histograms.cc:103
Table_histograms_collection & operator=(const Table_histograms_collection &)=delete
Table_histograms_collection(const Table_histograms_collection &)=delete
bool insert(Table_histograms *histograms)
Attempt to insert the supplied Table_histograms object into the collection.
Definition: table_histograms.cc:131
Table_histograms_collection(Table_histograms_collection &&)=delete
The Table_histograms class represents a snapshot of the collection of histograms associated with a ta...
Definition: table_histograms.h:144
const histograms::Histogram * find_histogram(unsigned int field_index) const
Perform a lookup in the local collection of histograms for a histogram on a given field.
Definition: table_histograms.cc:90
static Table_histograms * create(PSI_memory_key psi_key) noexcept
Factory method to create Table_histogram objects.
Definition: table_histograms.cc:43
void set_index(int index)
Definition: table_histograms.h:215
MEM_ROOT m_mem_root
Definition: table_histograms.h:197
void decrement_reference_counter()
Definition: table_histograms.h:208
~Table_histograms()=delete
Table_histograms & operator=(const Table_histograms &)=delete
Table_histograms(Table_histograms &&)=delete
bool insert_histogram(unsigned int field_index, const histograms::Histogram *histogram)
Copies the given histogram onto the local MEM_ROOT and inserts the copy into the local collection of ...
Definition: table_histograms.cc:75
mem_root_unordered_map< unsigned int, const histograms::Histogram * > * m_histograms
Definition: table_histograms.h:199
int reference_count() const
The number of TABLE objects referencing this object.
Definition: table_histograms.h:206
Table_histograms(const Table_histograms &)=delete
void increment_reference_counter()
Definition: table_histograms.h:207
size_t m_index
Definition: table_histograms.h:218
int m_reference_counter
Definition: table_histograms.h:217
Table_histograms & operator=(Table_histograms &&)=delete
void destroy()
Destroys the object and frees memory.
Definition: table_histograms.cc:63
int get_index() const
The index of this object in the Table_histograms_collection.
Definition: table_histograms.h:214
Table_histograms()=default
Histogram base class.
Definition: histogram.h:291
std::unordered_map, but allocated on a MEM_ROOT.
Definition: map_helpers.h:281
unsigned int PSI_memory_key
Instrumented memory key.
Definition: psi_memory_bits.h:48
Histogram base class.
This file follows Google coding style, except for the name MEM_ROOT (which is kept for historical rea...
Definition: column_statistics.h:33
The MEM_ROOT is a simple arena, where allocations are carved out of larger blocks.
Definition: my_alloc.h:82
constexpr size_t kMaxNumberOfTableHistogramsInCollection
Definition: table_histograms.h:221