| Bug #29011 | Query optimizaion error with NDB Engine | ||
|---|---|---|---|
| Submitted: | 11 Jun 2007 2:57 | Modified: | 28 Dec 2007 11:42 |
| Reporter: | Brian Moon | Email Updates: | |
| Status: | No Feedback | Impact on me: | |
| Category: | MySQL Server: Optimizer | Severity: | S2 (Serious) |
| Version: | 5.0.38, 5.1 | OS: | Linux (Genroo) |
| Assigned to: | Assigned Account | CPU Architecture: | Any |
| Tags: | ndb | ||
[11 Jun 2007 2:57]
Brian Moon
[11 Jun 2007 3:01]
Brian Moon
FYI, here is the explain output from the cluster servers:
Query 1:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: pub_articles
type: ref
possible_keys: PRIMARY,publication_id,publication_id_2
key: publication_id
key_len: 4
ref: const
rows: 10
Extra:
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: article_edition_lookup
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 11
ref: const,const,phewsro.pub_articles.article_id
rows: 1
Extra:
Query 2:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: article_edition_lookup
type: ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 7
ref: const,const
rows: 10
Extra:
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: pub_articles
type: eq_ref
possible_keys: PRIMARY,publication_id,publication_id_2
key: PRIMARY
key_len: 8
ref: phewsro.article_edition_lookup.article_id,const
rows: 1
Extra:
And here is the explain from the server with the exact same data using InnoDB. FYI, the queries both run in .01 or less with InnoDB.
Query 1:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: article_edition_lookup
type: ref
possible_keys: PRIMARY,article_id
key: PRIMARY
key_len: 7
ref: const,const
rows: 215
Extra: Using index
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: pub_articles
type: eq_ref
possible_keys: PRIMARY,publication_id,publication_id_2,expiring_deals
key: PRIMARY
key_len: 8
ref: phewsro.article_edition_lookup.article_id,const
rows: 1
Extra: Using index
Query 2:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: article_edition_lookup
type: ref
possible_keys: PRIMARY,article_id
key: PRIMARY
key_len: 7
ref: const,const
rows: 215
Extra: Using index
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: pub_articles
type: eq_ref
possible_keys: PRIMARY,publication_id,publication_id_2,expiring_deals
key: PRIMARY
key_len: 8
ref: phewsro.article_edition_lookup.article_id,const
rows: 1
Extra: Using index
[11 Jun 2007 10:14]
Sveta Smirnova
test case
Attachment: ndb_bug29011.test (application/octet-stream, text), 3.55 KiB.
[11 Jun 2007 10:17]
Sveta Smirnova
Thank you for the report. Verified using attached test.
[26 Jul 2007 16:54]
Martin Hansson
This problem arises on ndb when there is a ref on the first keypart and a join. Consider: CREATE TABLE t1 (a int, b int, c int, KEY abc( a, b, c )) ENGINE = ndbcluster; CREATE TABLE t3 (a int, b int, c int, KEY abc( a, b, c )); INSERT INTO t1 VALUES ( -1, 1, 1 ), ( 0, 1, 2 ), ( 0, 1, 3 ); INSERT INTO t3 VALUES ( -1, 1, 1 ), ( 0, 1, 2 ), ( 0, 1, 3 ); CREATE TABLE t2 (a int, b int, KEY ab( a, b ), KEY a( a )) ENGINE = ndbcluster; CREATE TABLE t4 (a int, b int, KEY ab( a, b ), KEY a( a )); INSERT INTO t2 VALUES ( 0, 0 ), ( 0, 0 ), ( 0, 0 ), ( 0, 0 ), ( 0, 1 ); INSERT INTO t4 VALUES ( 0, 0 ), ( 0, 0 ), ( 0, 0 ), ( 0, 0 ), ( 0, 1 ); Table t1 is identical with t2, except for the storage engine. Same goes for t2 and t4. Four EXPLAINs follow, a join between t1 and t2, then the same query but with t1 and t2 written in different order. Then it repeats for t3 and t4. mysql> EXPLAIN SELECT * FROM t1 JOIN t2 ON t1.a = t2.a AND t1.b = t2.b WHERE t2.a = 0; +----+-------------+-------+------+---------------+------+---------+---------------------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+---------------------+------+-------------+ | 1 | SIMPLE | t1 | ref | abc | abc | 5 | const | 10 | Using where | | 1 | SIMPLE | t2 | ref | ab,a | ab | 10 | const,bug29011.t1.b | 1 | Using where | +----+-------------+-------+------+---------------+------+---------+---------------------+------+-------------+ 2 rows in set (0.09 sec) mysql> EXPLAIN SELECT * FROM t2 JOIN t1 ON t1.a = t2.a AND t1.b = t2.b WHERE t2.a = 0; +----+-------------+-------+------+---------------+------+---------+---------------------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+---------------------+------+-------------+ | 1 | SIMPLE | t2 | ref | ab,a | ab | 5 | const | 10 | Using where | | 1 | SIMPLE | t1 | ref | abc | abc | 10 | const,bug29011.t2.b | 1 | Using where | +----+-------------+-------+------+---------------+------+---------+---------------------+------+-------------+ 2 rows in set (0.06 sec) mysql> EXPLAIN SELECT * FROM t3 JOIN t4 ON t3.a = t4.a AND t3.b = t4.b WHERE t4.a = 0; +----+-------------+-------+------+---------------+------+---------+---------------------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+---------------------+------+--------------------------+ | 1 | SIMPLE | t3 | ref | abc | abc | 5 | const | 1 | Using where; Using index | | 1 | SIMPLE | t4 | ref | ab,a | ab | 10 | const,bug29011.t3.b | 2 | Using where; Using index | +----+-------------+-------+------+---------------+------+---------+---------------------+------+--------------------------+ 2 rows in set (0.05 sec) mysql> EXPLAIN SELECT * FROM t4 JOIN t3 ON t3.a = t4.a AND t3.b = t4.b WHERE t4.a = 0; +----+-------------+-------+------+---------------+------+---------+---------------------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+---------------------+------+--------------------------+ | 1 | SIMPLE | t3 | ref | abc | abc | 5 | const | 1 | Using where; Using index | | 1 | SIMPLE | t4 | ref | ab,a | ab | 10 | const,bug29011.t3.b | 2 | Using where; Using index | +----+-------------+-------+------+---------------+------+---------+---------------------+------+--------------------------+ 2 rows in set (0.06 sec) The column <rows> for ndb is very suspicius. It says that the first table has 10 rows, whichever table that is.
[27 Jul 2007 16:16]
Martin Hansson
Ref access is used whenever there is a condition of the sort ... WHERE ... field = constant in a query. But since there are no statistics how many row this would return when using ndb, the optimizer instead uses range statistcs information, which comes from ha_ndbcluster::records_in_range. But there are no statistics here either, so this method always returns 10. If there are two keys that can be used, and they appear to have the same cost, the given join order is not altered. According to Pekka of the cluster team, there are some plans to fix range statistics for ndb in 5.1, but not for 5.0.
[27 Jul 2007 16:23]
Martin Hansson
Here is an even simpler test case to show the problem. We have two 'equally good' keys in the optimizer's eyes. The data is only there to make one access obviously cheaper than the other. CREATE TABLE t1( a int, KEY ( a ) ) ENGINE = ndbcluster; INSERT INTO t1 VALUES ( -1 ), ( 0 ), ( 1 ); CREATE TABLE t2( a int, KEY a( a ) ) ENGINE = ndbcluster; INSERT INTO t2 VALUES ( 0 ), ( 0 ), ( 0 ), ( 0 ), ( 1 ); # This tells the engine to use index statistics, but it appears to have no # effect SET NDB_INDEX_STAT_ENABLE = 1; # Note how access order depends on order in query EXPLAIN SELECT * FROM t2 JOIN t1 USING( a ) WHERE t2.a = 0; EXPLAIN SELECT * FROM t1 JOIN t2 USING( a ) WHERE t2.a = 0;
[27 Jul 2007 16:25]
Martin Hansson
Here's my output from the two EXPLAINs EXPLAIN SELECT * FROM t2 JOIN t1 USING( a ) WHERE t2.a = 0; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref a a 5 const 10 Using where with pushed condition 1 SIMPLE t1 ref a a 5 const 10 Using where with pushed condition EXPLAIN SELECT * FROM t1 JOIN t2 USING( a ) WHERE t2.a = 0; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref a a 5 const 10 Using where with pushed condition 1 SIMPLE t2 ref a a 5 const 10 Using where with pushed condition
[28 Nov 2007 11:42]
Martin Hansson
Brian, I'm about to write this off as 'Not a bug' as SET ndb_index_stat_enable=1 fixes the problem on 5.1 in the minimized test case. In order to run the original test case, data must be migrated to 5.1. Are you able to do this? Then please try the above in 5.1.
[29 Dec 2007 0:00]
Bugs System
No feedback was provided for this bug for over a month, so it is being suspended automatically. If you are able to provide the information that was originally requested, please do so and change the status of the bug back to "Open".
