意见箱
恒创运营部门将仔细参阅您的意见和建议,必要时将通过预留邮箱与您保持联络。感谢您的支持!
意见/建议
提交建议

2022-07-15 mysql/stonedb子查询校验exists流程分析

来源:恒创科技 编辑:恒创科技编辑部
2023-12-21 16:10:59


目录

​​摘要:​​


2022-07-15 mysql/stonedb子查询校验exists流程分析

​​调用分析:​​

​​火焰图:​​

​​日志统计:​​

​​调用堆栈:​​

​​核心函数:​​

​​ParameterizedFilter::UpdateMultiIndex​​

​​ParameterizedFilter::ApplyDescriptor​​

​​Descriptor::EvaluatePackImpl​​

​​Descriptor::CheckCondition​​

​​SubSelectColumn::PrepareSubqResult​​

​​SubSelectColumn::RoughPrepareSubqCopy​​

​​ParameterizedFilter::operator=​​

​​DimensionGroupFilter::DimensionGroupFilter​​

​​Filter::Filter​​

​​Filter::Block::Block​​

​​Filter::Block::CopyFrom​​


摘要:

mysql/stonedb子查询校验exists流程分析

调用分析:火焰图:

​​tests/perf/vm-30.208/subquery-slow-20220711Jul071657525409.mysql.svg · adofsauron/stonedb-dev - Gitee.com​​

日志统计:

[2022-07-15 12:48:37.058888] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 12.153567 : EvaluatePackImpl: midCheckNum : 2584 opExistNum: 2584 opOther : 0
[2022-07-15 12:48:49.631277] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 12.565700 : EvaluatePackImpl: midCheckNum : 2567 opExistNum: 2567 opOther : 0
[2022-07-15 12:49:00.402314] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 10.763108 : EvaluatePackImpl: midCheckNum : 2592 opExistNum: 2592 opOther : 0
[2022-07-15 12:49:10.951728] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 10.541731 : EvaluatePackImpl: midCheckNum : 2532 opExistNum: 2532 opOther : 0
[2022-07-15 12:49:23.096156] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 12.135596 : EvaluatePackImpl: midCheckNum : 2536 opExistNum: 2536 opOther : 0
[2022-07-15 12:49:34.248395] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 11.141438 : EvaluatePackImpl: midCheckNum : 2560 opExistNum: 2560 opOther : 0
[2022-07-15 12:49:34.598449] [30234] [INFO] [engine.cpp:1352] MSG: Command: select 0/6, update 0/0, insert 0/0, load 0/0, queries 0/11
[2022-07-15 12:49:34.598595] [30234] [INFO] [engine.cpp:1364] MSG: Select: 0/3, Loaded: 0/0(0/0), dup: 0/0, insert: 0/0, failed insert: 0/0, update: 0/0
[2022-07-15 12:49:44.965755] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 10.703444 : EvaluatePackImpl: midCheckNum : 2488 opExistNum: 2488 opOther : 0
[2022-07-15 12:49:55.200405] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 10.229072 : EvaluatePackImpl: midCheckNum : 2522 opExistNum: 2522 opOther : 0
[2022-07-15 12:50:04.697895] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 9.490288 : EvaluatePackImpl: midCheckNum : 2450 opExistNum: 2450 opOther : 0
[2022-07-15 12:50:13.874090] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 9.170173 : EvaluatePackImpl: midCheckNum : 2485 opExistNum: 2485 opOther : 0
[2022-07-15 12:50:24.670956] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 10.789188 : EvaluatePackImpl: midCheckNum : 2553 opExistNum: 2553 opOther : 0
[2022-07-15 12:50:34.599255] [30234] [INFO] [engine.cpp:1352] MSG: Command: select 0/6, update 0/0, insert 0/0, load 0/0, queries 0/11
[2022-07-15 12:50:34.599402] [30234] [INFO] [engine.cpp:1364] MSG: Select: 0/3, Loaded: 0/0(0/0), dup: 0/0, insert: 0/0, failed insert: 0/0, update: 0/0
[2022-07-15 12:50:35.832047] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 11.153139 : EvaluatePackImpl: midCheckNum : 2523 opExistNum: 2523 opOther : 0
[2022-07-15 12:50:46.084675] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 10.245093 : EvaluatePackImpl: midCheckNum : 2566 opExistNum: 2566 opOther : 0
[2022-07-15 12:50:55.520449] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 9.428787 : EvaluatePackImpl: midCheckNum : 2532 opExistNum: 2532 opOther : 0
[2022-07-15 12:51:07.434729] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 11.907794 : EvaluatePackImpl: midCheckNum : 2548 opExistNum: 2548 opOther : 0
[2022-07-15 12:51:18.519859] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 11.078832 : EvaluatePackImpl: midCheckNum : 2568 opExistNum: 2568 opOther : 0
[2022-07-15 12:51:29.839873] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 11.312882 : EvaluatePackImpl: midCheckNum : 2603 opExistNum: 2603 opOther : 0
[2022-07-15 12:51:34.599807] [30234] [INFO] [engine.cpp:1352] MSG: Command: select 0/6, update 0/0, insert 0/0, load 0/0, queries 0/11
[2022-07-15 12:51:34.599962] [30234] [INFO] [engine.cpp:1364] MSG: Select: 0/3, Loaded: 0/0(0/0), dup: 0/0, insert: 0/0, failed insert: 0/0, update: 0/0
[2022-07-15 12:51:38.901222] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 9.054050 : EvaluatePackImpl: midCheckNum : 2557 opExistNum: 2557 opOther : 0
[2022-07-15 12:51:49.577223] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 10.670466 : EvaluatePackImpl: midCheckNum : 2582 opExistNum: 2582 opOther : 0
[2022-07-15 12:52:01.252591] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 11.668336 : EvaluatePackImpl: midCheckNum : 2494 opExistNum: 2494 opOther : 0
[2022-07-15 12:52:11.939402] [30257] [INFO] [descriptor.cpp:874] MSG: Timer 10.679633 : EvaluatePackImpl: midCheckNum : 2556 opExistNum: 2556 opOther : 0

调用堆栈:

(gdb) bt
#0 stonedb::core::Filter::Block::CopyFrom (this=0x7f614677d000, block=..., owner=0x7f6134e4e430) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/filter_block.cpp:68
#1 0x0000000002d5b7a4 in stonedb::core::Filter::Block::Block (this=0x7f614677d000, block=..., owner=0x7f6134e4e430)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/filter_block.cpp:52
#2 0x0000000002d53660 in stonedb::core::Filter::Filter (this=0x7f6134e4e430, filter=...) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/filter.cpp:106
#3 0x000000000313582d in stonedb::core::DimensionGroupFilter::DimensionGroupFilter (this=0x7f6134a1d9a0, dim=0, f_source=0x7f61349fda50, copy_mode=0, power=16)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/dimension_group.cpp:35
#4 0x00000000031387fe in stonedb::core::DimensionGroupFilter::Clone (this=0x7f61349fc930, shallow=false)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/dimension_group.h:142
#5 0x000000000308f6c0 in stonedb::core::MultiIndex::MultiIndex (this=0x7f6134caa700, s=...) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/multi_index.cpp:54
#6 0x00000000030ac3a0 in stonedb::core::ParameterizedFilter::operator= (this=0x7f61349f1380, pf=...)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/parameterized_filter.cpp:47
#7 0x0000000002dfdb5c in stonedb::core::TempTableForSubquery::ResetToTemplate (this=0x7f61349f1230, rough=true)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/temp_table.cpp:2168
#8 0x0000000002ea50e4 in stonedb::vcolumn::SubSelectColumn::RoughPrepareSubqCopy (this=0x7f61349f5810, mit=..., sot=stonedb::core::ROW_BASED)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/vc/subselect_column.cpp:403
#9 0x0000000002ea5841 in stonedb::vcolumn::SubSelectColumn::RoughIsEmpty (this=0x7f61349f5810, mit=..., sot=stonedb::core::ROW_BASED)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/vc/subselect_column.cpp:487
#10 0x0000000003055ee2 in stonedb::core::Descriptor::RoughCheckSubselectCondition (this=0x7f61349ff2b0, mit=..., sot=stonedb::core::ROW_BASED)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/descriptor.cpp:1189
#11 0x00000000030527ea in stonedb::core::Descriptor::EvaluatePackImpl (this=0x7f61349ff2b0, mit=...) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/descriptor.cpp:845
#12 0x0000000003052a58 in stonedb::core::Descriptor::EvaluatePack (this=0x7f61349ff2b0, mit=...) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/descriptor.cpp:898
#13 0x00000000030b46de in stonedb::core::ParameterizedFilter::ApplyDescriptor (this=0x7f61349ef110, desc_number=1, limit=-1)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/parameterized_filter.cpp:1365
#14 0x00000000030b2b37 in stonedb::core::ParameterizedFilter::UpdateMultiIndex (this=0x7f61349ef110, count_only=false, limit=-1)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/parameterized_filter.cpp:1065
#15 0x0000000002d731f7 in stonedb::core::Query::Preexecute (this=0x7f6501cb2800, qu=..., sender=0x7f61349e6bb0, display_now=true)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/query.cpp:777
#16 0x0000000002d44a2e in stonedb::core::Engine::Execute (this=0x7779df0, thd=0x7f6134913df0, lex=0x7f6134916118, result_output=0x7f61340091f0, unit_for_union=0x0)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/engine_execute.cpp:421
#17 0x0000000002d43ce2 in stonedb::core::Engine::HandleSelect (this=0x7779df0, thd=0x7f6134913df0, lex=0x7f6134916118, result=@0x7f6501cb2d18: 0x7f61340091f0, setup_tables_done_option=0,
res=@0x7f6501cb2d14: 0, optimize_after_sdb=@0x7f6501cb2d0c: 1, sdb_free_join=@0x7f6501cb2d10: 1, with_insert=0)
at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/core/engine_execute.cpp:232
#18 0x0000000002e2c4df in stonedb::dbhandler::SDB_HandleSelect (thd=0x7f6134913df0, lex=0x7f6134916118, result=@0x7f6501cb2d18: 0x7f61340091f0, setup_tables_done_option=0, res=@0x7f6501cb2d14: 0,
optimize_after_sdb=@0x7f6501cb2d0c: 1, sdb_free_join=@0x7f6501cb2d10: 1, with_insert=0) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/stonedb/handler/ha_rcengine.cpp:82
#19 0x000000000246fe5a in execute_sqlcom_select (thd=0x7f6134913df0, all_tables=0x7f6134015440) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/sql/sql_parse.cc:5182
#20 0x00000000024691de in mysql_execute_command (thd=0x7f6134913df0, first_level=true) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/sql/sql_parse.cc:2831
#21 0x0000000002470e23 in mysql_parse (thd=0x7f6134913df0, parser_state=0x7f6501cb3eb0) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/sql/sql_parse.cc:5621
#22 0x00000000024660bb in dispatch_command (thd=0x7f6134913df0, com_data=0x7f6501cb4650, command=COM_QUERY) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/sql/sql_parse.cc:1495
#23 0x0000000002464fe7 in do_command (thd=0x7f6134913df0) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/sql/sql_parse.cc:1034
#24 0x0000000002597c03 in handle_connection (arg=0x7ea03b0) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/sql/conn_handler/connection_handler_per_thread.cc:313
#25 0x0000000002c7b834 in pfs_spawn_thread (arg=0x939e3f0) at /data/jenkins/workspace/stonedb5.7-zsl-centos7.9/storage/perfschema/pfs.cc:2197
#26 0x00007f65514c6ea5 in start_thread (arg=0x7f6501cb5700) at pthread_create.c:307
#27 0x00007f654f8fdb0d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

核心函数:ParameterizedFilter::UpdateMultiIndex
void ParameterizedFilter::UpdateMultiIndex(bool count_only, int64_t limit) {
MEASURE_FET("ParameterizedFilter::UpdateMultiIndex(...)");

thd_proc_info(mind->ConnInfo().Thd(), "update multi-index");

if (descriptors.Size() < 1) {
PrepareRoughMultiIndex();
rough_mind->ClearLocalDescFilters();
return;
}
SyntacticalDescriptorListPreprocessing();

bool empty_cannot_grow = true; // if false (e.g. outer joins), then do not
// optimize empty multiindex as empty result

for (uint i = 0; i < descriptors.Size(); i++)
if (descriptors[i].IsOuter()) empty_cannot_grow = false;

// special cases
bool nonempty = true;

DescriptorListOrdering();

// descriptor display
if (rccontrol.isOn()) {
rccontrol.lock(mind->m_conn->GetThreadID()) << "Initial execution plan (non-join):" << system::unlock;
for (uint i = 0; i < descriptors.Size(); i++)
if (!descriptors[i].done && !descriptors[i].IsType_Join() && descriptors[i].IsInner()) {
char buf[1000];
std::strcpy(buf, " ");
descriptors[i].ToString(buf, 1000);
if (descriptors[i].IsDelayed())
rccontrol.lock(mind->m_conn->GetThreadID())
<< "Delayed: " << buf << " \t(" << int(descriptors[i].evaluation * 100) / 100.0 << ")" << system::unlock;
else
rccontrol.lock(mind->m_conn->GetThreadID())
<< "Cnd(" << i << "): " << buf << " \t(" << int(descriptors[i].evaluation * 100) / 100.0 << ")"
<< system::unlock;
}
}

// end now if the multiindex is empty
if (mind->ZeroTuples() && empty_cannot_grow) {
mind->Empty();
PrepareRoughMultiIndex();
rough_mind->ClearLocalDescFilters();
return;
}

// Prepare execution - rough set part
for (uint i = 0; i < descriptors.Size(); i++) {
if (!descriptors[i].done && descriptors[i].IsInner()) {
if (descriptors[i].IsTrue()) {
descriptors[i].done = true;

continue;
} else if (descriptors[i].IsFalse()) {
if (descriptors[i].attr.vc) {
descriptors[i].done = true;
if (empty_cannot_grow) {
mind->Empty();
PrepareRoughMultiIndex();
rough_mind->ClearLocalDescFilters();
return;
} else {
DimensionVector dims(mind->NoDimensions());
descriptors[i].attr.vc->MarkUsedDims(dims);
mind->MakeCountOnly(0, dims);
}
}
}
}
}
if (rough_mind) rough_mind->ClearLocalDescFilters();
PrepareRoughMultiIndex();
nonempty = RoughUpdateMultiIndex(); // calculate all rough conditions,

if ((!nonempty && empty_cannot_grow) || mind->m_conn->Explain()) {
mind->Empty(); // nonempty==false if the whole result is empty (outer joins
// considered)
rough_mind->ClearLocalDescFilters();
return;
}
PropagateRoughToMind(); // exclude common::RSValue::RS_NONE from mind

// count other types of conditions, e.g. joins (i.e. conditions using
// attributes from two
// dimensions)
int no_of_join_conditions = 0; // count also one-dimensional outer join conditions
int no_of_delayed_conditions = 0;
for (uint i = 0; i < descriptors.Size(); i++) {
if (!descriptors[i].done)
if (descriptors[i].IsType_Join() || descriptors[i].IsDelayed() || descriptors[i].IsOuter()) {
if (!descriptors[i].IsDelayed())
no_of_join_conditions++;
else
no_of_delayed_conditions++;
}
}

// Apply all one-dimensional filters (after where, i.e. without
// outer joins)
int last_desc_dim = -1;
int cur_dim = -1;

int no_desc = 0;
for (uint i = 0; i < descriptors.Size(); i++)
if (!descriptors[i].done && descriptors[i].IsInner() && !descriptors[i].IsType_Join() &&
!descriptors[i].IsDelayed())
++no_desc;

int ApplyDescriptorNum = 0;
std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();

int descriptorsNum = descriptors.Size();

if (descriptorsNum > 1) {
STONEDB_LOG(LogCtl_Level::INFO, "UpdateMultiIndex: descriptorsNum : %d",
descriptorsNum);
}

int desc_no = 0;
for (uint i = 0; i < descriptors.Size(); i++) {
if (!descriptors[i].done && descriptors[i].IsInner() && !descriptors[i].IsType_Join() &&
!descriptors[i].IsDelayed()) {
++desc_no;
if (descriptors[i].attr.vc) {
cur_dim = descriptors[i].attr.vc->GetDim();
}
if (last_desc_dim != -1 && cur_dim != -1 && last_desc_dim != cur_dim) {
// Make all possible projections to other dimensions
RoughMakeProjections(cur_dim, false);
}

++ApplyDescriptorNum;

// limit should be applied only for the last descriptor
ApplyDescriptor(i, (desc_no != no_desc || no_of_delayed_conditions > 0 || no_of_join_conditions) ? -1 : limit);
if (!descriptors[i].attr.vc) continue; // probably desc got simplified and is true or false
if (cur_dim >= 0 && mind->GetFilter(cur_dim) && mind->GetFilter(cur_dim)->IsEmpty() && empty_cannot_grow) {
mind->Empty();
if (rccontrol.isOn()) {
rccontrol.lock(mind->m_conn->GetThreadID())
<< "Empty result set after non-join condition evaluation (WHERE)" << system::unlock;
}
rough_mind->ClearLocalDescFilters();
return;
}
last_desc_dim = cur_dim;
}
}

if (ApplyDescriptorNum > 1) {
auto diff =
std::chrono::duration_cast<std::chrono::duration<float>>(std::chrono::high_resolution_clock::now() - start);
STONEDB_LOG(LogCtl_Level::INFO, "Timer %f : UpdateMultiIndex: ApplyDescriptorNum : %d", diff.count(),
ApplyDescriptorNum);
}

rough_mind->UpdateReducedDimension();
mind->UpdateNoTuples();
for (int i = 0; i < mind->NoDimensions(); i++)
if (mind->GetFilter(i))
table->SetVCDistinctVals(i,
mind->GetFilter(i)->NoOnes()); // distinct values - not more than the
// number of rows after WHERE
rough_mind->ClearLocalDescFilters();

// Some displays

if (rccontrol.isOn()) {
int pack_full = 0, pack_some = 0, pack_all = 0;
rccontrol.lock(mind->m_conn->GetThreadID())
<< "Packrows after exact evaluation (execute WHERE end):" << system::unlock;
for (uint i = 0; i < (uint)mind->NoDimensions(); i++)
if (mind->GetFilter(i)) {
Filter *f = mind->GetFilter(i);
pack_full = 0;
pack_some = 0;
pack_all = (int)((mind->OrigSize(i) + ((1 << mind->NoPower()) - 1)) >> mind->NoPower());
for (int b = 0; b < pack_all; b++) {
if (f->IsFull(b))
pack_full++;
else if (!f->IsEmpty(b))
pack_some++;
}
rccontrol.lock(mind->m_conn->GetThreadID())
<< "(t" << i << "): " << pack_all << " all packrows, " << pack_full + pack_some << " to open (including "
<< pack_full << " full)" << system::unlock;
}
}

DescriptorJoinOrdering();

// descriptor display for joins
if (rccontrol.isOn()) {
bool first_time = true;
for (uint i = 0; i < descriptors.Size(); i++)
if (!descriptors[i].done && (descriptors[i].IsType_Join() || descriptors[i].IsOuter())) {
if (first_time) {
rccontrol.lock(mind->m_conn->GetThreadID()) << "Join execution plan:" << system::unlock;
first_time = false;
}
char buf[1000];
std::strcpy(buf, " ");
descriptors[i].ToString(buf, 1000);
if (descriptors[i].IsDelayed())
rccontrol.lock(mind->m_conn->GetThreadID())
<< "Delayed: " << buf << " \t(" << int(descriptors[i].evaluation * 100) / 100.0 << ")" << system::unlock;
else
rccontrol.lock(mind->m_conn->GetThreadID())
<< "Cnd(" << i << "): " << buf << " \t(" << int(descriptors[i].evaluation * 100) / 100.0 << ")"
<< system::unlock;
}
}

bool join_or_delayed_present = false;
for (uint i = 0; i < descriptors.Size(); i++) {
if (mind->ZeroTuples() && empty_cannot_grow) {
// set all following descriptors to done
for (uint j = i; j < descriptors.Size(); j++) descriptors[j].done = true;
break;
}
if (!descriptors[i].done && !descriptors[i].IsDelayed()) {
// Merging join conditions
Condition join_desc;
PrepareJoiningStep(join_desc, descriptors, i,
*mind); // group together all join conditions for one step
no_of_join_conditions -= join_desc.Size();
JoinTips join_tips(*mind);

// Optimization: Check whether there exists "a is null" delayed condition
// for an outer join
if (join_desc[0].IsOuter()) {
for (uint i = 0; i < descriptors.Size(); i++) {
if (descriptors[i].IsDelayed() && !descriptors[i].done && descriptors[i].op == common::Operator::O_IS_NULL &&
join_desc[0].right_dims.Get(descriptors[i].attr.vc->GetDim()) &&
!descriptors[i].attr.vc->IsNullsPossible()) {
for (int j = 0; j < join_desc[0].right_dims.Size(); j++) {
if (join_desc[0].right_dims[j] == true) join_tips.null_only[j] = true;
}
descriptors[i].done = true; // completed inside joining algorithms
no_of_delayed_conditions--;
}
}
}

if (no_of_join_conditions == 0 && // optimizations used only for the last group of conditions
no_of_delayed_conditions == 0 && parametrized_desc.Size() == 0) {
// Optimization: count_only is true => do not materialize multiindex
// (just counts tuples). WARNING: in this case cannot use multiindex for
// any operations other than NoTuples().
if (count_only) join_tips.count_only = true;
join_tips.limit = limit;
// only one dim used in distinct context?
int distinct_dim = table->DimInDistinctContext();
int dims_in_output = 0;
for (int dim = 0; dim < mind->NoDimensions(); dim++)
if (mind->IsUsedInOutput(dim)) dims_in_output++;
if (distinct_dim != -1 && dims_in_output == 1) join_tips.distinct_only[distinct_dim] = true;
}

// Optimization: Check whether all dimensions are really used
DimensionVector dims_used(mind->NoDimensions());
for (uint jj = 0; jj < descriptors.Size(); jj++) {
if (jj != i && !descriptors[jj].done) descriptors[jj].DimensionUsed(dims_used);
}
// can't utilize not_used_dims in case there are parameterized descs left
if (parametrized_desc.Size() == 0) {
for (int dim = 0; dim < mind->NoDimensions(); dim++)
if (!mind->IsUsedInOutput(dim) && dims_used[dim] == false) join_tips.forget_now[dim] = true;
}

// Joining itself
UpdateJoinCondition(join_desc, join_tips);
}
}

// Execute all delayed conditions
for (uint i = 0; i < descriptors.Size(); i++) {
if (!descriptors[i].done) {
rccontrol.lock(mind->m_conn->GetThreadID()) << "Executing delayed Cnd(" << i << ")" << system::unlock;
descriptors[i].CoerceColumnTypes();
descriptors[i].Simplify();
ApplyDescriptor(i);
join_or_delayed_present = true;
}
}
if (join_or_delayed_present) rough_mind->MakeDimensionSuspect(); // no common::RSValue::RS_ALL packs
mind->UpdateNoTuples();
}
ParameterizedFilter::ApplyDescriptor
void ParameterizedFilter::ApplyDescriptor(int desc_number, int64_t limit)
// desc_number = -1 => switch off the rough part
{
Descriptor &desc = descriptors[desc_number];
if (desc.op == common::Operator::O_TRUE) {
desc.done = true;
return;
}
if (desc.op == common::Operator::O_FALSE) {
mind->Empty();
desc.done = true;
return;
}

DimensionVector dims(mind->NoDimensions());
desc.DimensionUsed(dims);
mind->MarkInvolvedDimGroups(dims); // create iterators on whole groups (important for
// multidimensional updatable iterators)
int no_dims = dims.NoDimsUsed();
if (no_dims == 0 && !desc.IsDeterministic()) dims.SetAll();
// Check the easy case (one-dim, parallelizable)
int one_dim = -1;
common::RSValue *rf = NULL;
if (no_dims == 1) {
for (int i = 0; i < mind->NoDimensions(); i++) {
if (dims[i]) {
if (mind->GetFilter(i)) one_dim = i; // exactly one filter (non-join or join with forgotten dims)
break;
}
}
}
if (one_dim != -1)
rf = rough_mind->GetLocalDescFilter(one_dim, desc_number,
true); // "true" here means that we demand an existing local rough
// filter

int packs_no = (int)((mind->OrigSize(one_dim) + ((1 << mind->NoPower()) - 1)) >> mind->NoPower());
int pack_all = rough_mind->NoPacks(one_dim);
int pack_some = 0;
for (int b = 0; b < pack_all; b++) {
if (rough_mind->GetPackStatus(one_dim, b) != common::RSValue::RS_NONE) pack_some++;
}
MIUpdatingIterator mit(mind, dims);
desc.CopyDesCond(mit);
if (desc.EvaluateOnIndex(mit, limit) == common::ErrorCode::SUCCESS) {
rccontrol.lock(mind->m_conn->GetThreadID())
<< "EvaluateOnIndex done, desc number " << desc_number << system::unlock;
} else {
int poolsize = rceng->query_thread_pool.size();
if ((stonedb_sysvar_threadpoolsize > 0) && (packs_no / poolsize > 0) && !desc.IsType_Subquery() &&
!desc.ExsitTmpTable()) {
int step = 0;
int task_num = 0;
/*Partition task slice*/
if (pack_some <= poolsize) {
task_num = poolsize;
} else {
step = pack_some / poolsize;
task_num = packs_no / step;
}
int mod = packs_no % task_num;
int num = packs_no / task_num;

std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();

desc.InitParallel(task_num, mit);

std::vector<MultiIndex> mis;
mis.reserve(task_num);

std::vector<MIUpdatingIterator> taskIterator;
taskIterator.reserve(task_num);

for (int i = 0; i < task_num; ++i) {
auto &mi = mis.emplace_back(*mind, true);
int pstart = ((i == 0) ? 0 : mod + i * num);
int pend = mod + (i + 1) * num - 1;

auto &mii = taskIterator.emplace_back(&mi, dims);
mii.SetTaskNum(task_num);
mii.SetTaskId(i);
mii.SetNoPacksToGo(pend);
mii.RewindToPack(pstart);
}

utils::result_set<void> res;
for (int i = 0; i < task_num; ++i) {
res.insert(rceng->query_thread_pool.add_task(&ParameterizedFilter::TaskProcessPacks, this, &taskIterator[i],
current_tx, rf, &dims, desc_number, limit, one_dim));
}
res.get_all_with_except();

if (mind->m_conn->Killed()) throw common::KilledException("catch thread pool Exception: TaskProcessPacks");
mind->UpdateNoTuples();

auto diff =
std::chrono::duration_cast<std::chrono::duration<float>>(std::chrono::high_resolution_clock::now() - start);
STONEDB_LOG(LogCtl_Level::INFO, "Timer %f : ApplyDescriptor: Parallel : task_num : %d", diff.count(),
task_num);

} else {
common::RSValue cur_roughval;
uint64_t passed = 0;
int pack = -1;

int descEvaluatePackNum = 0;
std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();

while (mit.IsValid()) {
if (limit != -1 && rf) { // rf - not null if there is one dim only
// (otherwise packs make no sense)
if (passed >= (uint64_t)limit) {
mit.ResetCurrentPack();
mit.NextPackrow();
continue;
}
if (mit.PackrowStarted()) {
if (pack != -1) passed += mit.NoOnesUncommited(pack);
pack = mit.GetCurPackrow(one_dim);
}
}

if (rf && mit.GetCurPackrow(one_dim) >= 0)
cur_roughval = rf[mit.GetCurPackrow(one_dim)];
else
cur_roughval = common::RSValue::RS_SOME;

if (cur_roughval == common::RSValue::RS_NONE) {
mit.ResetCurrentPack();
mit.NextPackrow();
} else if (cur_roughval == common::RSValue::RS_ALL) {
mit.NextPackrow();
} else {
// common::RSValue::RS_SOME or common::RSValue::RS_UNKNOWN
desc.EvaluatePack(mit);
}
if (mind->m_conn->Killed()) throw common::KilledException();

++descEvaluatePackNum;
}

if (descEvaluatePackNum > 1) {
auto diff =
std::chrono::duration_cast<std::chrono::duration<float>>(std::chrono::high_resolution_clock::now() - start);
STONEDB_LOG(LogCtl_Level::INFO, "Timer %f : ApplyDescriptor: descEvaluatePackNum : %d", diff.count(),
descEvaluatePackNum);
}


mit.Commit();
}
}
desc.done = true;
if (one_dim != -1 && mind->GetFilter(one_dim)) { // update global rough part
Filter *f = mind->GetFilter(one_dim);
for (int p = 0; p < rough_mind->NoPacks(one_dim); p++)
if (f->IsEmpty(p)) {
rough_mind->SetPackStatus(one_dim, p, common::RSValue::RS_NONE);
}
}
desc.UpdateVCStatistics();
return;
}
Descriptor::EvaluatePackImpl
void Descriptor::EvaluatePackImpl(MIUpdatingIterator &mit) {
MEASURE_FET("Descriptor::EvaluatePackImpl(...)");

// Check if we can delegate evaluation of descriptor to physical column
if (encoded)
attr.vc->EvaluatePack(mit, *this);
else if (IsType_OrTree() && (GetParallelSize() == 0)) {
// single thread Prepare rough values to be stored inside the tree
tree->root->ClearRoughValues();
tree->root->EvaluateRoughlyPack(mit);
tree->root->EvaluatePack(mit);
} else if (IsType_OrTree() && GetParallelSize()) {
// muti thread for IsType_OrTree; single reserved
tree->root->MClearRoughValues(mit.GetTaskId());
tree->root->MEvaluateRoughlyPack(mit, mit.GetTaskId());
tree->root->MEvaluatePack(mit, mit.GetTaskId());
} else if (types::RequiresUTFConversions(collation)) {
std::scoped_lock guard(mtx);
while (mit.IsValid()) {
if (CheckCondition_UTF(mit) == false) mit.ResetCurrent();
++mit;
if (mit.PackrowStarted()) break;
}
} else {
if (IsType_Subquery() && op != common::Operator::O_OR_TREE) {
// pack based optimization of corr. subq. by using RoughQuery
common::Tribool res = RoughCheckSubselectCondition(mit, SubSelectOptimizationType::PACK_BASED);
if (res == false)
mit.ResetCurrentPack();
else if (res == common::TRIBOOL_UNKNOWN) {
// int true_c = 0, false_c = 0, unkn_c = 0;

int midCheckNum = 0;
int opExistNum = 0;
int opOther = 0;
std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();

while (mit.IsValid()) {

++midCheckNum;

//std::chrono::high_resolution_clock::time_point __start = std::chrono::high_resolution_clock::now();


// row based optimization of corr. subq. by using RoughQuery
res = RoughCheckSubselectCondition(mit, SubSelectOptimizationType::ROW_BASED);
// if(res == false)
// false_c++;
// else if(res == true)
// true_c++;
// else
// unkn_c++;
if (res == false)
mit.ResetCurrent();
else if (res == common::TRIBOOL_UNKNOWN && CheckCondition(mit) == false)
mit.ResetCurrent();
++mit;

if (op == common::Operator::O_EXISTS || op == common::Operator::O_NOT_EXISTS) {
++opExistNum;
} else {
++opOther;
}

//auto diff = std::chrono::duration_cast<std::chrono::duration<float>>(
// std::chrono::high_resolution_clock::now() - start);
//STONEDB_LOG(LogCtl_Level::INFO, "Timer %f : CheckCondition: OP : %d", diff.count(), static_cast<int>(op));

if (mit.PackrowStarted()) break;
}

auto diff =
std::chrono::duration_cast<std::chrono::duration<float>>(std::chrono::high_resolution_clock::now() - start);
STONEDB_LOG(LogCtl_Level::INFO, "Timer %f : EvaluatePackImpl: midCheckNum : %d opExistNum: %d opOther : %d",
diff.count(), midCheckNum, opExistNum, opOther);

// cout << "# of skipped subqueries: " << true_c << "/" << false_c <<
// "/" << unkn_c
// << " -> " << (true_c + false_c) << " / " << (true_c + false_c +
// unkn_c) << endl;
}
} else {
std::scoped_lock guard(mtx);
while (mit.IsValid()) {
if (CheckCondition(mit) == false) mit.ResetCurrent();
++mit;
if (mit.PackrowStarted()) break;
}
}
}
}
Descriptor::CheckCondition
bool Descriptor::CheckCondition(const MIIterator &mit) {
MEASURE_FET("Descriptor::CheckCondition(...)");
if (op == common::Operator::O_TRUE)
return true;
else if (op == common::Operator::O_FALSE)
return false;

bool result = true;

// Assumption: LockSourcePacks externally done.
if (op == common::Operator::O_EQ) { // fast track for the most common operator
DEBUG_ASSERT(attr.vc && val1.vc);
// nulls checked in operator ==
if (!(attr.vc->GetValue(mit) == val1.vc->GetValue(mit))) return false;
} else if (op == common::Operator::O_NOT_NULL) {
if (attr.vc->IsNull(mit)) return false;
} else if (op == common::Operator::O_IS_NULL) {
if (!attr.vc->IsNull(mit)) return false;
} else if (op == common::Operator::O_EXISTS || op == common::Operator::O_NOT_EXISTS) {
DEBUG_ASSERT(dynamic_cast<vcolumn::SubSelectColumn *>(attr.vc));
vcolumn::SubSelectColumn *sub = static_cast<vcolumn::SubSelectColumn *>(attr.vc);
bool is_nonempty = sub->CheckExists(mit);
if ((op == common::Operator::O_EXISTS && !is_nonempty) || (op == common::Operator::O_NOT_EXISTS && is_nonempty))
return false;
} else if (op == common::Operator::O_BETWEEN || op == common::Operator::O_NOT_BETWEEN) {
if (attr.vc->IsNull(mit)) return false;
// need to consider three value logic
common::Tribool val1_res, val2_res;
if (encoded) {
if (attr.vc->Type().IsString() && !attr.vc->Type().IsLookup()) {
types::BString val, v1, v2;
attr.vc->GetNotNullValueString(val, mit);
val1.vc->GetValueString(v1, mit);
val2.vc->GetValueString(v2, mit);
val1_res = v1.IsNull() ? true : (sharp ? common::Tribool(val > v1) : common::Tribool(val >= v1));
val2_res = v2.IsNull() ? true : (sharp ? common::Tribool(val < v2) : common::Tribool(val <= v2));
} else if (!attr.vc->Type().IsFloat()) {
int64_t val = attr.vc->GetNotNullValueInt64(mit);
val1_res =
val1.vc->IsNull(mit) ? common::TRIBOOL_UNKNOWN : common::Tribool(val >= val1.vc->GetNotNullValueInt64(mit));
val2_res =
val2.vc->IsNull(mit) ? common::TRIBOOL_UNKNOWN : common::Tribool(val <= val2.vc->GetNotNullValueInt64(mit));
} else { // Rare case: for encoded conditions treat NULL as +/- inf.
types::RCValueObject rcvo1 = attr.vc->GetValue(mit, false);
val1_res = val1.vc->IsNull(mit) ? true
: (sharp ? common::Tribool(rcvo1 > val1.vc->GetValue(mit, false))
: common::Tribool(rcvo1 >= val1.vc->GetValue(mit, false)));
val2_res = val2.vc->IsNull(mit) ? true
: (sharp ? common::Tribool(rcvo1 < val2.vc->GetValue(mit, false))
: common::Tribool(rcvo1 <= val2.vc->GetValue(mit, false)));
}
} else {
types::RCValueObject rcvo1 = attr.vc->GetValue(mit, false);
val1_res =
val1.vc->IsNull(mit) ? common::TRIBOOL_UNKNOWN : common::Tribool(rcvo1 >= val1.vc->GetValue(mit, false));
val2_res =
val2.vc->IsNull(mit) ? common::TRIBOOL_UNKNOWN : common::Tribool(rcvo1 <= val2.vc->GetValue(mit, false));
}
if (op == common::Operator::O_BETWEEN) {
if (val1_res != true || val2_res != true) return false;
} else {
if (val1_res != false && val2_res != false) return false;
}
} else if (IsSetOperator(op)) {
DEBUG_ASSERT(attr.vc && dynamic_cast<vcolumn::MultiValColumn *>(val1.vc));
return CheckSetCondition(mit, op);
} else if (IsType_OrTree()) {
DEBUG_ASSERT(tree);
return tree->root->CheckCondition((MIIterator &)mit);
} else { // all other logical operators: >, >=, <, <=
DEBUG_ASSERT(attr.vc && val1.vc);
if (attr.vc->IsNull(mit) || val1.vc->IsNull(mit)) return false;
if (!types::RCValueObject::compare(attr.vc->GetValue(mit), val1.vc->GetValue(mit), op, like_esc)) return false;
}
return result;
}
SubSelectColumn::PrepareSubqResult
void SubSelectColumn::PrepareSubqResult(const core::MIIterator &mit, bool exists_only) {
MEASURE_FET("SubSelectColumn::PrepareSubqCopy(...)");
bool cor = IsCorrelated();
if (!cor) {
if (subq->IsFullyMaterialized()) return;
}

subq->CreateTemplateIfNotExists();

if (cor && (FeedArguments(mit, false))) {
cache.reset();
no_cached_values = 0;
subq->ResetToTemplate(false);
subq->ResetVCStatistics();
subq->SuspendDisplay();
try {
subq->ProcessParameters(mit,
parent_tt_alias); // exists_only is not needed
// here (limit already set)
} catch (...) {
subq->ResumeDisplay();
throw;
}
subq->ResumeDisplay();
}
subq->SuspendDisplay();
try {
if (exists_only) subq->SetMode(core::TMParameter::TM_EXISTS);
subq->Materialize(cor);
} catch (...) {
subq->ResumeDisplay();
// subq->ResetForSubq();
throw;
}
subq->ResumeDisplay();
}
SubSelectColumn::RoughPrepareSubqCopy
void SubSelectColumn::RoughPrepareSubqCopy(const core::MIIterator &mit,
[[maybe_unused]] core::SubSelectOptimizationType sot) {
MEASURE_FET("SubSelectColumn::RoughPrepareSubqCopy(...)");
subq->CreateTemplateIfNotExists();
if ((!IsCorrelated() && first_eval_for_rough) || (IsCorrelated() && (FeedArguments(mit, true)))) {
out_of_date_rough = false;
// cache.reset();
// no_cached_values = 0;
subq->ResetToTemplate(true);
subq->ResetVCStatistics();
subq->SuspendDisplay();
try {
subq->RoughProcessParameters(mit, parent_tt_alias);
} catch (...) {
subq->ResumeDisplay();
}
subq->ResumeDisplay();
}
subq->SuspendDisplay();
try {
subq->RoughMaterialize(true);
} catch (...) {
}
subq->ResumeDisplay();
}
ParameterizedFilter::operator=
ParameterizedFilter &ParameterizedFilter::operator=(const ParameterizedFilter &pf) {
if (this != &pf) {
if (mind) delete mind;
if (pf.mind)
mind = new MultiIndex(*pf.mind);
else
mind = NULL; // possible e.g. for a temporary data sources
AssignInternal(pf);
}
return *this;
}
DimensionGroupFilter::DimensionGroupFilter
// copy_mode: 0 - copy filter, 1 - ShallowCopy filter, 2 - grab pointer
DimensionGroupFilter::DimensionGroupFilter(int dim, Filter *f_source, int copy_mode, [[maybe_unused]] uint32_t power) {
base_dim = dim;
f = NULL;
if (copy_mode == 0)
f = new Filter(*f_source);
else if (copy_mode == 1)
f = Filter::ShallowCopy(*f_source);
else if (copy_mode == 2)
f = f_source;
dim_group_type = DGType::DG_FILTER;
no_obj = f->NoOnes();
}
Filter::Filter
Filter::Filter(const Filter &filter)
: mm::TraceableObject(filter),
block_status(0),
blocks(0),
no_of_bits_in_last_block(0),
shallow(false),
block_last_one(NULL),
delayed_stats(-1),
delayed_block(-1),
delayed_stats_set(-1) {
MEASURE_FET("Filter::Filter(const Filter&)");
Filter &tmp_filter = const_cast<Filter &>(filter);
no_power = filter.no_power;
pack_def = 1 << no_power;
no_blocks = filter.NoBlocks();
no_of_bits_in_last_block = tmp_filter.NoAddBits();
blocks = new Block *[no_blocks];
ConstructPool();
block_filter = this;
for (size_t i = 0; i < no_blocks; i++) {
if (tmp_filter.GetBlock(i)) {
blocks[i] = block_allocator->Alloc(false);
new (blocks[i]) Block(*(tmp_filter.GetBlock(i)),
block_filter); // block_filter<->this
} else
blocks[i] = NULL;
}
block_status = new uchar[no_blocks];
std::memcpy(block_status, filter.block_status, no_blocks);
block_last_one = new ushort[no_blocks];
std::memcpy(block_last_one, filter.block_last_one, no_blocks * sizeof(ushort));
block_changed.resize(no_blocks);
}
Filter::Block::Block
Filter::Block::Block(Block const &block, Filter *owner) {
MEASURE_FET("Filter::Block::Block(...)");
block_table = 0;
CopyFrom(block, owner);
}
Filter::Block::CopyFrom
void Filter::Block::CopyFrom(Block const &block, Filter *owner) {
MEASURE_FET("Filter::Block::CopyFrom(...)");
this->owner = owner;
block_size = block.block_size;
no_set_bits = block.no_set_bits;
no_obj = block.no_obj;
if (block.block_table) {
if (!block_table) {
owner->bit_mut->lock();
block_table = (uint *)owner->bit_block_pool->malloc();
owner->bit_mut->unlock();
if (!block_table) throw common::OutOfMemoryException();
}
std::memcpy(block_table, block.block_table, block_size * sizeof(uint));
}
}
上一篇: 2022-07-13 mysql/stonedb子查询-优化器处理记录 下一篇: 2022-07-15 mysql接收新连接处理