From: Ole John Aske Date: November 11 2010 1:07pm Subject: bzr commit into mysql-5.1-telco-7.0-spj-scan-vs-scan branch (ole.john.aske:3360) List-Archive: http://lists.mysql.com/commits/123604 Message-Id: <20101111130747.AE3ED222@fimafeng09.norway.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0789258762759789815==" --===============0789258762759789815== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///net/fimafeng09/export/home/tmp/oleja/mysql/mysql-5.1-telco-7.0-spj-scan-scan/ based on revid:ole.john.aske@stripped 3360 Ole John Aske 2010-11-11 spj-svs: Followup on commit 'revno: 3322' (Less eager order access request) This commit was based on the idea that we could disable the ordered index usage by setting 'QUICK_SELECT_I::sorted=false' when we later decided to use a filesort to provide the ordered resultset. However, for QUICK_SELECT_DESC the implementation internals also assumed the underlying table to return its result in sorted order. It will therefore cause incorrect results if 'sorted' is disabled for QUICK_SELECT_DESC. AQP::is_fixed_ordered_index() has been introduced for the purpose of identifying those QUICK_SELECT's which has 'fixed' its access to use an 'ordered_index'. Furthermore, QUICK_SELECT_DESC::reset() has been extended to make sure that 'sorted= 1' before the QUICK_SELECT_DESC resulset is made available. modified: mysql-test/suite/ndb/r/ndb_join_pushdown.result mysql-test/suite/ndb/t/ndb_join_pushdown.test sql/abstract_query_plan.cc sql/abstract_query_plan.h sql/ha_ndbcluster.cc sql/opt_range.cc sql/opt_range.h === modified file 'mysql-test/suite/ndb/r/ndb_join_pushdown.result' --- a/mysql-test/suite/ndb/r/ndb_join_pushdown.result 2010-11-09 10:11:09 +0000 +++ b/mysql-test/suite/ndb/r/ndb_join_pushdown.result 2010-11-11 13:07:41 +0000 @@ -4475,6 +4475,28 @@ select * from t as t1 join t as t2 on t2 b a b a 0 0 0 0 drop table t; +create table t (pk1 int, pk2 int, primary key(pk1,pk2)) engine = ndb; +insert into t values (1,3), (3,6), (6,9), (9,1); +explain extended +select * from t as t1 join t as t2 +on t1.pk2 = t2.pk1 +where t1.pk1 != 6 +order by t1.pk1 DESC; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 20 10.00 Using where with pushed condition: (`test`.`t1`.`pk1` <> 6) +1 SIMPLE t2 ref PRIMARY PRIMARY 4 test.t1.pk2 1 100.00 +Warnings: +Note 1644 Push of table 't2' as scan-child with ordered indexscan-root 't1' not implemented +Note 1003 select `test`.`t1`.`pk1` AS `pk1`,`test`.`t1`.`pk2` AS `pk2`,`test`.`t2`.`pk1` AS `pk1`,`test`.`t2`.`pk2` AS `pk2` from `test`.`t` `t1` join `test`.`t` `t2` where ((`test`.`t2`.`pk1` = `test`.`t1`.`pk2`) and (`test`.`t1`.`pk1` <> 6)) order by `test`.`t1`.`pk1` desc +select * from t as t1 join t as t2 +on t1.pk2 = t2.pk1 +where t1.pk1 != 6 +order by t1.pk1 DESC; +pk1 pk2 pk1 pk2 +9 1 1 3 +3 6 6 9 +1 3 3 6 +drop table t; create table tc( a varchar(10) not null, b varchar(10), @@ -4567,11 +4589,11 @@ LOCAL+REMOTE READS_SENT drop table spj_counts_at_startup; drop table spj_counts_at_end; scan_count -2014 +2021 pruned_scan_count 8 sorted_scan_count -7 +9 pushed_queries_defined 348 pushed_queries_dropped === modified file 'mysql-test/suite/ndb/t/ndb_join_pushdown.test' --- a/mysql-test/suite/ndb/t/ndb_join_pushdown.test 2010-11-09 13:01:43 +0000 +++ b/mysql-test/suite/ndb/t/ndb_join_pushdown.test 2010-11-11 13:07:41 +0000 @@ -2875,6 +2875,28 @@ select * from t as t1 join t as t2 on t2 drop table t; ####### +# Testcase for bug introduced by initial fix for +# bug#57601 'Optimizer is overly eager to request ordered access.' +# When we turned of 'sorted' for 'descending', we broke QUICK_SELECT_DESC +# which required result to be read as an ordered index access +####### +create table t (pk1 int, pk2 int, primary key(pk1,pk2)) engine = ndb; +insert into t values (1,3), (3,6), (6,9), (9,1); + +explain extended +select * from t as t1 join t as t2 + on t1.pk2 = t2.pk1 + where t1.pk1 != 6 + order by t1.pk1 DESC; + +select * from t as t1 join t as t2 + on t1.pk2 = t2.pk1 + where t1.pk1 != 6 + order by t1.pk1 DESC; + +drop table t; + +####### # Test of varchar query parameteres. ####### === modified file 'sql/abstract_query_plan.cc' --- a/sql/abstract_query_plan.cc 2010-11-08 15:13:37 +0000 +++ b/sql/abstract_query_plan.cc 2010-11-11 13:07:41 +0000 @@ -261,9 +261,11 @@ namespace AQP DBUG_PRINT("info", ("index:%d", get_join_tab()->index)); DBUG_PRINT("info", ("quick:%p", get_join_tab()->quick)); DBUG_PRINT("info", ("select:%p", get_join_tab()->select)); - if (get_join_tab()->select) - DBUG_PRINT("info", ("select->quick:%p", - get_join_tab()->select->quick)); + if (get_join_tab()->select && get_join_tab()->select->quick) + { + DBUG_PRINT("info", ("select->quick->get_type():%d", + get_join_tab()->select->quick->get_type())); + } } @@ -400,6 +402,14 @@ namespace AQP (quick->get_type() == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT) || (quick->get_type() == QUICK_SELECT_I::QS_TYPE_ROR_UNION))); +#if 0 + if (quick->get_type() == QUICK_SELECT_I::QS_TYPE_RANGE_DESC) + { + m_access_type= AT_OTHER; // Multiple PKs are produced by merge + m_other_access_reason = "DESCending ORDER BY can not be pushed while using index"; + } +#endif + // JT_INDEX_MERGE: We have a set of qualifying PKs as root of pushed joins if (quick->index == MAX_KEY) { @@ -460,6 +470,28 @@ namespace AQP {} /** + @return True iff ordered index access is *required* from this operation. + */ + bool Table_access::is_fixed_ordered_index() const + { + const JOIN_TAB* const join_tab= get_join_tab(); + + /* For the QUICK_SELECT_I classes we can disable ordered index usage by + * setting 'QUICK_SELECT_I::sorted = false'. + * However, QUICK_SELECT_I::QS_TYPE_RANGE_DESC is special as its + * internal implementation requires its 'multi-ranges' to be retrieved + * in (descending) sorted order from the underlying table. + */ + if (join_tab->select != NULL && + join_tab->select->quick != NULL) + { + QUICK_SELECT_I *quick= join_tab->select->quick; + return (quick->get_type() == QUICK_SELECT_I::QS_TYPE_RANGE_DESC); + } + return false; + } + + /** @param plan Iterate over fields within this plan. @param field_item Iterate over Item_fields equal to this. */ === modified file 'sql/abstract_query_plan.h' --- a/sql/abstract_query_plan.h 2010-11-08 15:13:37 +0000 +++ b/sql/abstract_query_plan.h 2010-11-11 13:07:41 +0000 @@ -209,6 +209,8 @@ namespace AQP void dbug_print() const; + bool is_fixed_ordered_index() const; + private: /** Backref. to the Join_plan which this Table_access is part of */ === modified file 'sql/ha_ndbcluster.cc' --- a/sql/ha_ndbcluster.cc 2010-11-10 08:01:00 +0000 +++ b/sql/ha_ndbcluster.cc 2010-11-11 13:07:41 +0000 @@ -905,7 +905,7 @@ ndb_pushed_builder_ctx::init_pushability bool ndb_pushed_builder_ctx::is_pushable_as_parent(const AQP::Table_access* table) { - DBUG_ENTER("::is_pushable_as_parent"); + DBUG_ENTER("is_pushable_as_parent"); uint table_no = table->get_access_no(); if ((m_tables[table_no].m_maybe_pushable & PUSHABLE_AS_PARENT) != PUSHABLE_AS_PARENT) { @@ -978,7 +978,7 @@ ndb_pushed_builder_ctx::is_pushable_as_c } // Currently there is a limitation in not allowing LOOKUP - (index)SCAN operations - if (is_lookup_operation(root_type) && access_type==AQP::AT_ORDERED_INDEX_SCAN) + if (access_type==AQP::AT_ORDERED_INDEX_SCAN && is_lookup_operation(root_type)) { EXPLAIN_NO_PUSH("Push of table '%s' as scan-child " "with lookup-root '%s' not implemented", @@ -987,6 +987,15 @@ ndb_pushed_builder_ctx::is_pushable_as_c DBUG_RETURN(false); } + if (access_type==AQP::AT_ORDERED_INDEX_SCAN && join_root()->is_fixed_ordered_index()) + { + // root must be an ordered index scan - Thus it cannot have other scan descendant. + EXPLAIN_NO_PUSH("Push of table '%s' as scan-child " + "with ordered indexscan-root '%s' not implemented", + table->get_table()->alias, join_root()->get_table()->alias); + DBUG_RETURN(false); + } + if (table->get_no_of_key_fields() > ndb_pushed_join::MAX_LINKED_KEYS) { EXPLAIN_NO_PUSH("Can't push table '%s' as child, " @@ -1477,7 +1486,7 @@ ha_ndbcluster::make_pushed_join(ndb_push if (!context.is_pushable_as_child(join_tab, join_items, join_parent)) { - DBUG_PRINT("info", ("Table %d not REF-joined, not pushable", join_cnt)); + DBUG_PRINT("info", ("Table %d not pushable as child", join_cnt)); continue; } /** === modified file 'sql/opt_range.cc' --- a/sql/opt_range.cc 2010-10-20 13:53:02 +0000 +++ b/sql/opt_range.cc 2010-11-11 13:07:41 +0000 @@ -1097,7 +1097,8 @@ SQL_SELECT::~SQL_SELECT() #undef index // Fix for Unixware 7 QUICK_SELECT_I::QUICK_SELECT_I() - :max_used_key_length(0), + :sorted(false), + max_used_key_length(0), used_key_parts(0) {} @@ -1109,7 +1110,6 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(T DBUG_ENTER("QUICK_RANGE_SELECT::QUICK_RANGE_SELECT"); in_ror_merged_scan= 0; - sorted= 0; index= key_nr; head= table; key_part_info= head->key_info[index].key_part; @@ -8804,6 +8804,14 @@ QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUI } +int QUICK_SELECT_DESC::reset(void) +{ + sorted= 1; // 'sorted' index access is required by internals + rev_it.rewind(); + return QUICK_RANGE_SELECT::reset(); +} + + int QUICK_SELECT_DESC::get_next() { DBUG_ENTER("QUICK_SELECT_DESC::get_next"); === modified file 'sql/opt_range.h' --- a/sql/opt_range.h 2010-10-20 13:53:02 +0000 +++ b/sql/opt_range.h 2010-11-11 13:07:41 +0000 @@ -762,7 +762,7 @@ public: int get_type() { return QS_TYPE_RANGE_DESC; } private: bool range_reads_after_key(QUICK_RANGE *range); - int reset(void) { rev_it.rewind(); return QUICK_RANGE_SELECT::reset(); } + int reset(void); List rev_ranges; List_iterator rev_it; uint used_key_parts; --===============0789258762759789815== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/ole.john.aske@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: ole.john.aske@stripped\ # hp0c4rtqf4k3hsy2 # target_branch: file:///net/fimafeng09/export/home/tmp/oleja/mysql\ # /mysql-5.1-telco-7.0-spj-scan-scan/ # testament_sha1: 123ce5945a0cec755360e166df0816058a964019 # timestamp: 2010-11-11 14:07:47 +0100 # source_branch: bzr+ssh://oaske@stripped/bzrroot/server\ # /mysql-5.1-telco-7.0-spj/ # base_revision_id: ole.john.aske@stripped\ # wpwnc5susem0klad # # Begin bundle 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 --===============0789258762759789815==--