From: Ole John Aske Date: October 25 2011 8:10am Subject: bzr push into mysql-trunk-cluster branch (ole.john.aske:3398 to 3399) List-Archive: http://lists.mysql.com/commits/141573 Message-Id: <20111025081002.D8E68233@fimafeng09.norway.sun.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3399 Ole John Aske 2011-10-25 Integrated pushed join execution into new MRR interface. modified: mysql-test/suite/ndb/r/ndb_join_pushdown.result sql/ha_ndbcluster.cc 3398 Ole John Aske 2011-10-21 Reverted part of previous fix: Increased execute count should not be expected after all when 'Read Before Write Removal' now has been implemented. modified: mysql-test/suite/ndb/t/ndb_bulk_delete.test === modified file 'mysql-test/suite/ndb/r/ndb_join_pushdown.result' --- a/mysql-test/suite/ndb/r/ndb_join_pushdown.result 2011-10-18 10:43:35 +0000 +++ b/mysql-test/suite/ndb/r/ndb_join_pushdown.result 2011-10-25 08:09:27 +0000 @@ -4028,15 +4028,15 @@ and new_count.counter_name <> 'LOCAL_REA and new_count.counter_name <> 'REMOTE_READS_SENT'; counter_name new_count.val - old_count.val CONST_PRUNED_RANGE_SCANS_RECEIVED 0 -LOCAL_RANGE_SCANS_SENT 0 +LOCAL_RANGE_SCANS_SENT 2 LOCAL_TABLE_SCANS_SENT 2 PRUNED_RANGE_SCANS_RECEIVED 0 -RANGE_SCANS_RECEIVED 0 -READS_NOT_FOUND 1 +RANGE_SCANS_RECEIVED 2 +READS_NOT_FOUND 2 READS_RECEIVED 1 REMOTE_RANGE_SCANS_SENT 0 -SCAN_BATCHES_RETURNED 2 -SCAN_ROWS_RETURNED 5 +SCAN_BATCHES_RETURNED 4 +SCAN_ROWS_RETURNED 8 TABLE_SCANS_RECEIVED 2 select 'READS_SENT', sum(new_count.val - old_count.val) from new_count, old_count @@ -4044,7 +4044,7 @@ where new_count.counter_name = old_count and (new_count.counter_name = 'LOCAL_READS_SENT' or new_count.counter_name = 'REMOTE_READS_SENT'); READS_SENT sum(new_count.val - old_count.val) -READS_SENT 5 +READS_SENT 7 drop table old_count; drop table new_count; drop table t1; @@ -5487,8 +5487,8 @@ counter_name spj_counts_at_end.val - spj CONST_PRUNED_RANGE_SCANS_RECEIVED 6 LOCAL_TABLE_SCANS_SENT 250 PRUNED_RANGE_SCANS_RECEIVED 25 -RANGE_SCANS_RECEIVED 703 -READS_RECEIVED 53 +RANGE_SCANS_RECEIVED 726 +READS_RECEIVED 58 TABLE_SCANS_RECEIVED 250 drop table spj_counts_at_startup; drop table spj_counts_at_end; @@ -5497,11 +5497,11 @@ scan_count_derived pruned_scan_count 8 sorted_scan_count -34 +35 pushed_queries_defined 401 pushed_queries_dropped -6 +9 pushed_queries_executed -529 +547 set ndb_join_pushdown = @save_ndb_join_pushdown; === modified file 'sql/ha_ndbcluster.cc' --- a/sql/ha_ndbcluster.cc 2011-10-21 12:52:20 +0000 +++ b/sql/ha_ndbcluster.cc 2011-10-25 08:09:27 +0000 @@ -14668,8 +14668,6 @@ read_multi_needs_scan(NDB_INDEX_TYPE cur The implementation is copied from handler::multi_range_read_info_const. The only difference is that NDB-MRR cannot handle blob columns or keys with NULLs for unique indexes. We disable MRR for those cases. - As Pushed join execution has not yet been integrated into NDB-MRR, - we also disable MRR for those. NOTES See NOTES for handler::multi_range_read_info_const(). @@ -14730,9 +14728,7 @@ ha_ndbcluster::multi_range_read_info_con { if (uses_blob_value(table->read_set) || ((get_index_type(keyno) == UNIQUE_INDEX && - has_null_in_unique_index(keyno)) && null_ranges) - || (m_pushed_join_operation==PUSHED_ROOT && - !m_disable_pushed_join)) + has_null_in_unique_index(keyno)) && null_ranges)) { /* Use default MRR implementation */ *flags|= HA_MRR_USE_DEFAULT_IMPL; @@ -14867,6 +14863,9 @@ int ha_ndbcluster::multi_range_read_init || bufsize < multi_range_fixed_size(1) + multi_range_max_entry(get_index_type(active_index), table_share->reclength) + || (m_pushed_join_operation==PUSHED_ROOT && + !m_disable_pushed_join && + !m_pushed_join_member->get_query_def().isScanQuery()) || m_delete_cannot_batch || m_update_cannot_batch) { m_disable_multi_read= TRUE; @@ -14992,7 +14991,10 @@ int ha_ndbcluster::multi_range_start_ret if (range_no >= max_range) break; my_bool need_scan= - read_multi_needs_scan(cur_index_type, key_info, &mrr_cur_range); + read_multi_needs_scan(cur_index_type, key_info, &mrr_cur_range) || + // Pushed joins restricted to ordered range scan in mrr + (m_pushed_join_operation==PUSHED_ROOT && + m_pushed_join_member->get_query_def().isScanQuery()); if (row_buf + multi_range_entry_size(!need_scan, reclength) > end_of_buffer) break; if (need_scan) @@ -15069,7 +15071,25 @@ int ha_ndbcluster::multi_range_start_ret DBUG_PRINT("info", ("any_real_read= TRUE")); /* Create the scan operation for the first scan range. */ - if (!m_multi_cursor) + if (check_if_pushable(NdbQueryOperationDef::OrderedIndexScan, + active_index, + !m_active_query && mrr_is_output_sorted)) + { + DBUG_ASSERT(!m_read_before_write_removal_used); + if (!m_active_query) + { + const int error= create_pushed_join(); + if (unlikely(error)) + DBUG_RETURN(error); + + NdbQuery* const query= m_active_query; + if (mrr_is_output_sorted && + query->getQueryOperation((uint)PUSHED_ROOT)->setOrdering(NdbQueryOptions::ScanOrdering_ascending)) + ERR_RETURN(query->getNdbError()); + } + } // check_if_pushable() + + else if (!m_multi_cursor) { /* Do a multi-range index scan for ranges not done by primary/unique key. */ NdbScanOperation::ScanOptions options; @@ -15147,12 +15167,24 @@ int ha_ndbcluster::multi_range_start_ret &mrr_cur_range.start_key, &mrr_cur_range.end_key, 0); bound.range_no= range_no; - if (m_multi_cursor->setBound(m_index[active_index].ndb_record_key, - bound, - ndbPartSpecPtr, // Only for user-def tables - sizeof(Ndb::PartitionSpec))) + const NdbRecord *key_rec= m_index[active_index].ndb_record_key; + if (m_active_query) + { + DBUG_PRINT("info", ("setBound:%d, for pushed join", bound.range_no)); + if (m_active_query->setBound(key_rec, &bound)) + { + ERR_RETURN(trans->getNdbError()); + } + } + else { - ERR_RETURN(trans->getNdbError()); + if (m_multi_cursor->setBound(m_index[active_index].ndb_record_key, + bound, + ndbPartSpecPtr, // Only for user-def tables + sizeof(Ndb::PartitionSpec))) + { + ERR_RETURN(trans->getNdbError()); + } } multi_range_entry_type(row_buf)= enum_ordered_range; @@ -15201,17 +15233,60 @@ int ha_ndbcluster::multi_range_start_ret ppartitionId=&partitionId; } - if (!(op= pk_unique_index_read_key(active_index, - mrr_cur_range.start_key.key, - multi_range_row(row_buf), lm, - ppartitionId))) - ERR_RETURN(trans->getNdbError()); + /** + * 'Pushable codepath' is incomplete and expected not + * to be produced as make_join_pushed() handle + * AT_MULTI_UNIQUE_KEY as non-pushable. + */ + if (m_pushed_join_operation==PUSHED_ROOT && + !m_disable_pushed_join && + !m_pushed_join_member->get_query_def().isScanQuery()) + { + DBUG_ASSERT(false); // FIXME: Incomplete code, should not be executed + DBUG_ASSERT(lm == NdbOperation::LM_CommittedRead); + const int error= pk_unique_index_read_key_pushed(active_index, + mrr_cur_range.start_key.key, + ppartitionId); + if (unlikely(error)) + DBUG_RETURN(error); + } + else + { + if (m_pushed_join_operation == PUSHED_ROOT) + { + DBUG_PRINT("info", ("Cannot push join due to incomplete implementation.")); + m_thd_ndb->m_pushed_queries_dropped++; + } + if (!(op= pk_unique_index_read_key(active_index, + mrr_cur_range.start_key.key, + multi_range_row(row_buf), lm, + ppartitionId))) + ERR_RETURN(trans->getNdbError()); + } } oplist[num_keyops++]= op; row_buf= multi_range_next_entry(row_buf, reclength); } } + if (m_active_query != NULL && + m_pushed_join_member->get_query_def().isScanQuery()) + { + m_thd_ndb->m_scan_count++; + if (mrr_is_output_sorted) + { + m_thd_ndb->m_sorted_scan_count++; + } + + bool prunable= false; + if (unlikely(m_active_query->isPrunable(prunable) != 0)) + ERR_RETURN(m_active_query->getNdbError()); + if (prunable) + m_thd_ndb->m_pruned_scan_count++; + + DBUG_PRINT("info", ("Is MRR scan-query pruned to 1 partition? :%u", prunable)); + DBUG_ASSERT(!m_multi_cursor); + } if (m_multi_cursor) { DBUG_PRINT("info", ("Is MRR scan pruned to 1 partition? :%u", No bundle (reason: useless for push emails).