Bug #70038 | Wrong select count distinct with a field included in two-column unique key | ||
---|---|---|---|
Submitted: | 14 Aug 2013 20:47 | Modified: | 19 Nov 2013 17:20 |
Reporter: | Michal Sulik | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: InnoDB storage engine | Severity: | S2 (Serious) |
Version: | 5.5/5.6 | OS: | Any |
Assigned to: | CPU Architecture: | Any | |
Tags: | COUNT DISTINCT, innodb, SELECT, unique key |
[14 Aug 2013 20:47]
Michal Sulik
[14 Aug 2013 21:27]
MySQL Verification Team
Thank you for the bug report. C:\dbs>c:\dbs\5.5\bin\mysql -uroot --port=3550 --prompt="mysql 5.5 > " Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.5.34 Source distribution Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql 5.5 > use test Database changed mysql 5.5 > CREATE TABLE tmp ( -> id int NOT NULL AUTO_INCREMENT, -> a int NOT NULL, -> b int NOT NULL, -> PRIMARY KEY (id), -> UNIQUE KEY ba (b, a) -> ) ENGINE=InnoDB; Query OK, 0 rows affected (0.11 sec) <CUT> mysql 5.5 > mysql 5.5 > -- Returns 5, should return 10. Compare with previous queries. mysql 5.5 > SELECT SQL_NO_CACHE COUNT(DISTINCT b) FROM tmp WHERE a = 1; +-------------------+ | COUNT(DISTINCT b) | +-------------------+ | 5 | +-------------------+ 1 row in set (0.00 sec) mysql 5.5 > alter table tmp drop index ba; Query OK, 0 rows affected (0.11 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql 5.5 > SELECT SQL_NO_CACHE COUNT(DISTINCT b) FROM tmp WHERE a = 1; +-------------------+ | COUNT(DISTINCT b) | +-------------------+ | 10 | +-------------------+ ------------------------------------------------------------------------------- 1 roC:\dbs>c:\dbs\5.6\bin\mysql -uroot --port=3560 --prompt="mysql 5.6 > " Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.6.14 Source distribution Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql 5.6 > use test Database changed mysql 5.6 > CREATE TABLE tmp ( -> id int NOT NULL AUTO_INCREMENT, -> a int NOT NULL, -> b int NOT NULL, -> PRIMARY KEY (id), -> UNIQUE KEY ba (b, a) -> ) ENGINE=InnoDB; Query OK, 0 rows affected (0.38 sec) <CUT> mysql 5.6 > mysql 5.6 > -- Returns 5, should return 10. Compare with previous queries. mysql 5.6 > SELECT SQL_NO_CACHE COUNT(DISTINCT b) FROM tmp WHERE a = 1; +-------------------+ | COUNT(DISTINCT b) | +-------------------+ | 5 | +-------------------+ 1 row in set (0.00 sec) mysql 5.6 > alter table tmp drop index ba; Query OK, 0 rows affected (0.13 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql 5.6 > SELECT SQL_NO_CACHE COUNT(DISTINCT b) FROM tmp WHERE a = 1; +-------------------+ | COUNT(DISTINCT b) | +-------------------+ | 10 | +-------------------+ 1 row in set (0.00 sec)w in set (0.00 sec) --------------------------------------------------------------------------------- C:\dbs>c:\dbs\5.0\bin\mysql -uroot --port=3500 --prompt="mysql 5.0 > " Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.0.97-Win X64 Source distribution Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql 5.0 > use test Database changed mysql 5.0 > CREATE TABLE tmp ( -> id int NOT NULL AUTO_INCREMENT, -> a int NOT NULL, -> b int NOT NULL, -> PRIMARY KEY (id), -> UNIQUE KEY ba (b, a) -> ) ENGINE=InnoDB; Query OK, 0 rows affected (0.08 sec) <CUT> mysql 5.0 > mysql 5.0 > -- Returns 5, should return 10. Compare with previous queries. mysql 5.0 > SELECT SQL_NO_CACHE COUNT(DISTINCT b) FROM tmp WHERE a = 1; +-------------------+ | COUNT(DISTINCT b) | +-------------------+ | 10 | +-------------------+ 1 row in set (0.00 sec)
[19 Aug 2013 13:54]
Patryk Pomykalski
Looks like a bug in QUICK_GROUP_MIN_MAX_SELECT when is_index_scan is true (can skip half of the rows). I think this can fix it: === modified file 'sql/opt_range.cc' --- sql/opt_range.cc 2013-04-30 17:16:37 +0000 +++ sql/opt_range.cc 2013-08-19 13:43:51 +0000 @@ -11039,7 +11039,7 @@ are equality predicates for the key parts after the group, find the first sub-group with the extended prefix. */ - if (!have_min && !have_max && key_infix_len > 0) + if (!have_min && !have_max && key_infix_len > 0 && !is_index_scan) result= file->index_read_map(record, group_prefix, make_prev_keypart_map(real_key_parts), HA_READ_KEY_EXACT);
[19 Aug 2013 19:39]
Patryk Pomykalski
Myisam works, so maybe the above fix is incorrect.
[2 Sep 2013 3:04]
Guangpu Feng
Verified, this bug also affects Percona server 5.5.18.
[17 Sep 2013 6:59]
Guangpu Feng
Any progress?
[17 Sep 2013 12:33]
Mattias Jonsson
The patch is currently in review.
[14 Nov 2013 13:00]
Hartmut Holzgraefe
5.6 (tested with 5.6.14) is even worse, returns 100 on the last query instead of 200: SELECT SQL_NO_CACHE COUNT(DISTINCT b) FROM t1 WHERE a = 1; COUNT(DISTINCT b) -200 +100
[19 Nov 2013 17:20]
Daniel Price
This bug was addressed in a bug fix for a related bug (Oracle Bug#14621190). The fix is noted in 5.5.35, 5.6.15, and 5.7.3 changelogs. The changelog text for the duplicate bug, as noted in the 5.5.35, 5.6.15, and 5.7.3 changelogs, is: When "index_read_map" is called for an exact search and fails to return a record due to non-matching search criteria, the cursor would be positioned on the next record after the searched key. A subsequent call to "index_next " would return the next record instead of returning the previous non-matching row, thereby skipping a record. Thank you for the bug report.