MySQL 8.4.2
Source Code Documentation
|
#include <hash_join_iterator.h>
Public Member Functions | |
HashJoinIterator (THD *thd, unique_ptr_destroy_only< RowIterator > build_input, const Prealloced_array< TABLE *, 4 > &build_input_tables, double estimated_build_rows, unique_ptr_destroy_only< RowIterator > probe_input, const Prealloced_array< TABLE *, 4 > &probe_input_tables, bool store_rowids, table_map tables_to_get_rowid_for, size_t max_memory_available, const std::vector< HashJoinCondition > &join_conditions, bool allow_spill_to_disk, JoinType join_type, const Mem_root_array< Item * > &extra_conditions, HashJoinInput first_input, bool probe_input_batch_mode, uint64_t *hash_table_generation) | |
Construct a HashJoinIterator. More... | |
bool | Init () override |
Initialize or reinitialize the iterator. More... | |
int | Read () override |
Read a single row. More... | |
void | SetNullRowFlag (bool is_null_row) override |
Mark the current row buffer as containing a NULL row or not, so that if you read from it and the flag is true, you'll get only NULLs no matter what is actually in the buffer (typically some old leftover row). More... | |
void | EndPSIBatchModeIfStarted () override |
Ends performance schema batch mode, if started. More... | |
void | UnlockRow () override |
int | ChunkCount () |
Public Member Functions inherited from RowIterator | |
RowIterator (THD *thd) | |
virtual | ~RowIterator ()=default |
RowIterator (const RowIterator &)=delete | |
RowIterator (RowIterator &&)=default | |
virtual const IteratorProfiler * | GetProfiler () const |
Get profiling data for this iterator (for 'EXPLAIN ANALYZE'). More... | |
virtual void | SetOverrideProfiler ([[maybe_unused]] const IteratorProfiler *profiler) |
virtual void | StartPSIBatchMode () |
Start performance schema batch mode, if supported (otherwise ignored). More... | |
virtual RowIterator * | real_iterator () |
If this iterator is wrapping a different iterator (e.g. More... | |
virtual const RowIterator * | real_iterator () const |
Static Public Attributes | |
static constexpr uint32_t | kChunkPartitioningHashSeed {899339} |
static constexpr size_t | kMaxChunks = 128 |
Private Types | |
enum class | State { READING_ROW_FROM_PROBE_ITERATOR , READING_ROW_FROM_PROBE_CHUNK_FILE , READING_ROW_FROM_PROBE_ROW_SAVING_FILE , LOADING_NEXT_CHUNK_PAIR , READING_FIRST_ROW_FROM_HASH_TABLE , READING_FROM_HASH_TABLE , END_OF_ROWS } |
enum class | HashJoinType { IN_MEMORY , SPILL_TO_DISK , IN_MEMORY_WITH_HASH_TABLE_REFILL } |
Private Member Functions | |
bool | BuildHashTable () |
Read all rows from the build input and store the rows into the in-memory hash table. More... | |
bool | ReadNextHashJoinChunk () |
Read all rows from the next chunk file into the in-memory hash table. More... | |
bool | ReadRowFromProbeIterator () |
Read a single row from the probe iterator input into the tables' record buffers. More... | |
bool | ReadRowFromProbeChunkFile () |
Read a single row from the current probe chunk file into the tables' record buffers. More... | |
bool | ReadRowFromProbeRowSavingFile () |
Read a single row from the probe row saving file into the tables' record buffers. More... | |
void | LookupProbeRowInHashTable () |
int | ReadJoinedRow () |
Take the next matching row from the hash table, and put the row into the build tables' record buffers. More... | |
bool | on_disk_hash_join () const |
bool | WriteProbeRowToDiskIfApplicable () |
Write the last row read from the probe input out to chunk files on disk, if applicable. More... | |
bool | JoinedRowPassesExtraConditions () const |
bool | RejectDuplicateKeys () const |
If true, reject duplicate keys in the hash table. More... | |
bool | InitRowBuffer () |
Clear the row buffer and reset all iterators pointing to it. More... | |
bool | InitProbeIterator () |
Prepare to read the probe iterator from the beginning, and enable batch mode if applicable. More... | |
bool | InitWritingToProbeRowSavingFile () |
Mark that probe row saving is enabled, and prepare the probe row saving file for writing. More... | |
bool | InitReadingFromProbeRowSavingFile () |
Mark that we should read from the probe row saving file. More... | |
void | SetReadingProbeRowState () |
Set the iterator state to the correct READING_ROW_FROM_PROBE_*-state. More... | |
int | ReadNextJoinedRowFromHashTable () |
Read a joined row from the hash table, and see if it passes any extra conditions. More... | |
bool | ReadFirstProbeRow () |
Helper function for Init(). More... | |
bool | InitHashTable () |
Helper function for Init(). More... | |
Additional Inherited Members | |
Protected Member Functions inherited from RowIterator | |
THD * | thd () const |
|
strongprivate |
|
strongprivate |
HashJoinIterator::HashJoinIterator | ( | THD * | thd, |
unique_ptr_destroy_only< RowIterator > | build_input, | ||
const Prealloced_array< TABLE *, 4 > & | build_input_tables, | ||
double | estimated_build_rows, | ||
unique_ptr_destroy_only< RowIterator > | probe_input, | ||
const Prealloced_array< TABLE *, 4 > & | probe_input_tables, | ||
bool | store_rowids, | ||
table_map | tables_to_get_rowid_for, | ||
size_t | max_memory_available, | ||
const std::vector< HashJoinCondition > & | join_conditions, | ||
bool | allow_spill_to_disk, | ||
JoinType | join_type, | ||
const Mem_root_array< Item * > & | extra_conditions, | ||
HashJoinInput | first_input, | ||
bool | probe_input_batch_mode, | ||
uint64_t * | hash_table_generation | ||
) |
Construct a HashJoinIterator.
thd | the thread handle |
build_input | the iterator for the build input |
build_input_tables | a list of all the tables in the build input. The tables are needed for two things: 1) Accessing the columns when creating the join key during creation of the hash table, 2) and accessing the column data when creating the row to be stored in the hash table and/or the chunk file on disk. |
estimated_build_rows | How many rows we assume there will be when reading the build input. This is used to choose how many chunks we break it into on disk. |
probe_input | the iterator for the probe input |
probe_input_tables | the probe input tables. Needed for the same reasons as build_input_tables. |
store_rowids | whether we need to make sure row ids are available for all tables below us, after Read() has been called. used only if we are below a weedout operation. |
tables_to_get_rowid_for | a map of which tables we need to call position() for ourselves. tables that are in build_input_tables but not in this map, are expected to be handled by some other iterator. tables that are in this map but not in build_input_tables will be ignored. |
max_memory_available | the amount of memory available, in bytes, for this hash join iterator. This can be user-controlled by setting the system variable join_buffer_size. |
join_conditions | a list of all the join conditions between the two inputs |
allow_spill_to_disk | whether the hash join can spill to disk. This is set to false in some cases where we have a LIMIT in the query |
join_type | The join type. |
extra_conditions | A list of extra conditions that the iterator will evaluate after a lookup in the hash table is done, but before the row is returned. The conditions are AND-ed together into a single Item. |
first_input | The first input (build or probe) to read from. (If this is empty, we will not have to read from the other.) |
probe_input_batch_mode | Whether we need to enable batch mode on the probe input table. Only make sense if it is a single table, and we are not on the outer side of any nested loop join. |
hash_table_generation | If this is non-nullptr, it is a counter of how many times the query block the iterator is a part of has been asked to clear hash tables, since outer references may have changed value. It is used to know when we need to drop our hash table; when the value changes, we need to drop it. If it is nullptr, we always drop it on Init(). |
|
private |
Read all rows from the build input and store the rows into the in-memory hash table.
If the hash table goes full, the rest of the rows are written out to chunk files on disk. See the class comment for more details.
true | in case of error |
|
inline |
|
inlineoverridevirtual |
Ends performance schema batch mode, if started.
It's always safe to call this.
Iterators that have children (composite iterators) must forward the EndPSIBatchModeIfStarted() call to every iterator they could conceivably have called StartPSIBatchMode() on. This ensures that after such a call to on the root iterator, all handlers are out of batch mode.
Reimplemented from RowIterator.
|
overridevirtual |
Initialize or reinitialize the iterator.
You must always call Init() before trying a Read() (but Init() does not imply Read()).
You can call Init() multiple times; subsequent calls will rewind the iterator (or reposition it, depending on whether the iterator takes in e.g. a Index_lookup) and allow you to read the records anew.
Implements RowIterator.
|
private |
Helper function for Init().
Build the hash table and check for empty query results (empty build input or non-empty build input in case of degenerate antijoin.)
|
private |
Prepare to read the probe iterator from the beginning, and enable batch mode if applicable.
The iterator state will remain unchanged.
true | in case of error. my_error has been called. |
|
private |
Mark that we should read from the probe row saving file.
The probe row saving file is rewinded to the beginning.
true | in case of error. my_error has been called. |
|
private |
Clear the row buffer and reset all iterators pointing to it.
This may be called multiple times to re-init the row buffer.
true | in case of error. my_error has been called |
|
private |
Mark that probe row saving is enabled, and prepare the probe row saving file for writing.
true | in case of error. my_error has been called. |
|
private |
true | if the last joined row passes all of the extra conditions. |
|
private |
|
inlineprivate |
|
overridevirtual |
Read a single row.
The row data is not actually returned from the function; it is put in the table's (or tables', in case of a join) record buffer, ie., table->records[0].
0 | OK |
-1 | End of records |
1 | Error |
Implements RowIterator.
|
private |
Helper function for Init().
Read the first row from m_probe_input.
|
private |
Take the next matching row from the hash table, and put the row into the build tables' record buffers.
The function expects that LookupProbeRowInHashTable() has been called up-front. The user must call ReadJoinedRow() as long as it returns false, as there may be multiple matching rows from the hash table. It is up to the caller to set a new state in case of EOF.
0 | if a match was found and the row is put in the build tables' record buffers |
-1 | if there are no more matching rows in the hash table |
|
private |
Read all rows from the next chunk file into the in-memory hash table.
See the class comment for details.
true | in case of error |
|
private |
Read a joined row from the hash table, and see if it passes any extra conditions.
The last probe row read will also be written do disk if needed (see WriteProbeRowToDiskIfApplicable).
-1 | There are no more matching rows in the hash table. |
0 | A joined row is ready. |
1 | An error occurred. |
|
private |
Read a single row from the current probe chunk file into the tables' record buffers.
The end conditions are the same as for ReadRowFromProbeIterator().
true | in case of error |
|
private |
Read a single row from the probe iterator input into the tables' record buffers.
If we have started spilling to disk, the row is written out to a chunk file on disk as well.
The end condition is that either: a) a row is ready in the tables' record buffers, and the state will be set to READING_FIRST_ROW_FROM_HASH_TABLE. b) There are no more rows to process from the probe input, so the iterator state will be LOADING_NEXT_CHUNK_PAIR.
true | in case of error |
|
private |
Read a single row from the probe row saving file into the tables' record buffers.
true | in case of error |
|
inlineprivate |
If true, reject duplicate keys in the hash table.
Semijoins/antijoins are only interested in the first matching row from the hash table, so we can avoid storing duplicate keys in order to save some memory. However, this cannot be applied if we have any "extra" conditions: the first matching row in the hash table may fail the extra condition(s).
true | if we can reject duplicate keys in the hash table. |
|
inlineoverridevirtual |
Mark the current row buffer as containing a NULL row or not, so that if you read from it and the flag is true, you'll get only NULLs no matter what is actually in the buffer (typically some old leftover row).
This is used for outer joins, when an iterator hasn't produced any rows and we need to produce a NULL-complemented row. Init() or Read() won't necessarily reset this flag, so if you ever set is to true, make sure to also set it to false when needed.
Note that this can be called without Init() having been called first. For example, NestedLoopIterator can hit EOF immediately on the outer iterator, which means the inner iterator doesn't get an Init() call, but will still forward SetNullRowFlag to both inner and outer iterators.
TODO: We shouldn't need this. See the comments on AggregateIterator for a bit more discussion on abstracting out a row interface.
Implements RowIterator.
|
private |
Set the iterator state to the correct READING_ROW_FROM_PROBE_*-state.
Which state we end up in depends on which hash join type we are executing (in-memory, on-disk or in-memory with hash table refill).
|
inlineoverridevirtual |
Implements RowIterator.
|
private |
Write the last row read from the probe input out to chunk files on disk, if applicable.
For inner joins, we must write all probe rows to chunk files, since we need to match the row against rows from the build input that are written out to chunk files. For semijoin, we can only write probe rows that do not match any of the rows in the hash table. Writing a probe row with a matching row in the hash table could cause the row to be returned multiple times.
true | in case of errors. |
|
staticconstexpr |
|
staticconstexpr |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
The first input (build or probe) to read from.
(If this is empty, we will not have to read from the other.)
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
If true, a row was already read from the probe input, in order to check if that input was empty.
If so, we should process that row before reading another.
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |