Skip to content

Commit 792f2d2

Browse files
author
Jonas Oreland
committed
ndb - merge latest spj changes
2 parents 12bff39 + 4674fe7 commit 792f2d2

File tree

6 files changed

+490
-95
lines changed

6 files changed

+490
-95
lines changed

mysql-test/suite/ndb/r/ndb_join_pushdown.result

+246-29
Large diffs are not rendered by default.

mysql-test/suite/ndb/t/ndb_join_pushdown.test

+162-47
Original file line numberDiff line numberDiff line change
@@ -37,30 +37,6 @@ let $pushed_queries_dropped_at_startup = query_get_value(show status like 'Ndb_p
3737
let $pushed_queries_executed_at_startup = query_get_value(show status like 'Ndb_pushed_queries_executed', Value, 1);
3838
let $pushed_reads_at_startup = query_get_value(show status like 'Ndb_pushed_reads', Value, 1);
3939

40-
# Use this table and the two queries below to turn of meassuring
41-
# SCAN_ROWS_RETURNED for certain bushy scan queries. The reason for this is
42-
# that growth of this counter is platform dependent for these queries. There
43-
# are two reasons for this:
44-
# 1. Distribution hashing (partitioning) of tables is endian dependent. This
45-
# may cause data to be more skewed on some platforms. This again requires more
46-
# batches to scan the table and thus more repeats of repeatable scans (i.e.
47-
# those that will be repeated for each batch of the other branch of a bushy
48-
# scan). This increases the overall scan row count.
49-
# 2. If a timer expires in LQH after receiving SCAN_FRAGREQ, LQH may decide to
50-
# send SCAN_FRAGCONF immediately, even if more tuples could fit in the batch.
51-
# As above this causes more repeats of repeatable scans.
52-
53-
create temporary table spj_save_counts like spj_counts_at_startup;
54-
55-
insert into spj_save_counts values ('SCAN_ROWS_RETURNED', 0);
56-
57-
# Record current counter value.
58-
let $save_scan_rows_returned = update spj_save_counts set val = (select sum(val) from ndbinfo.counters where block_name='DBSPJ' and counter_name='SCAN_ROWS_RETURNED') where counter_name='SCAN_ROWS_RETURNED';
59-
60-
# Update spj_counts_at_startup to compensate for counter increments since
61-
# running save_scan_rows_returned.
62-
let $compensate_scan_rows_returned = update spj_counts_at_startup set val = val + (select sum(val) from ndbinfo.counters where block_name='DBSPJ' and counter_name='SCAN_ROWS_RETURNED') - (select val from spj_save_counts where counter_name='SCAN_ROWS_RETURNED') where counter_name='SCAN_ROWS_RETURNED';
63-
6440
##############
6541
# Test start
6642

@@ -1046,7 +1022,6 @@ connection ddl;
10461022
alter table t1 partition by key(a);
10471023

10481024
connection spj;
1049-
eval $save_scan_rows_returned;
10501025

10511026
explain select count(*) from t1
10521027
join t1 as t2 on t2.a = t1.c
@@ -1077,8 +1052,6 @@ select count(*) from t1 as x1
10771052
join t1 as x2 on x2.a = x1.c and x1.b < 2
10781053
join t1 as x3 on x3.a = x1.c;
10791054

1080-
eval $compensate_scan_rows_returned;
1081-
10821055
connection ddl;
10831056
drop table t1;
10841057
drop table tx;
@@ -1281,6 +1254,162 @@ insert into t1 values (0x4f, null);
12811254
--sorted_result
12821255
select * from t1 left join t1 as t2 on t2.a = t1.b;
12831256

1257+
### Test max number of pushable operations.
1258+
1259+
insert into t3 values (8,8,8,8);
1260+
1261+
# Unique lookups only.
1262+
explain extended select count(*) from t3 as x0
1263+
join t3 as x1 on x0.b3=x1.d3 and x0.d3=8
1264+
join t3 as x2 on x1.b3=x2.d3
1265+
join t3 as x3 on x2.b3=x3.d3
1266+
join t3 as x4 on x3.b3=x4.d3
1267+
join t3 as x5 on x4.b3=x5.d3
1268+
join t3 as x6 on x5.b3=x6.d3
1269+
join t3 as x7 on x6.b3=x7.d3
1270+
join t3 as x8 on x7.b3=x8.d3
1271+
join t3 as x9 on x8.b3=x9.d3
1272+
join t3 as x10 on x9.b3=x10.d3
1273+
join t3 as x11 on x10.b3=x11.d3
1274+
join t3 as x12 on x11.b3=x12.d3
1275+
join t3 as x13 on x12.b3=x13.d3
1276+
join t3 as x14 on x13.b3=x14.d3
1277+
join t3 as x15 on x14.b3=x15.d3
1278+
join t3 as x16 on x15.b3=x16.d3
1279+
join t3 as x17 on x16.b3=x17.d3;
1280+
1281+
select count(*) from t3 as x0
1282+
join t3 as x1 on x0.b3=x1.d3 and x0.d3=8
1283+
join t3 as x2 on x1.b3=x2.d3
1284+
join t3 as x3 on x2.b3=x3.d3
1285+
join t3 as x4 on x3.b3=x4.d3
1286+
join t3 as x5 on x4.b3=x5.d3
1287+
join t3 as x6 on x5.b3=x6.d3
1288+
join t3 as x7 on x6.b3=x7.d3
1289+
join t3 as x8 on x7.b3=x8.d3
1290+
join t3 as x9 on x8.b3=x9.d3
1291+
join t3 as x10 on x9.b3=x10.d3
1292+
join t3 as x11 on x10.b3=x11.d3
1293+
join t3 as x12 on x11.b3=x12.d3
1294+
join t3 as x13 on x12.b3=x13.d3
1295+
join t3 as x14 on x13.b3=x14.d3
1296+
join t3 as x15 on x14.b3=x15.d3
1297+
join t3 as x16 on x15.b3=x16.d3
1298+
join t3 as x17 on x16.b3=x17.d3;
1299+
1300+
1301+
# Max scans
1302+
explain extended select count(*) from t3 as x0
1303+
join t3 as x1 on x0.c3=x1.a3
1304+
join t3 as x2 on x1.c3=x2.a3
1305+
join t3 as x3 on x2.c3=x3.a3
1306+
join t3 as x4 on x3.c3=x4.a3
1307+
join t3 as x5 on x4.c3=x5.a3
1308+
join t3 as x6 on x5.c3=x6.a3
1309+
join t3 as x7 on x6.c3=x7.a3
1310+
join t3 as x8 on x7.c3=x8.a3
1311+
join t3 as x9 on x8.c3=x9.a3
1312+
join t3 as x10 on x9.c3=x10.a3
1313+
join t3 as x11 on x10.c3=x11.a3
1314+
join t3 as x12 on x11.c3=x12.a3
1315+
join t3 as x13 on x12.c3=x13.a3
1316+
join t3 as x14 on x13.c3=x14.a3
1317+
join t3 as x15 on x14.c3=x15.a3
1318+
join t3 as x16 on x15.c3=x16.a3
1319+
join t3 as x17 on x16.c3=x17.a3
1320+
join t3 as x18 on x17.c3=x18.a3
1321+
join t3 as x19 on x18.c3=x19.a3
1322+
join t3 as x20 on x19.c3=x20.a3
1323+
join t3 as x21 on x20.c3=x21.a3
1324+
join t3 as x22 on x21.c3=x22.a3
1325+
join t3 as x23 on x22.c3=x23.a3
1326+
join t3 as x24 on x23.c3=x24.a3
1327+
join t3 as x25 on x24.c3=x25.a3
1328+
join t3 as x26 on x25.c3=x26.a3
1329+
join t3 as x27 on x26.c3=x27.a3
1330+
join t3 as x28 on x27.c3=x28.a3
1331+
join t3 as x29 on x28.c3=x29.a3
1332+
join t3 as x30 on x29.c3=x30.a3
1333+
join t3 as x31 on x30.c3=x31.a3
1334+
join t3 as x32 on x31.c3=x32.a3
1335+
join t3 as x33 on x32.c3=x33.a3;
1336+
1337+
select count(*) from t3 as x0
1338+
join t3 as x1 on x0.c3=x1.a3
1339+
join t3 as x2 on x1.c3=x2.a3
1340+
join t3 as x3 on x2.c3=x3.a3
1341+
join t3 as x4 on x3.c3=x4.a3
1342+
join t3 as x5 on x4.c3=x5.a3
1343+
join t3 as x6 on x5.c3=x6.a3
1344+
join t3 as x7 on x6.c3=x7.a3
1345+
join t3 as x8 on x7.c3=x8.a3
1346+
join t3 as x9 on x8.c3=x9.a3
1347+
join t3 as x10 on x9.c3=x10.a3
1348+
join t3 as x11 on x10.c3=x11.a3
1349+
join t3 as x12 on x11.c3=x12.a3
1350+
join t3 as x13 on x12.c3=x13.a3
1351+
join t3 as x14 on x13.c3=x14.a3
1352+
join t3 as x15 on x14.c3=x15.a3
1353+
join t3 as x16 on x15.c3=x16.a3
1354+
join t3 as x17 on x16.c3=x17.a3
1355+
join t3 as x18 on x17.c3=x18.a3
1356+
join t3 as x19 on x18.c3=x19.a3
1357+
join t3 as x20 on x19.c3=x20.a3
1358+
join t3 as x21 on x20.c3=x21.a3
1359+
join t3 as x22 on x21.c3=x22.a3
1360+
join t3 as x23 on x22.c3=x23.a3
1361+
join t3 as x24 on x23.c3=x24.a3
1362+
join t3 as x25 on x24.c3=x25.a3
1363+
join t3 as x26 on x25.c3=x26.a3
1364+
join t3 as x27 on x26.c3=x27.a3
1365+
join t3 as x28 on x27.c3=x28.a3
1366+
join t3 as x29 on x28.c3=x29.a3
1367+
join t3 as x30 on x29.c3=x30.a3
1368+
join t3 as x31 on x30.c3=x31.a3
1369+
join t3 as x32 on x31.c3=x32.a3
1370+
join t3 as x33 on x32.c3=x33.a3;
1371+
1372+
#Mixed join
1373+
explain extended select count(*) from t3 as x0
1374+
join t3 as x1 on x0.b3=x1.d3
1375+
join t3 as x2 on x1.b3=x2.d3
1376+
join t3 as x3 on x2.b3=x3.d3
1377+
join t3 as x4 on x3.b3=x4.d3
1378+
join t3 as x5 on x4.b3=x5.d3
1379+
join t3 as x6 on x5.b3=x6.d3
1380+
join t3 as x7 on x6.b3=x7.d3
1381+
join t3 as x8 on x7.b3=x8.d3
1382+
join t3 as x9 on x8.b3=x9.d3
1383+
join t3 as x10 on x9.b3=x10.d3
1384+
join t3 as x11 on x10.b3=x11.d3
1385+
join t3 as x12 on x11.b3=x12.d3
1386+
join t3 as x13 on x12.b3=x13.d3
1387+
join t3 as x14 on x13.b3=x14.d3
1388+
join t3 as x15 on x14.b3=x15.d3
1389+
join t3 as x16 on x15.b3=x16.d3
1390+
join t3 as x17 on x15.b3=x17.a3
1391+
join t3 as x18 on x16.b3=x18.d3;
1392+
1393+
select count(*) from t3 as x0
1394+
join t3 as x1 on x0.b3=x1.d3
1395+
join t3 as x2 on x1.b3=x2.d3
1396+
join t3 as x3 on x2.b3=x3.d3
1397+
join t3 as x4 on x3.b3=x4.d3
1398+
join t3 as x5 on x4.b3=x5.d3
1399+
join t3 as x6 on x5.b3=x6.d3
1400+
join t3 as x7 on x6.b3=x7.d3
1401+
join t3 as x8 on x7.b3=x8.d3
1402+
join t3 as x9 on x8.b3=x9.d3
1403+
join t3 as x10 on x9.b3=x10.d3
1404+
join t3 as x11 on x10.b3=x11.d3
1405+
join t3 as x12 on x11.b3=x12.d3
1406+
join t3 as x13 on x12.b3=x13.d3
1407+
join t3 as x14 on x13.b3=x14.d3
1408+
join t3 as x15 on x14.b3=x15.d3
1409+
join t3 as x16 on x15.b3=x16.d3
1410+
join t3 as x17 on x15.b3=x17.a3
1411+
join t3 as x18 on x16.b3=x18.d3;
1412+
12841413
connection ddl;
12851414
drop table t1,t2,t3, t3_hash;
12861415

@@ -2987,7 +3116,6 @@ explain extended select straight_join * from
29873116
# These should be allowed to be executed in 'parallel', depending on
29883117
# only the root operation
29893118
#
2990-
eval $save_scan_rows_returned;
29913119

29923120
explain extended select straight_join count(*) from t1 as x1
29933121
join t1 as x2 on x2.b = x1.a
@@ -3023,8 +3151,6 @@ select straight_join count(*) from t1 as x1
30233151
join t1 as x7 on x7.b = x1.a
30243152
where x3.a < x2.pk and x4.a < x3.pk;
30253153

3026-
eval $compensate_scan_rows_returned;
3027-
30283154
#############
30293155
# If we have an outer join, we can't create an artificial dep. 'through' the outer join.
30303156
# In this case the child scan can't be part of the pushed query.
@@ -3064,8 +3190,6 @@ select straight_join count(*) from t1 as x1
30643190
#
30653191
# Bushy execution is expected for these scans (x2 & x4) wrt. root (x1)
30663192
#
3067-
eval $save_scan_rows_returned;
3068-
30693193
explain extended
30703194
select straight_join count(*) from t1 as x1
30713195
join t1 as x2 on x2.b = x1.a
@@ -3080,8 +3204,6 @@ select straight_join count(*) from t1 as x1
30803204
join t1 as x2 on x2.b = x1.a
30813205
join t1 as x3 on x3.pk = x1.a join t1 as x4 on x4.b = x3.a;
30823206

3083-
eval $compensate_scan_rows_returned;
3084-
30853207
#############
30863208
# Test bushy lookups + 1scan,
30873209
# (Regression test for previous commit: http://lists.mysql.com/commits/117571)
@@ -3195,16 +3317,12 @@ explain select straight_join count(*) from t1 as x0
31953317
join t3 as x3 on x2.c=x3.a
31963318
join t1 as x4 on x0.d=x4.a and x3.b=x4.b;
31973319

3198-
eval $save_scan_rows_returned;
3199-
32003320
select straight_join count(*) from t1 as x0
32013321
join t3 as x1 on x0.c=x1.a
32023322
join t1 as x2 on x0.c=x2.a
32033323
join t3 as x3 on x2.c=x3.a
32043324
join t1 as x4 on x0.d=x4.a and x3.b=x4.b;
32053325

3206-
eval $compensate_scan_rows_returned;
3207-
32083326
connection ddl;
32093327
drop table t1;
32103328
drop table t2;
@@ -3720,21 +3838,15 @@ connection spj;
37203838
select spj_counts_at_end.counter_name, spj_counts_at_end.val - spj_counts_at_startup.val
37213839
from spj_counts_at_end, spj_counts_at_startup
37223840
where spj_counts_at_end.counter_name = spj_counts_at_startup.counter_name
3841+
and spj_counts_at_end.counter_name <> 'READS_NOT_FOUND'
37233842
and spj_counts_at_end.counter_name <> 'LOCAL_READS_SENT'
37243843
and spj_counts_at_end.counter_name <> 'REMOTE_READS_SENT'
37253844
and spj_counts_at_end.counter_name <> 'LOCAL_RANGE_SCANS_SENT'
37263845
and spj_counts_at_end.counter_name <> 'REMOTE_RANGE_SCANS_SENT'
3846+
and spj_counts_at_end.counter_name <> 'SCAN_ROWS_RETURNED'
37273847
and spj_counts_at_end.counter_name <> 'SCAN_BATCHES_RETURNED';
37283848

3729-
# The sum of LOCAL+REMOTE should be constant
3730-
select sum(spj_counts_at_end.val - spj_counts_at_startup.val) as 'LOCAL+REMOTE READS_SENT'
3731-
from spj_counts_at_end, spj_counts_at_startup
3732-
where spj_counts_at_end.counter_name = spj_counts_at_startup.counter_name
3733-
and (spj_counts_at_end.counter_name = 'LOCAL_READS_SENT'
3734-
or spj_counts_at_end.counter_name = 'REMOTE_READS_SENT');
3735-
37363849
connection spj;
3737-
drop table spj_save_counts;
37383850
drop table spj_counts_at_startup;
37393851
drop table spj_counts_at_end;
37403852

@@ -3750,7 +3862,10 @@ let $pushed_reads_at_end = query_get_value(show status like 'Ndb_pushed_reads',
37503862

37513863
# Calculate the change.
37523864
--disable_query_log
3753-
--eval select $scan_count_at_end - $scan_count_at_startup as scan_count
3865+
# There is some random variation in scan_count, probably due to statistics
3866+
# being updated at unpredictable intervals. Therefore, we only test for
3867+
# deviations greater than on tenth of the expected value.
3868+
--eval select round(($scan_count_at_end - $scan_count_at_startup)/2524, 1) as scan_count_derived
37543869
--eval select $pruned_scan_count_at_end - $pruned_scan_count_at_startup as pruned_scan_count
37553870
--eval select $sorted_scan_count_at_end - $sorted_scan_count_at_startup as sorted_scan_count
37563871
--eval select $pushed_queries_defined_at_end - $pushed_queries_defined_at_startup as pushed_queries_defined

sql/ha_ndbcluster_push.cc

+42
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ ndb_pushed_builder_ctx::ndb_pushed_builder_ctx(const AQP::Join_plan& plan)
324324
m_join_root(),
325325
m_join_scope(),
326326
m_const_scope(),
327+
m_internal_op_count(0),
327328
m_fld_refs(0),
328329
m_builder(NULL)
329330
{
@@ -492,6 +493,33 @@ ndb_pushed_builder_ctx::make_pushed_join(
492493
} // ndb_pushed_builder_ctx::make_pushed_join()
493494

494495

496+
/**
497+
* Find the number SPJ operations needed to execute a given access type.
498+
* (Unique index lookups are translated to two single table lookups internally.)
499+
*/
500+
uint internal_operation_count(AQP::enum_access_type accessType)
501+
{
502+
switch (accessType)
503+
{
504+
case AQP::AT_PRIMARY_KEY:
505+
case AQP::AT_ORDERED_INDEX_SCAN:
506+
case AQP::AT_MULTI_PRIMARY_KEY:
507+
case AQP::AT_MULTI_MIXED:
508+
case AQP::AT_TABLE_SCAN:
509+
return 1;
510+
511+
// Unique key lookups is mapped to two primary key lookups internally.
512+
case AQP::AT_UNIQUE_KEY:
513+
case AQP::AT_MULTI_UNIQUE_KEY:
514+
return 2;
515+
516+
default:
517+
// Other access types are not pushable, so seeing them here is an error.
518+
DBUG_ASSERT(false);
519+
return 2;
520+
}
521+
}
522+
495523
/**
496524
* If there is a pushable query starting with 'root'; add as many
497525
* child operations as possible to this 'ndb_pushed_builder_ctx' starting
@@ -531,6 +559,7 @@ ndb_pushed_builder_ctx::is_pushable_with_root(const AQP::Table_access* root)
531559
m_join_root= root;
532560
m_const_scope.set_prefix(root_no);
533561
m_join_scope= ndb_table_access_map(root_no);
562+
m_internal_op_count = internal_operation_count(access_type);
534563

535564
uint push_cnt= 0;
536565
for (uint tab_no= root->get_access_no()+1; tab_no<m_plan.get_access_count(); tab_no++)
@@ -637,6 +666,19 @@ ndb_pushed_builder_ctx::is_pushable_as_child(
637666
}
638667
}
639668

669+
// Check that we do not exceed the max number of pushable operations.
670+
const uint internal_ops_needed = internal_operation_count(access_type);
671+
if (unlikely(m_internal_op_count + internal_ops_needed
672+
> NDB_SPJ_MAX_TREE_NODES))
673+
{
674+
EXPLAIN_NO_PUSH("Cannot push table '%s' as child of '%s'. Max number"
675+
" of pushable tables exceeded.",
676+
table->get_table()->alias,
677+
m_join_root->get_table()->alias);
678+
DBUG_RETURN(false);
679+
}
680+
m_internal_op_count += internal_ops_needed;
681+
640682
DBUG_PRINT("info", ("Table:%d, Checking %d REF keys", tab_no,
641683
table->get_no_of_key_fields()));
642684

sql/ha_ndbcluster_push.h

+3
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@ class ndb_pushed_builder_ctx
258258
// Set of tables required to have strict sequential dependency
259259
ndb_table_access_map m_forced_sequence;
260260

261+
// Number of internal operations used so far (unique lookups count as two).
262+
uint m_internal_op_count;
263+
261264
uint m_fld_refs;
262265
Field* m_referred_fields[ndb_pushed_join::MAX_REFERRED_FIELDS];
263266

0 commit comments

Comments
 (0)