MySQL问题与选择查询和'顺序由'条款

时间:2014-05-28 14:27:20

标签: mysql mariadb

对于MySQL数据库(InnoDB)的SELECT查询,我们遇到了一个奇怪的问题。

以下查询错误地返回1条匹配记录:

select `ID` 
from `AccessTables` 
where `numTableID` = 14 
    AND `numUserCatID` IN (7,253) 
    AND (`numUpdateCat` = 2 OR `numUpdateItems` = 2) 
order by `ID` asc 
limit 1

而以下查询正确返回没有匹配的记录:

select `ID` 
from `AccessTables` 
where `numTableID` = 14 
    AND `numUserCatID` IN (7,253) 
    AND (`numUpdateCat` = 2 OR `numUpdateItems` = 2) 
limit 1

如您所见,这些查询之间的唯一区别是“order by”子句。

查询中请求的ID列是表的自动生成的主键列。

第一个查询中返回的记录是一个记录,如果'或'子句周围没有括号,则会找到该记录。 但是在查询的那一部分周围有括号,所以我不明白为什么在这里返回此记录。然后,只有在查询中存在“order by”子句时才会这样。

正在使用的MySQL版本是:MySQL服务器:5.5.32-MariaDB-log

这里的任何人都可以对这个问题有所了解吗?提前谢谢。

(编辑:省略括号确实返回一行,但这是第一次查询返回的那一行)

 insert  into `AccessTables`(`ID`,`numUserCatID`,`numTableID`,`numUpdateCat`,`numPublishCat`,`numUpdateItems`,`dateInsert`,`dateUpdate`,`numInsertAuthorID`,`numUpdateAuthorID`,`numViewItems`) values (71,15,14,0,0,2,'2008-03-13 23:38:47','2013-04-04 09:34:36',0,513,2);

(编辑nr.2:没有MariaDB,但.... http://sqlfiddle.com/#!2/2a922/8

编辑nr。 3,针对真正的MariaDB事件运行这些查询:

查询1:

EXPLAIN EXTENDED SELECT `ID` 
FROM `AccessTables` 
WHERE `numTableID` = 14 
    AND `numUserCatID` IN (7,253) 
    AND (`numUpdateCat` = 2 OR `numUpdateItems` = 2) 
ORDER BY `ID` ASC 
LIMIT 1;

输出:

"id"    "select_type"   "table" "type"  "possible_keys" "key"   "key_len"   "ref"   "rows"  "filtered"  "Extra"<br />
"1" "SIMPLE"    "AccessTables"  "range" "numUserCatID,numTableID,numUpdateCat,numUpdateItems"   "numTableID"    "8" \N  "136"   "11.03" "Using where"

QUERY2:

EXPLAIN EXTENDED SELECT `ID` 
FROM `AccessTables` 
WHERE `numTableID` = 14 
    AND `numUserCatID` IN (7,253) 
    AND (`numUpdateCat` = 2 OR `numUpdateItems` = 2) 
LIMIT 1;

输出:

"id"    "select_type"   "table" "type"  "possible_keys" "key"   "key_len"   "ref"   "rows"  "filtered"  "Extra"<br />
"1" "SIMPLE"    "AccessTables"  "range" "numUserCatID,numTableID,numUpdateCat,numUpdateItems"   "numUserCatID"  "8" \N  "20"    "75.00" "Using index condition; Using where"

QUERY3:

EXPLAIN EXTENDED SELECT `ID` 
FROM `AccessTables` 
WHERE `numTableID` = 14 
    AND (numUserCatID = 7 OR numUserCatID = 253) 
    AND (`numUpdateCat` = 2 OR `numUpdateItems` = 2) 
ORDER BY `ID` ASC 
LIMIT 1;

输出:

"id"    "select_type"   "table" "type"  "possible_keys" "key"   "key_len"   "ref"   "rows"  "filtered"  "Extra"<br />
"1" "SIMPLE"    "AccessTables"  "range" "numUserCatID,numTableID,numUpdateCat,numUpdateItems"   "numTableID"    "8" \N  "136"   "11.03" "Using where"

编辑nr。 4: 删除'limit 1'与删除'order by'的结果相同:没有找到行。

查询4:

EXPLAIN EXTENDED SELECT `ID` 
FROM `AccessTables` 
WHERE `numTableID` = 14 
    AND `numUserCatID` IN (7,253) 
    AND (`numUpdateCat` = 2 OR `numUpdateItems` = 2) 
ORDER BY `ID` ASC;

输出:

"id"    "select_type"   "table" "type"  "possible_keys" "key"   "key_len"   "ref"   "rows"  "filtered"  "Extra"<br />
"1" "SIMPLE"    "AccessTables"  "range" "numUserCatID,numTableID,numUpdateCat,numUpdateItems"   "numUserCatID"  "8" \N  "20"    "75.00" "Using index condition; Using where; Using filesort"

因此,返回正确结果的查询(找到0条记录)似乎与numUserCatID上的索引一起使用,而返回错误结果的查询(找到1条记录)似乎与numTableID上的索引一起使用。

奇怪...!

编辑nr。 5:
通过其他专栏订购,例如。 dateInsert(表示记录插入表中的日期/时间戳)也会更改查询结果。
然后再次没有返回记录,并且使用的索引再次是numUserCatID上的索引。

我们使用'按ID asc排序',因为我们假设ID始终代表记录插入数据库的顺序。
但是dateInsert在我们的例子中基本相同。

使用常规键列进行排序而不是主键时,大型数据库是否会出现性能损失?

2 个答案:

答案 0 :(得分:2)

如果这确实发生了,那就是一个错误。“真的”我的意思是这些是您发送到数据库服务器的确切查询,并且基础表尚未更新时间。

类似(但不完全相同)的问题在于: MDEV-2662

请将问题报告给MariaDB团队。


要解决当前问题,请尝试重新编写查询,例如不使用IN替换;

AND numUserCatID IN (7,253) 

使用:

AND (numUserCatID = 7 OR numUserCatID = 253)

并检查您是否得到相同的错误结果。

答案 1 :(得分:0)

我与MarjaR合作,经过测试:MariaDB 5.5中的这个错误在5.5.37中得到解决