【问题标题】:MySQL issue with select query and 'order by' clauseMySQL 选择查询和“order by”子句的问题
【发布时间】:2014-07-17 20:11:54
【问题描述】:

我们遇到了一个针对 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 列是表的自动生成的主键列。

在第一个查询中返回的记录是在“or”子句周围没有括号时可以找到的记录。 但是查询的那部分周围有括号,所以我不明白为什么这里会返回这条记录。然后仅当查询中有“order by”子句时。

使用的 MySQL 版本为:MySQL Server: 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);

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

编辑编号。 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"

查询2:

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"

查询3:

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"

编辑编号。 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 上的索引。

奇怪...!

编辑编号。 5:
按另一列排序,例如。 dateInsert(这是一个日期/时间戳,表示将记录插入表中的时刻),也会更改查询结果。
然后再次没有返回任何记录,并且使用的索引再次是 numUserCatID 上的索引。

我们使用“order by ID asc”是因为我们假设 ID 始终代表记录插入数据库的顺序。
但是 dateInsert 在我们的例子中基本上是一样的。

在大型数据库中使用常规键列而不是主键进行排序时会不会有性能损失?

【问题讨论】:

  • 我们是否有机会获得该行的数据副本,或者至少获得与问题相关的列?
  • 这两个查询是自动生成的(在某些应用程序中)还是您在受信任的环境中运行它们(例如,使用 mysql-cli)并看到奇怪的结果?
  • 这似乎是一个错误。向 MariaDB 发送错误报告。
  • 你能告诉我们返回的行吗? (我的意思是所有列,而不仅仅是ID
  • 表使用的是哪个引擎? AccessTables 是基表还是视图?

标签: mysql mariadb


【解决方案1】:

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

这里有一个类似(但不相同)的问题:MDEV-2662

请将该问题报告给 MariaDB 团队。


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

AND numUserCatID IN (7,253) 

与:

AND (numUserCatID = 7 OR numUserCatID = 253)

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

【讨论】:

  • 重写查询(因此丢失了 IN 子句)似乎解决了这个问题。
  • 我建议您在问题中添加 EXPLAIN EXTENDED 的所有 3 个查询版本的输出(问题中的 2 和没有 IN 的第 3 个。)如果您还可以设置一个小的SQLFiddle.com 的脚本会更好(虽然错误不会在那里显示,没有 MariaDB,其他人可以将脚本复制到他们的机器中并重现错误。)
  • 谢谢。请使用此链接和您机器的 EXPLAIN 输出编辑问题。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-05
    • 2014-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    相关资源
    最近更新 更多