You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-08-01 06:46:55 +03:00
feat(optimizer): moved related code into a separate unit
This commit is contained in:
@ -40,6 +40,7 @@ set(libcalmysql_SRCS
|
|||||||
is_columnstore_files.cpp
|
is_columnstore_files.cpp
|
||||||
is_columnstore_extents.cpp
|
is_columnstore_extents.cpp
|
||||||
columnstore_dataload.cpp
|
columnstore_dataload.cpp
|
||||||
|
rulebased_optimizer.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set_source_files_properties(ha_mcs.cpp PROPERTIES COMPILE_FLAGS "-fno-implicit-templates")
|
set_source_files_properties(ha_mcs.cpp PROPERTIES COMPILE_FLAGS "-fno-implicit-templates")
|
||||||
|
@ -78,6 +78,7 @@ using namespace cal_impl_if;
|
|||||||
#include "predicateoperator.h"
|
#include "predicateoperator.h"
|
||||||
#include "rewrites.h"
|
#include "rewrites.h"
|
||||||
#include "rowcolumn.h"
|
#include "rowcolumn.h"
|
||||||
|
#include "rulebased_optimizer.h"
|
||||||
#include "selectfilter.h"
|
#include "selectfilter.h"
|
||||||
#include "simplecolumn_decimal.h"
|
#include "simplecolumn_decimal.h"
|
||||||
#include "simplecolumn_int.h"
|
#include "simplecolumn_int.h"
|
||||||
@ -9206,162 +9207,6 @@ int cs_get_derived_plan(ha_columnstore_derived_handler* handler, THD* /*thd*/, S
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tableIsInUnion(const execplan::CalpontSystemCatalog::TableAliasName& table, CalpontSelectExecutionPlan& csep)
|
|
||||||
{
|
|
||||||
return std::any_of(csep.unionVec().begin(), csep.unionVec().end(),
|
|
||||||
[&table](const auto& unionUnit) {
|
|
||||||
execplan::CalpontSelectExecutionPlan* unionUnitLocal = dynamic_cast<execplan::CalpontSelectExecutionPlan*>(unionUnit.get());
|
|
||||||
bool tableIsPresented = std::any_of(unionUnitLocal->tableList().begin(), unionUnitLocal->tableList().end(),
|
|
||||||
[&table](const auto& unionTable) {
|
|
||||||
return unionTable == table;
|
|
||||||
});
|
|
||||||
return tableIsPresented;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool matchParallelCES(CalpontSelectExecutionPlan& csep)
|
|
||||||
{
|
|
||||||
auto tables = csep.tableList();
|
|
||||||
// This is leaf and there are no other tables at this level.
|
|
||||||
// WIP filter out CSEPs with orderBy, groupBy, having
|
|
||||||
// WIP filter out CSEPs with nonSimpleColumns in projection
|
|
||||||
return tables.size() == 1 && !tables[0].isColumnstore() && !tableIsInUnion(tables[0], csep);
|
|
||||||
}
|
|
||||||
|
|
||||||
CalpontSelectExecutionPlan::SelectList makeUnionFromTable(const size_t numberOfLegs,
|
|
||||||
CalpontSelectExecutionPlan& csep)
|
|
||||||
{
|
|
||||||
CalpontSelectExecutionPlan::SelectList unionVec;
|
|
||||||
unionVec.reserve(numberOfLegs);
|
|
||||||
for (size_t i = 0; i < numberOfLegs; ++i)
|
|
||||||
{
|
|
||||||
unionVec.push_back(csep.cloneWORecursiveSelects());
|
|
||||||
}
|
|
||||||
|
|
||||||
return unionVec;
|
|
||||||
}
|
|
||||||
|
|
||||||
// void applyParallelCES(CalpontSelectExecutionPlan& csep)
|
|
||||||
// {
|
|
||||||
// auto tables = csep.tableList();
|
|
||||||
// for (auto it = tables.begin(); it != tables.end(); ++it)
|
|
||||||
// {
|
|
||||||
// if (!it->isColumnstore())
|
|
||||||
// {
|
|
||||||
// size_t parallelFactor = 2;
|
|
||||||
// auto additionalUnionVec = makeUnionFromTable(parallelFactor, csep);
|
|
||||||
// csep.unionVec().insert(csep.unionVec().end(), additionalUnionVec.begin(), additionalUnionVec.end());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
void applyParallelCES(CalpontSelectExecutionPlan& csep)
|
|
||||||
{
|
|
||||||
auto tables = csep.tableList();
|
|
||||||
CalpontSelectExecutionPlan::TableList newTableList;
|
|
||||||
CalpontSelectExecutionPlan::SelectList newDerivedTableList;
|
|
||||||
static const std::string aliasPrefix = "$sub_";
|
|
||||||
|
|
||||||
// ATM Must be only 1 table
|
|
||||||
for (auto& table: tables)
|
|
||||||
{
|
|
||||||
if (!table.isColumnstore())
|
|
||||||
{
|
|
||||||
auto derivedSCEP = csep.cloneWORecursiveSelects();
|
|
||||||
// need to intro a level
|
|
||||||
std::string alias = aliasPrefix + table.schema + "_" + table.table;
|
|
||||||
|
|
||||||
derivedSCEP->location(CalpontSelectExecutionPlan::FROM);
|
|
||||||
derivedSCEP->subType(CalpontSelectExecutionPlan::FROM_SUBS);
|
|
||||||
derivedSCEP->derivedTbAlias(alias);
|
|
||||||
|
|
||||||
size_t parallelFactor = 2;
|
|
||||||
auto additionalUnionVec = makeUnionFromTable(parallelFactor, csep);
|
|
||||||
derivedSCEP->unionVec().insert(derivedSCEP->unionVec().end(), additionalUnionVec.begin(), additionalUnionVec.end());
|
|
||||||
|
|
||||||
// change parent to derived table columns
|
|
||||||
for (auto& rc : csep.returnedCols())
|
|
||||||
{
|
|
||||||
auto* sc = dynamic_cast<execplan::SimpleColumn*>(rc.get());
|
|
||||||
if (sc)
|
|
||||||
{
|
|
||||||
sc->tableName("");
|
|
||||||
sc->schemaName("");
|
|
||||||
sc->tableAlias(alias);
|
|
||||||
sc->colPosition(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WIP need to work with existing derived tables
|
|
||||||
newDerivedTableList.push_back(derivedSCEP);
|
|
||||||
// WIP
|
|
||||||
CalpontSystemCatalog::TableAliasName tn = make_aliasview("", "", alias, "");
|
|
||||||
newTableList.push_back(tn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SimpleColumn* sc = new SimpleColumn("test", "i1", "i", false, csep.sessionID());
|
|
||||||
// string alias(table->alias.c_ptr());
|
|
||||||
// sc->timeZone(csep.timeZone());
|
|
||||||
// sc->partitions(getPartitions(table));
|
|
||||||
// boost::shared_ptr<SimpleColumn> spsc(sc);
|
|
||||||
|
|
||||||
// csep.columnMap().insert({"`test`.`i1`.`i`", spsc});
|
|
||||||
|
|
||||||
csep.derivedTableList(newDerivedTableList);
|
|
||||||
csep.tableList(newTableList);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Rule
|
|
||||||
{
|
|
||||||
Rule(std::string&& name, bool (*matchRule)(CalpontSelectExecutionPlan&),
|
|
||||||
void (*applyRule)(CalpontSelectExecutionPlan&))
|
|
||||||
: name(name), matchRule(matchRule), applyRule(applyRule) {};
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
bool (*matchRule)(CalpontSelectExecutionPlan&);
|
|
||||||
void (*applyRule)(CalpontSelectExecutionPlan&);
|
|
||||||
bool apply(CalpontSelectExecutionPlan& csep)
|
|
||||||
{
|
|
||||||
bool rewrite = false;
|
|
||||||
for (auto& table : csep.derivedTableList())
|
|
||||||
{
|
|
||||||
auto& csepLocal = *dynamic_cast<execplan::CalpontSelectExecutionPlan*>(table.get());
|
|
||||||
if (matchRule(csepLocal))
|
|
||||||
{
|
|
||||||
applyRule(csepLocal);
|
|
||||||
rewrite = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rewrite |= apply(csepLocal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& unionUnit : csep.unionVec())
|
|
||||||
{
|
|
||||||
auto& unionUnitLocal = *dynamic_cast<execplan::CalpontSelectExecutionPlan*>(unionUnit.get());
|
|
||||||
|
|
||||||
if (matchRule(unionUnitLocal))
|
|
||||||
{
|
|
||||||
applyRule(unionUnitLocal);
|
|
||||||
rewrite = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rewrite |= apply(unionUnitLocal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matchRule(csep))
|
|
||||||
{
|
|
||||||
applyRule(csep);
|
|
||||||
rewrite = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rewrite;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int cs_get_select_plan(ha_columnstore_select_handler* handler, THD* /*thd*/, SCSEP& csep, gp_walk_info& gwi,
|
int cs_get_select_plan(ha_columnstore_select_handler* handler, THD* /*thd*/, SCSEP& csep, gp_walk_info& gwi,
|
||||||
bool isSelectLexUnit)
|
bool isSelectLexUnit)
|
||||||
@ -9393,15 +9238,7 @@ int cs_get_select_plan(ha_columnstore_select_handler* handler, THD* /*thd*/, SCS
|
|||||||
// Derived table projection and filter optimization.
|
// Derived table projection and filter optimization.
|
||||||
derivedTableOptimization(&gwi, csep);
|
derivedTableOptimization(&gwi, csep);
|
||||||
|
|
||||||
// static const Rule rules[] = {
|
optimizer::Rule parallelCES{"parallelCES", optimizer::matchParallelCES, optimizer::applyParallelCES};
|
||||||
// {"paralliseCES", matchparalliseCES, applyParalliseCES},
|
|
||||||
// /* add more here */
|
|
||||||
// };
|
|
||||||
|
|
||||||
// auto matchParallelCES = [](CalpontSelectExecutionPlan&){return false;};
|
|
||||||
// auto applyParallelCES = [](CalpontSelectExecutionPlan&){ return;};
|
|
||||||
|
|
||||||
Rule parallelCES{"parallelCES", matchParallelCES, applyParallelCES};
|
|
||||||
|
|
||||||
{
|
{
|
||||||
parallelCES.apply(*csep);
|
parallelCES.apply(*csep);
|
||||||
|
158
dbcon/mysql/rulebased_optimizer.cpp
Normal file
158
dbcon/mysql/rulebased_optimizer.cpp
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/* Copyright (C) 2025 MariaDB Corporation
|
||||||
|
|
||||||
|
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 Street, Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#include "execplan/calpontselectexecutionplan.h"
|
||||||
|
#include "execplan/simplecolumn.h"
|
||||||
|
#include "rulebased_optimizer.h"
|
||||||
|
|
||||||
|
namespace optimizer {
|
||||||
|
|
||||||
|
bool Rule::apply(execplan::CalpontSelectExecutionPlan& csep)
|
||||||
|
{
|
||||||
|
bool rewrite = false;
|
||||||
|
for (auto& table : csep.derivedTableList())
|
||||||
|
{
|
||||||
|
auto& csepLocal = *dynamic_cast<execplan::CalpontSelectExecutionPlan*>(table.get());
|
||||||
|
if (matchRule(csepLocal))
|
||||||
|
{
|
||||||
|
applyRule(csepLocal);
|
||||||
|
rewrite = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rewrite |= apply(csepLocal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& unionUnit : csep.unionVec())
|
||||||
|
{
|
||||||
|
auto& unionUnitLocal = *dynamic_cast<execplan::CalpontSelectExecutionPlan*>(unionUnit.get());
|
||||||
|
|
||||||
|
if (matchRule(unionUnitLocal))
|
||||||
|
{
|
||||||
|
applyRule(unionUnitLocal);
|
||||||
|
rewrite = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rewrite |= apply(unionUnitLocal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchRule(csep))
|
||||||
|
{
|
||||||
|
applyRule(csep);
|
||||||
|
rewrite = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rewrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool tableIsInUnion(const execplan::CalpontSystemCatalog::TableAliasName& table, execplan::CalpontSelectExecutionPlan& csep)
|
||||||
|
{
|
||||||
|
return std::any_of(csep.unionVec().begin(), csep.unionVec().end(),
|
||||||
|
[&table](const auto& unionUnit) {
|
||||||
|
execplan::CalpontSelectExecutionPlan* unionUnitLocal = dynamic_cast<execplan::CalpontSelectExecutionPlan*>(unionUnit.get());
|
||||||
|
bool tableIsPresented = std::any_of(unionUnitLocal->tableList().begin(), unionUnitLocal->tableList().end(),
|
||||||
|
[&table](const auto& unionTable) {
|
||||||
|
return unionTable == table;
|
||||||
|
});
|
||||||
|
return tableIsPresented;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matchParallelCES(execplan::CalpontSelectExecutionPlan& csep)
|
||||||
|
{
|
||||||
|
auto tables = csep.tableList();
|
||||||
|
// This is leaf and there are no other tables at this level.
|
||||||
|
// WIP filter out CSEPs with orderBy, groupBy, having
|
||||||
|
// WIP filter out CSEPs with nonSimpleColumns in projection
|
||||||
|
return tables.size() == 1 && !tables[0].isColumnstore() && !tableIsInUnion(tables[0], csep);
|
||||||
|
}
|
||||||
|
|
||||||
|
execplan::CalpontSelectExecutionPlan::SelectList makeUnionFromTable(const size_t numberOfLegs,
|
||||||
|
execplan::CalpontSelectExecutionPlan& csep)
|
||||||
|
{
|
||||||
|
execplan::CalpontSelectExecutionPlan::SelectList unionVec;
|
||||||
|
unionVec.reserve(numberOfLegs);
|
||||||
|
for (size_t i = 0; i < numberOfLegs; ++i)
|
||||||
|
{
|
||||||
|
unionVec.push_back(csep.cloneWORecursiveSelects());
|
||||||
|
}
|
||||||
|
|
||||||
|
return unionVec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyParallelCES(execplan::CalpontSelectExecutionPlan& csep)
|
||||||
|
{
|
||||||
|
auto tables = csep.tableList();
|
||||||
|
execplan::CalpontSelectExecutionPlan::TableList newTableList;
|
||||||
|
execplan::CalpontSelectExecutionPlan::SelectList newDerivedTableList;
|
||||||
|
static const std::string aliasPrefix = "$sub_";
|
||||||
|
|
||||||
|
// ATM Must be only 1 table
|
||||||
|
for (auto& table: tables)
|
||||||
|
{
|
||||||
|
if (!table.isColumnstore())
|
||||||
|
{
|
||||||
|
auto derivedSCEP = csep.cloneWORecursiveSelects();
|
||||||
|
// need to intro a level
|
||||||
|
std::string alias = aliasPrefix + table.schema + "_" + table.table;
|
||||||
|
|
||||||
|
derivedSCEP->location(execplan::CalpontSelectExecutionPlan::FROM);
|
||||||
|
derivedSCEP->subType(execplan::CalpontSelectExecutionPlan::FROM_SUBS);
|
||||||
|
derivedSCEP->derivedTbAlias(alias);
|
||||||
|
|
||||||
|
size_t parallelFactor = 2;
|
||||||
|
auto additionalUnionVec = makeUnionFromTable(parallelFactor, csep);
|
||||||
|
derivedSCEP->unionVec().insert(derivedSCEP->unionVec().end(), additionalUnionVec.begin(), additionalUnionVec.end());
|
||||||
|
|
||||||
|
// change parent to derived table columns
|
||||||
|
for (auto& rc : csep.returnedCols())
|
||||||
|
{
|
||||||
|
auto* sc = dynamic_cast<execplan::SimpleColumn*>(rc.get());
|
||||||
|
if (sc)
|
||||||
|
{
|
||||||
|
sc->tableName("");
|
||||||
|
sc->schemaName("");
|
||||||
|
sc->tableAlias(alias);
|
||||||
|
sc->colPosition(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WIP need to work with existing derived tables
|
||||||
|
newDerivedTableList.push_back(derivedSCEP);
|
||||||
|
// WIP
|
||||||
|
execplan::CalpontSystemCatalog::TableAliasName tn = execplan::make_aliasview("", "", alias, "");
|
||||||
|
newTableList.push_back(tn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimpleColumn* sc = new SimpleColumn("test", "i1", "i", false, csep.sessionID());
|
||||||
|
// string alias(table->alias.c_ptr());
|
||||||
|
// sc->timeZone(csep.timeZone());
|
||||||
|
// sc->partitions(getPartitions(table));
|
||||||
|
// boost::shared_ptr<SimpleColumn> spsc(sc);
|
||||||
|
|
||||||
|
// csep.columnMap().insert({"`test`.`i1`.`i`", spsc});
|
||||||
|
|
||||||
|
csep.derivedTableList(newDerivedTableList);
|
||||||
|
csep.tableList(newTableList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
40
dbcon/mysql/rulebased_optimizer.h
Normal file
40
dbcon/mysql/rulebased_optimizer.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* Copyright (C) 2025 MariaDB Corporation
|
||||||
|
|
||||||
|
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 Street, Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "execplan/calpontselectexecutionplan.h"
|
||||||
|
|
||||||
|
namespace optimizer {
|
||||||
|
|
||||||
|
struct Rule
|
||||||
|
{
|
||||||
|
Rule(std::string&& name, bool (*matchRule)(execplan::CalpontSelectExecutionPlan&),
|
||||||
|
void (*applyRule)(execplan::CalpontSelectExecutionPlan&))
|
||||||
|
: name(name), matchRule(matchRule), applyRule(applyRule) {};
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
bool (*matchRule)(execplan::CalpontSelectExecutionPlan&);
|
||||||
|
void (*applyRule)(execplan::CalpontSelectExecutionPlan&);
|
||||||
|
bool apply(execplan::CalpontSelectExecutionPlan& csep);
|
||||||
|
};
|
||||||
|
|
||||||
|
bool matchParallelCES(execplan::CalpontSelectExecutionPlan& csep);
|
||||||
|
void applyParallelCES(execplan::CalpontSelectExecutionPlan& csep);
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user