[MDEV-8553] Impossible WHERE a!=a Created: 2015-07-28  Updated: 2019-05-10  Resolved: 2019-05-10

Status: Closed
Project: MariaDB Server
Component/s: Optimizer
Fix Version/s: 10.4.5

Type: Task Priority: Minor
Reporter: Daniel Black Assignee: Sergei Petrunia
Resolution: Fixed Votes: 0
Labels: upstream-fixed


 Description   

from 5.5.44

| gpd | CREATE TABLE `gpd` (
  `recID` int(11) NOT NULL AUTO_INCREMENT,
  `sessionID` int(11) DEFAULT NULL,
  `time` decimal(12,0) DEFAULT NULL,
  `position` int(11) DEFAULT NULL,
  `angle` int(11) DEFAULT NULL,
  `velocity` decimal(12,6) DEFAULT NULL,
  `acceleration` decimal(12,6) DEFAULT NULL,
  `forcePlate` decimal(12,6) DEFAULT '0.000000',
  PRIMARY KEY (`recID`),
  KEY `sessionID` (`sessionID`)
) ENGINE=InnoDB AUTO_INCREMENT=464380557 DEFAULT CHARSET=latin1 |

Queries like this should end up as 'Impossible Where' the same as 'WHERE 0' is used. Same with > or < as an operator.

explain SELECT 1 FROM `gpd` WHERE `gpd`.`sessionID` != `gpd`.`sessionID`;
+------+-------------+---------------+-------+---------------+-----------+---------+------+-----------+--------------------------+
| id   | select_type | table         | type  | possible_keys | key       | key_len | ref  | rows      | Extra                    |
+------+-------------+---------------+-------+---------------+-----------+---------+------+-----------+--------------------------+
|    1 | SIMPLE      | gpd           | index | NULL          | sessionID | 5       | NULL | 461252463 | Using where; Using index |

I came across this and was potentially generated from the depths of an ORM (sqlalchemy)



 Comments   
Comment by Jabbar Memon [ 2017-03-12 ]

hello sir,

I am postgraduate at Dhirubhai Ambani Institute of Information and Communication technology,Ahmedabad.I'd like to contribute to this project in the GSOC 2017. I have a good knowledge about Sql,Postgresql and little bit about mariadb..I want more details about this issue..

Thanks
Jabbar Memon

Comment by Daniel Black [ 2017-03-12 ]

In SQL terms the condition col1!=col1 will always be false. The same with col1<col1 and col1>col1. Rather than have mariadb engine look through the entire table to validate this, the optimizer can include the code that checks for these impossible conditions and generate the "Impossible Where" warning as well as effectively replace the condition with FALSE.

Like wise a col1=col1 condition is almost always true. Requiring the mariadb server to fetch all rows to validate this would be a waste of time. Replacing this with TRUE would enable the query optimiser to choose a better plan. Using your SQL knowledge, when is col1=col1 false?

Comment by Jabbar Memon [ 2017-03-13 ]

Hello sir,
i am running this query select * from gpd where gpd.sessionID!=gpd.sessionID; but it is showing no record.can plz help what to do now i am confused little bit.

Thank You
Jabbar Memon

Comment by Sergei Petrunia [ 2017-03-15 ]

Points to consider:

  • every kind of processing adds some overhead. If we make the optimizer too smart, people start complaining about simple queries having too much overhead.
  • how broad should this be? Should it just look for col1!=col1 , or some other forms should be checked for, also?
Comment by Daniel Black [ 2017-03-15 ]

I suspect the comparison of the two sides of the expression to see if they are the same table/column will be simple leaving the longer case of doing the >, <, and != (to be handled the same) and the = case which requires checking if the column can be NULL checks to determine which simplification is needed.

Comment by Jabbar Memon [ 2017-03-18 ]

thank you for the help but if the table is same then we dont have to check == and if the column is null so we can make that column primary key so that will reduce the error i think...

Thank You
Jabbar Memon

Comment by Daniel Black [ 2017-03-23 ]

Given the number of other proposals being received, the lower importance of this task, and the limited mentor resources I'm removing the gsoc label for this year. Thanks for your interest and apologies for changing my mind on this task.

Comment by Daniel Black [ 2018-12-16 ]

psergey as it turns out this is very easy and virtually no impact for reasons described on https://github.com/MariaDB/server/pull/1027

Comment by Daniel Black [ 2018-12-16 ]

Fixed in MySQL-8.0

----------- MYSQLTEST OUTPUT START -----------
 
CREATE TABLE t1 (a TINYINT NOT NULL, KEY(a));
INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
SELECT VERSION();
VERSION()
8.0.13
EXPLAIN SELECT * FROM t1 WHERE a!=a;
id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	filtered	Extra
1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
Warnings:
Note	1003	/* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
EXPLAIN SELECT * FROM t1 WHERE a>a;
id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	filtered	Extra
1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
Warnings:
Note	1003	/* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
EXPLAIN SELECT * FROM t1 WHERE a<a;
id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	filtered	Extra
1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
Warnings:
Note	1003	/* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
EXPLAIN SELECT * FROM t1 WHERE NOT a=a;
id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	filtered	Extra
1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE

Comment by Igor Babaev [ 2018-12-17 ]

Daniel,
For the above examples the current 10.4 returns:

MariaDB [test]> CREATE TABLE t1 (a TINYINT NOT NULL, KEY(a));
Query OK, 0 rows affected (0.025 sec)
 
MariaDB [test]> INSERT INTO t1 VALUES (1),(2),(3),(4),(5);
Query OK, 5 rows affected (0.011 sec)
Records: 5  Duplicates: 0  Warnings: 0
 
MariaDB [test]> EXPLAIN SELECT * FROM t1 WHERE a<a;
+------+-------------+-------+------+---------------+------+---------+------+------+------------------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra            |
+------+-------------+-------+------+---------------+------+---------+------+------+------------------+
|    1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible WHERE |
+------+-------------+-------+------+---------------+------+---------+------+------+------------------+

There is no wonder, because the MySQL code that processes a<a is practically the same as in MariaDB

Comment by Daniel Black [ 2018-12-18 ]

Quite right MySQL and MariaDB are behaving identical. I was getting confused on table definitions too.

Remove the `NOT NULL` from the column definition is where the 'Impossible WHERE' is no longer detected. Adding an index just changes plan to 'Using index'. Also the `WHERE not (a!=a)` is a condition that doesn't result in 'Select tables optimized away'. The updated PR corrects both of these to use the more optimal query plan.

Summary of existing MariaDB behaviour (and can switch to MySQL-8.0.13 quickly):
https://dbfiddle.uk/?rdbms=mariadb_10.3&fiddle=f4b57e5eb6b34bd47d2d71a8f9bde3cf

Comment by Igor Babaev [ 2019-04-04 ]

Hi Daniel,
The patch is ok.

Comment by Sergey Vojtovich [ 2019-05-10 ]

PR have been applied.

Generated at Thu Feb 08 07:28:01 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.