#At file:///home/jonas/src/telco-7.0/ based on revid:jonas@stripped
4475 jonas oreland 2011-06-23
ndb - maintained row-estimates
added:
mysql-test/suite/ndb/r/ndb_row_count.result
mysql-test/suite/ndb/t/ndb_row_count.test
modified:
mysql-test/suite/ndb/r/ndb_condition_pushdown.result
mysql-test/suite/ndb/r/ndb_index_unique.result
sql/ha_ndbcluster.cc
sql/ha_ndbcluster.h
=== modified file 'mysql-test/suite/ndb/r/ndb_condition_pushdown.result'
--- a/mysql-test/suite/ndb/r/ndb_condition_pushdown.result 2011-04-08 13:59:44 +0000
+++ b/mysql-test/suite/ndb/r/ndb_condition_pushdown.result 2011-06-23 12:19:32 +0000
@@ -1910,7 +1910,7 @@ insert into NodeAlias VALUES(null, 8 , '
12:22:26');
explain select * from NodeAlias where (aliasKey LIKE '491803%');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE NodeAlias range NodeAlias_KeyIndex NodeAlias_KeyIndex 48 NULL 2 Using where with pushed condition
+1 SIMPLE NodeAlias range NodeAlias_KeyIndex NodeAlias_KeyIndex 48 NULL 3 Using where with pushed condition
select * from NodeAlias where (aliasKey LIKE '491803%') order by id;
id nodeId displayName aliasKey objectVersion changed
7 8 491803% 491803% 0 2008-03-10 12:22:26
@@ -2105,46 +2105,46 @@ pk x
set engine_condition_pushdown = on;
explain select * from t where x <> "aa";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t ALL NULL NULL NULL NULL 2 Using where
select * from t where x <> "aa";
pk x
0 a
explain select * from t where "aa" <> x;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t ALL NULL NULL NULL NULL 2 Using where
select * from t where "aa" <> x;
pk x
0 a
explain select * from t where x between "" and "bb";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t ALL NULL NULL NULL NULL 2 Using where
select * from t where x between "" and "bb";
pk x
0 a
explain select * from t where x not between "" and "bb";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t ALL NULL NULL NULL NULL 2 Using where
select * from t where x not between "" and "bb";
pk x
explain select * from t where x in ("","aa","b");
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t ALL NULL NULL NULL NULL 2 Using where
select * from t where x in ("","aa","b");
pk x
explain select * from t where x not in ("","aa","b");
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t ALL NULL NULL NULL NULL 1 Using where
+1 SIMPLE t ALL NULL NULL NULL NULL 2 Using where
select * from t where x not in ("","aa","b");
pk x
0 a
explain select * from t where x like "aa?";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t ALL NULL NULL NULL NULL 1 Using where with pushed condition
+1 SIMPLE t ALL NULL NULL NULL NULL 2 Using where with pushed condition
select * from t where x like "aa?";
pk x
explain select * from t where x not like "aa?";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t ALL NULL NULL NULL NULL 1 Using where with pushed condition
+1 SIMPLE t ALL NULL NULL NULL NULL 2 Using where with pushed condition
select * from t where x not like "aa?";
pk x
0 a
@@ -2201,8 +2201,8 @@ primary key (`a`,`b`)
) engine = ndb;
explain extended select * from tx join tx as t2 on tx.c=1 where t2.c=1;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE tx ALL NULL NULL NULL NULL 0 0.00 Using where with pushed condition: (`test`.`tx`.`c` = 1)
-1 SIMPLE t2 ALL NULL NULL NULL NULL 0 0.00 Using where with pushed condition: (`test`.`t2`.`c` = 1); Using join buffer
+1 SIMPLE tx ALL NULL NULL NULL NULL 2 100.00 Using where with pushed condition: (`test`.`tx`.`c` = 1)
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where with pushed condition: (`test`.`t2`.`c` = 1); Using join buffer
Warnings:
Note 1003 select `test`.`tx`.`a` AS `a`,`test`.`tx`.`b` AS `b`,`test`.`tx`.`c` AS `c`,`test`.`tx`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`tx` join `test`.`tx` `t2` where ((`test`.`tx`.`c` = 1) and (`test`.`t2`.`c` = 1))
explain extended
@@ -2212,7 +2212,7 @@ join tx as t2 on t2.a = tx.a and t2.b =
join tx as t3 on t3.a = tx.c and t3.b = tx.d
join tx as t4 on t4.a = t3.b and t4.b = t2.c;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE tx ALL PRIMARY NULL NULL NULL 0 0.00
+1 SIMPLE tx ALL PRIMARY NULL NULL NULL 2 100.00
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 8 test.tx.a,test.tx.b 1 100.00
1 SIMPLE t3 eq_ref PRIMARY PRIMARY 8 test.tx.c,test.tx.d 1 100.00
1 SIMPLE t4 eq_ref PRIMARY PRIMARY 8 test.tx.d,test.t2.c 1 100.00
@@ -2231,8 +2231,8 @@ Warnings:
Note 1003 select `test`.`t2`.`c` AS `c`,count(distinct `test`.`t2`.`a`) AS `count(distinct t2.a)` from `test`.`tx` join `test`.`tx` `t2` where ((`test`.`tx`.`b` = `test`.`t2`.`d`) and (`test`.`tx`.`a` = `test`.`t2`.`c`) and (`test`.`t2`.`a` = 4)) group by `test`.`t2`.`c`
explain extended select * from tx join tx as t2 on tx.c=1 where t2.c=1;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE tx ALL NULL NULL NULL NULL 0 0.00 Using where with pushed condition: (`test`.`tx`.`c` = 1)
-1 SIMPLE t2 ALL NULL NULL NULL NULL 0 0.00 Using where with pushed condition: (`test`.`t2`.`c` = 1); Using join buffer
+1 SIMPLE tx ALL NULL NULL NULL NULL 2 100.00 Using where with pushed condition: (`test`.`tx`.`c` = 1)
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where with pushed condition: (`test`.`t2`.`c` = 1); Using join buffer
Warnings:
Note 1003 select `test`.`tx`.`a` AS `a`,`test`.`tx`.`b` AS `b`,`test`.`tx`.`c` AS `c`,`test`.`tx`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`tx` join `test`.`tx` `t2` where ((`test`.`tx`.`c` = 1) and (`test`.`t2`.`c` = 1))
explain extended
@@ -2256,7 +2256,7 @@ explain extended
select * from t where exists
(select * from t as subq where subq.i=3 and t.i=3);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t ALL NULL NULL NULL NULL 4 50.00 Using where
+1 PRIMARY t ALL NULL NULL NULL NULL 4 100.00 Using where
2 DEPENDENT SUBQUERY subq ALL NULL NULL NULL NULL 4 100.00 Using where with pushed condition: (`test`.`subq`.`i` = 3)
Warnings:
Note 1276 Field or reference 'test.t.i' of SELECT #2 was resolved in SELECT #1
@@ -2266,7 +2266,7 @@ select * from t where exists
(select * from subq where subq.i=3 and t.i=3);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t ALL NULL NULL NULL NULL 4 100.00 Using where
-2 DEPENDENT SUBQUERY subq ALL NULL NULL NULL NULL 4 50.00 Using where with pushed condition: (`test`.`subq`.`i` = 3)
+2 DEPENDENT SUBQUERY subq ALL NULL NULL NULL NULL 4 100.00 Using where with pushed condition: (`test`.`subq`.`i` = 3)
Warnings:
Note 1276 Field or reference 'test.t.i' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t`.`pk` AS `pk`,`test`.`t`.`i` AS `i` from `test`.`t` where exists(select 1 from `test`.`subq` where ((`test`.`subq`.`i` = 3) and (`test`.`t`.`i` = 3)))
=== modified file 'mysql-test/suite/ndb/r/ndb_index_unique.result'
--- a/mysql-test/suite/ndb/r/ndb_index_unique.result 2011-02-28 10:42:04 +0000
+++ b/mysql-test/suite/ndb/r/ndb_index_unique.result 2011-06-23 12:19:32 +0000
@@ -185,7 +185,7 @@ set @old_ecpd = @@session.engine_conditi
set engine_condition_pushdown = true;
explain select * from t2 where (b = 3 OR b = 5) AND c IS NULL AND a < 9 order by a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range PRIMARY,b PRIMARY 4 NULL 2 Using where with pushed condition
+1 SIMPLE t2 range PRIMARY,b b 9 NULL 2 Using where with pushed condition; Using filesort
select * from t2 where (b = 3 OR b = 5) AND c IS NULL AND a < 9 order by a;
a b c
3 3 NULL
=== added file 'mysql-test/suite/ndb/r/ndb_row_count.result'
--- a/mysql-test/suite/ndb/r/ndb_row_count.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/r/ndb_row_count.result 2011-06-23 12:19:32 +0000
@@ -0,0 +1,115 @@
+create table t1(
+a int primary key
+) engine=ndbcluster;
+insert into t1 values
+(00),(01),(02),(03),(04),(05),(06),(07),(08),(09),
+(10),(11),(12),(13),(14),(15),(16),(17),(18),(19),
+(20),(21),(22),(23),(24),(25),(26),(27),(28),(29),
+(30),(31),(32),(33),(34),(35),(36),(37),(38),(39),
+(40),(41),(42),(43),(44),(45),(46),(47),(48),(49),
+(50),(51),(52),(53),(54),(55),(56),(57),(58),(59),
+(60),(61),(62),(63),(64),(65),(66),(67),(68),(69),
+(70),(71),(72),(73),(74),(75),(76),(77),(78),(79),
+(80),(81),(82),(83),(84),(85),(86),(87),(88),(89),
+(90),(91),(92),(93),(94),(95),(96),(97),(98),(99);
+
+# expected result 0 roundtrips - read stats from share
+explain extended select * from t1 where a < 100;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 10 100.00 Using where with pushed condition: (`test`.`t1`.`a` < 100)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` < 100)
+@ndb_execute_count:=VARIABLE_VALUE-@ndb_init_execute_count
+0
+insert into t1 select a+100 from t1;
+
+# expected result 0 roundtrips - read stats from share
+explain extended select * from t1 where a < 100;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 20 100.00 Using where with pushed condition: (`test`.`t1`.`a` < 100)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` < 100)
+@ndb_execute_count:=VARIABLE_VALUE-@ndb_init_execute_count
+0
+delete from t1 where a >= 100;
+
+# expected result 0 roundtrips - read stats from share
+explain extended select * from t1 where a < 100;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 10 100.00 Using where with pushed condition: (`test`.`t1`.`a` < 100)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` < 100)
+@ndb_execute_count:=VARIABLE_VALUE-@ndb_init_execute_count
+0
+begin;
+insert into t1 select a+100 from t1;
+commit;
+
+# expected result 0 roundtrips - read stats from share
+explain extended select * from t1 where a < 100;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 20 100.00 Using where with pushed condition: (`test`.`t1`.`a` < 100)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` < 100)
+@ndb_execute_count:=VARIABLE_VALUE-@ndb_init_execute_count
+0
+begin;
+delete from t1 where a >= 100;
+commit;
+
+# expected result 0 roundtrips - read stats from share
+explain extended select * from t1 where a < 100;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 10 100.00 Using where with pushed condition: (`test`.`t1`.`a` < 100)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` < 100)
+@ndb_execute_count:=VARIABLE_VALUE-@ndb_init_execute_count
+0
+begin;
+insert into t1 select a+100 from t1;
+rollback;
+
+# expected result 0 roundtrips - read stats from share
+explain extended select * from t1 where a < 100;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 10 100.00 Using where with pushed condition: (`test`.`t1`.`a` < 100)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` < 100)
+@ndb_execute_count:=VARIABLE_VALUE-@ndb_init_execute_count
+0
+begin;
+delete from t1 where a <= 100;
+rollback;
+
+# expected result 0 roundtrips - read stats from share
+explain extended select * from t1 where a < 100;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 10 100.00 Using where with pushed condition: (`test`.`t1`.`a` < 100)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` < 100)
+@ndb_execute_count:=VARIABLE_VALUE-@ndb_init_execute_count
+0
+insert into t1 select a from t1;
+ERROR 23000: Can't write; duplicate key in table 't1'
+
+# expected result 0 roundtrips - read stats from share
+explain extended select * from t1 where a < 100;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 10 100.00 Using where with pushed condition: (`test`.`t1`.`a` < 100)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` < 100)
+@ndb_execute_count:=VARIABLE_VALUE-@ndb_init_execute_count
+0
+begin;
+insert into t1 select a from t1;
+ERROR 23000: Can't write; duplicate key in table 't1'
+
+# expected result 0 roundtrips - read stats from share
+explain extended select * from t1 where a < 100;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 10 100.00 Using where with pushed condition: (`test`.`t1`.`a` < 100)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` < 100)
+@ndb_execute_count:=VARIABLE_VALUE-@ndb_init_execute_count
+0
+drop table t1;
=== added file 'mysql-test/suite/ndb/t/ndb_row_count.test'
--- a/mysql-test/suite/ndb/t/ndb_row_count.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_row_count.test 2011-06-23 12:19:32 +0000
@@ -0,0 +1,100 @@
+-- source include/have_ndb.inc
+
+create table t1(
+ a int primary key
+) engine=ndbcluster;
+
+insert into t1 values
+(00),(01),(02),(03),(04),(05),(06),(07),(08),(09),
+(10),(11),(12),(13),(14),(15),(16),(17),(18),(19),
+(20),(21),(22),(23),(24),(25),(26),(27),(28),(29),
+(30),(31),(32),(33),(34),(35),(36),(37),(38),(39),
+(40),(41),(42),(43),(44),(45),(46),(47),(48),(49),
+(50),(51),(52),(53),(54),(55),(56),(57),(58),(59),
+(60),(61),(62),(63),(64),(65),(66),(67),(68),(69),
+(70),(71),(72),(73),(74),(75),(76),(77),(78),(79),
+(80),(81),(82),(83),(84),(85),(86),(87),(88),(89),
+(90),(91),(92),(93),(94),(95),(96),(97),(98),(99);
+
+--echo
+--echo # expected result 0 roundtrips - read stats from share
+--source suite/ndb/include/ndb_init_execute_count.inc
+explain extended select * from t1 where a < 100;
+--source suite/ndb/include/ndb_execute_count.inc
+
+insert into t1 select a+100 from t1;
+
+--echo
+--echo # expected result 0 roundtrips - read stats from share
+--source suite/ndb/include/ndb_init_execute_count.inc
+explain extended select * from t1 where a < 100;
+--source suite/ndb/include/ndb_execute_count.inc
+
+delete from t1 where a >= 100;
+
+--echo
+--echo # expected result 0 roundtrips - read stats from share
+--source suite/ndb/include/ndb_init_execute_count.inc
+explain extended select * from t1 where a < 100;
+--source suite/ndb/include/ndb_execute_count.inc
+
+begin;
+insert into t1 select a+100 from t1;
+commit;
+
+--echo
+--echo # expected result 0 roundtrips - read stats from share
+--source suite/ndb/include/ndb_init_execute_count.inc
+explain extended select * from t1 where a < 100;
+--source suite/ndb/include/ndb_execute_count.inc
+
+begin;
+delete from t1 where a >= 100;
+commit;
+
+--echo
+--echo # expected result 0 roundtrips - read stats from share
+--source suite/ndb/include/ndb_init_execute_count.inc
+explain extended select * from t1 where a < 100;
+--source suite/ndb/include/ndb_execute_count.inc
+
+begin;
+insert into t1 select a+100 from t1;
+rollback;
+
+--echo
+--echo # expected result 0 roundtrips - read stats from share
+--source suite/ndb/include/ndb_init_execute_count.inc
+explain extended select * from t1 where a < 100;
+--source suite/ndb/include/ndb_execute_count.inc
+
+begin;
+delete from t1 where a <= 100;
+rollback;
+
+--echo
+--echo # expected result 0 roundtrips - read stats from share
+--source suite/ndb/include/ndb_init_execute_count.inc
+explain extended select * from t1 where a < 100;
+--source suite/ndb/include/ndb_execute_count.inc
+
+--error ER_DUP_KEY
+insert into t1 select a from t1;
+
+--echo
+--echo # expected result 0 roundtrips - read stats from share
+--source suite/ndb/include/ndb_init_execute_count.inc
+explain extended select * from t1 where a < 100;
+--source suite/ndb/include/ndb_execute_count.inc
+
+begin;
+--error ER_DUP_KEY
+insert into t1 select a from t1;
+
+--echo
+--echo # expected result 0 roundtrips - read stats from share
+--source suite/ndb/include/ndb_init_execute_count.inc
+explain extended select * from t1 where a < 100;
+--source suite/ndb/include/ndb_execute_count.inc
+
+drop table t1;
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc 2011-06-22 20:01:17 +0000
+++ b/sql/ha_ndbcluster.cc 2011-06-23 12:19:32 +0000
@@ -405,6 +405,9 @@ HASH ndbcluster_open_tables;
static uchar *ndbcluster_get_key(NDB_SHARE *share, size_t *length,
my_bool not_used __attribute__((unused)));
+static void modify_shared_stats(NDB_SHARE *share,
+ Ndb_local_table_statistics *local_stat);
+
static int ndb_get_table_statistics(THD *thd, ha_ndbcluster*, bool, Ndb*,
const NdbRecord *, struct Ndb_statistics *,
bool have_lock= FALSE,
@@ -6059,27 +6062,50 @@ int ha_ndbcluster::info(uint flag)
if (!thd)
thd= current_thd;
DBUG_PRINT("info", ("HA_STATUS_VARIABLE"));
- if ((flag & HA_STATUS_NO_LOCK) &&
- !THDVAR(thd, use_exact_count))
- {
- if (thd->lex->sql_command != SQLCOM_SHOW_TABLE_STATUS &&
- thd->lex->sql_command != SQLCOM_SHOW_KEYS)
- {
- /*
- just use whatever stats we have however,
- optimizer behaves strangely if we return few rows
- */
- if (stats.records < 2)
- stats.records= 2;
- break;
- }
- }
+
if (!m_table_info)
{
if ((my_errno= check_ndb_connection(thd)))
DBUG_RETURN(my_errno);
}
- result= update_stats(thd, 1);
+
+ /*
+ May need to update local copy of statistics in
+ 'm_table_info', either directly from datanodes,
+ or from shared (mutex protected) cached copy, if:
+ 1) 'use_exact_count' has been set (by config or user).
+ 2) HA_STATUS_NO_LOCK -> read from shared cached copy.
+ 3) Local copy is invalid.
+ */
+ bool exact_count= THDVAR(thd, use_exact_count);
+ if (exact_count || // 1)
+ !(flag & HA_STATUS_NO_LOCK) || // 2)
+ m_table_info == NULL || // 3)
+ m_table_info->records == ~(ha_rows)0) // 3)
+ {
+ result= update_stats(thd, (exact_count || !(flag & HA_STATUS_NO_LOCK)));
+ if (result)
+ DBUG_RETURN(result);
+ }
+ /* Read from local statistics, fast and fuzzy, wo/ locks */
+ else
+ {
+ DBUG_ASSERT(m_table_info->records != ~(ha_rows)0);
+ stats.records= m_table_info->records +
+ m_table_info->no_uncommitted_rows_count;
+ }
+
+ if (thd->lex->sql_command != SQLCOM_SHOW_TABLE_STATUS &&
+ thd->lex->sql_command != SQLCOM_SHOW_KEYS)
+ {
+ /*
+ just use whatever stats we have. However,
+ optimizer interprets the values 0 and 1 as EXACT:
+ -> < 2 should not be returned.
+ */
+ if (stats.records < 2)
+ stats.records= 2;
+ }
break;
}
/* RPK moved to variable part */
@@ -6641,7 +6667,18 @@ int ha_ndbcluster::start_statement(THD *
there is more than one handler involved, execute deferal
not possible
*/
+ ha_ndbcluster* handler = thd_ndb->m_handler;
thd_ndb->m_handler= NULL;
+ if (handler != NULL)
+ {
+ /**
+ * If we initially belived that this could be run
+ * using execute deferal...but changed out mind
+ * add handler to thd_ndb->open_tables like it would
+ * have done "normally"
+ */
+ add_handler_to_open_tables(thd, thd_ndb, handler);
+ }
}
if (!trans && table_count == 0)
{
@@ -6687,6 +6724,57 @@ int ha_ndbcluster::start_statement(THD *
DBUG_RETURN(0);
}
+int
+ha_ndbcluster::add_handler_to_open_tables(THD *thd,
+ Thd_ndb *thd_ndb,
+ ha_ndbcluster* handler)
+{
+ DBUG_ENTER("ha_ndbcluster::add_handler_to_open_tables");
+ DBUG_PRINT("info", ("Adding %s", handler->m_share->key));
+
+ /**
+ * thd_ndb->open_tables is only used iff thd_ndb->m_handler is not
+ */
+ DBUG_ASSERT(thd_ndb->m_handler == NULL);
+ const void *key= handler->m_share;
+ HASH_SEARCH_STATE state;
+ THD_NDB_SHARE *thd_ndb_share=
+ (THD_NDB_SHARE*)my_hash_first(&thd_ndb->open_tables,
+ (const uchar *)&key, sizeof(key),
+ &state);
+ while (thd_ndb_share && thd_ndb_share->key != key)
+ {
+ thd_ndb_share=
+ (THD_NDB_SHARE*)my_hash_next(&thd_ndb->open_tables,
+ (const uchar *)&key, sizeof(key),
+ &state);
+ }
+ if (thd_ndb_share == 0)
+ {
+ thd_ndb_share= (THD_NDB_SHARE *) alloc_root(&thd->transaction.mem_root,
+ sizeof(THD_NDB_SHARE));
+ if (!thd_ndb_share)
+ {
+ mem_alloc_error(sizeof(THD_NDB_SHARE));
+ DBUG_RETURN(1);
+ }
+ thd_ndb_share->key= key;
+ thd_ndb_share->stat.last_count= thd_ndb->count;
+ thd_ndb_share->stat.no_uncommitted_rows_count= 0;
+ thd_ndb_share->stat.records= ~(ha_rows)0;
+ my_hash_insert(&thd_ndb->open_tables, (uchar *)thd_ndb_share);
+ }
+ else if (thd_ndb_share->stat.last_count != thd_ndb->count)
+ {
+ thd_ndb_share->stat.last_count= thd_ndb->count;
+ thd_ndb_share->stat.no_uncommitted_rows_count= 0;
+ thd_ndb_share->stat.records= ~(ha_rows)0;
+ }
+
+ handler->m_table_info= &thd_ndb_share->stat;
+ DBUG_RETURN(0);
+}
+
int ha_ndbcluster::init_handler_for_statement(THD *thd)
{
/*
@@ -6720,45 +6808,11 @@ int ha_ndbcluster::init_handler_for_stat
}
#endif
- if (thd_options(thd) & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
+ int ret = 0;
+ if (thd_ndb->m_handler == 0)
{
- const void *key= m_table;
- HASH_SEARCH_STATE state;
- THD_NDB_SHARE *thd_ndb_share=
- (THD_NDB_SHARE*)my_hash_first(&thd_ndb->open_tables,
- (const uchar *)&key, sizeof(key),
- &state);
- while (thd_ndb_share && thd_ndb_share->key != key)
- {
- thd_ndb_share=
- (THD_NDB_SHARE*)my_hash_next(&thd_ndb->open_tables,
- (const uchar *)&key, sizeof(key),
- &state);
- }
- if (thd_ndb_share == 0)
- {
- thd_ndb_share= (THD_NDB_SHARE *) alloc_root(&thd->transaction.mem_root,
- sizeof(THD_NDB_SHARE));
- if (!thd_ndb_share)
- {
- mem_alloc_error(sizeof(THD_NDB_SHARE));
- DBUG_RETURN(1);
- }
- thd_ndb_share->key= key;
- thd_ndb_share->stat.last_count= thd_ndb->count;
- thd_ndb_share->stat.no_uncommitted_rows_count= 0;
- thd_ndb_share->stat.records= ~(ha_rows)0;
- my_hash_insert(&thd_ndb->open_tables, (uchar *)thd_ndb_share);
- }
- else if (thd_ndb_share->stat.last_count != thd_ndb->count)
- {
- thd_ndb_share->stat.last_count= thd_ndb->count;
- thd_ndb_share->stat.no_uncommitted_rows_count= 0;
- thd_ndb_share->stat.records= ~(ha_rows)0;
- }
- DBUG_PRINT("exit", ("thd_ndb_share: 0x%lx key: 0x%lx",
- (long) thd_ndb_share, (long) key));
- m_table_info= &thd_ndb_share->stat;
+ DBUG_ASSERT(m_share);
+ ret = add_handler_to_open_tables(thd, thd_ndb, this);
}
else
{
@@ -6768,7 +6822,7 @@ int ha_ndbcluster::init_handler_for_stat
stat.records= ~(ha_rows)0;
m_table_info= &stat;
}
- DBUG_RETURN(0);
+ DBUG_RETURN(ret);
}
int ha_ndbcluster::external_lock(THD *thd, int lock_type)
@@ -7140,6 +7194,25 @@ int ndbcluster_commit(handlerton *hton,
if (res != -1)
ndbcluster_print_error(res, error_op);
}
+ else
+ {
+ /* Update shared statistics for tables inserted into / deleted from*/
+ if (thd_ndb->m_handler && // Autocommit Txn
+ thd_ndb->m_handler->m_share &&
+ thd_ndb->m_handler->m_table_info)
+ {
+ modify_shared_stats(thd_ndb->m_handler->m_share, thd_ndb->m_handler->m_table_info);
+ }
+
+ /* Manual commit: Update all affected NDB_SHAREs found in 'open_tables' */
+ for (uint i= 0; i<thd_ndb->open_tables.records; i++)
+ {
+ THD_NDB_SHARE *thd_share=
+ (THD_NDB_SHARE*)my_hash_element(&thd_ndb->open_tables, i);
+ modify_shared_stats((NDB_SHARE*)thd_share->key, &thd_share->stat);
+ }
+ }
+
ndb->closeTransaction(trans);
thd_ndb->trans= NULL;
thd_ndb->m_handler= NULL;
@@ -12313,8 +12386,22 @@ int ha_ndbcluster::update_stats(THD *thd
struct Ndb_statistics stat;
Thd_ndb *thd_ndb= get_thd_ndb(thd);
DBUG_ENTER("ha_ndbcluster::update_stats");
- if (do_read_stat || !m_share)
+ do
{
+ if (m_share && !do_read_stat)
+ {
+ pthread_mutex_lock(&m_share->mutex);
+ stat= m_share->stat;
+ pthread_mutex_unlock(&m_share->mutex);
+
+ DBUG_ASSERT(stat.row_count != ~(ha_rows)0); // should never be invalid
+
+ /* Accept shared cached statistics if row_count is valid. */
+ if (stat.row_count != ~(ha_rows)0)
+ break;
+ }
+
+ /* Request statistics from datanodes */
Ndb *ndb= thd_ndb->ndb;
if (ndb->setDatabaseName(m_dbname))
{
@@ -12326,25 +12413,25 @@ int ha_ndbcluster::update_stats(THD *thd
{
DBUG_RETURN(err);
}
+
+ /* Update shared statistics with fresh data */
if (m_share)
{
pthread_mutex_lock(&m_share->mutex);
m_share->stat= stat;
pthread_mutex_unlock(&m_share->mutex);
}
+ break;
}
- else
+ while(0);
+
+ int no_uncommitted_rows_count= 0;
+ if (m_table_info && !thd_ndb->m_error)
{
- pthread_mutex_lock(&m_share->mutex);
- stat= m_share->stat;
- pthread_mutex_unlock(&m_share->mutex);
+ m_table_info->records= stat.row_count;
+ m_table_info->last_count= thd_ndb->count;
+ no_uncommitted_rows_count= m_table_info->no_uncommitted_rows_count;
}
- struct Ndb_local_table_statistics *local_info= m_table_info;
- int no_uncommitted_rows_count;
- if (thd_ndb->m_error || !local_info)
- no_uncommitted_rows_count= 0;
- else
- no_uncommitted_rows_count= local_info->no_uncommitted_rows_count;
stats.mean_rec_length= stat.row_size;
stats.data_file_length= stat.fragment_memory;
stats.records= stat.row_count + no_uncommitted_rows_count;
@@ -12364,6 +12451,35 @@ int ha_ndbcluster::update_stats(THD *thd
DBUG_RETURN(0);
}
+/**
+ Update 'row_count' in shared table statistcs if any rows where
+ inserted/deleted by the local transaction related to specified
+ 'local_stat'.
+ Should be called when transaction has succesfully commited its changes.
+*/
+static
+void modify_shared_stats(NDB_SHARE *share,
+ Ndb_local_table_statistics *local_stat)
+{
+ if (local_stat->no_uncommitted_rows_count)
+ {
+ pthread_mutex_lock(&share->mutex);
+ DBUG_ASSERT(share->stat.row_count != ~(ha_rows)0);// should never be invalid
+ if (share->stat.row_count != ~(ha_rows)0)
+ {
+ DBUG_PRINT("info", ("Update row_count for %s, row_count: %lu, with:%d",
+ share->table_name, (ulong) share->stat.row_count,
+ local_stat->no_uncommitted_rows_count));
+ share->stat.row_count=
+ ((Int64)share->stat.row_count+local_stat->no_uncommitted_rows_count > 0)
+ ? share->stat.row_count+local_stat->no_uncommitted_rows_count
+ : 0;
+ }
+ pthread_mutex_unlock(&share->mutex);
+ local_stat->no_uncommitted_rows_count= 0;
+ }
+}
+
/* If part_id contains a legal partition id, ndbstat returns the
partition-statistics pertaining to that partition only.
Otherwise, it returns the table-statistics,
=== modified file 'sql/ha_ndbcluster.h'
--- a/sql/ha_ndbcluster.h 2011-06-22 08:34:17 +0000
+++ b/sql/ha_ndbcluster.h 2011-06-23 12:19:32 +0000
@@ -985,6 +985,7 @@ private:
int update_stats(THD *thd, bool do_read_stat, bool have_lock= FALSE,
uint part_id= ~(uint)0);
+ int add_handler_to_open_tables(THD*, Thd_ndb*, ha_ndbcluster* handler);
};
int ndbcluster_discover(THD* thd, const char* dbname, const char* name,
Attachment: [text/bzr-bundle] bzr/jonas@mysql.com-20110623121932-ir7c5dw5cm2k05vm.bundle
| Thread |
|---|
| • bzr commit into mysql-5.1-telco-7.0 branch (jonas:4475) | jonas oreland | 23 Jun |