添加 criteria.setMaxResults(1) 是否只返回一行?或者,它是否仍会返回 100 万行,但请选择其中之一?
是的,它只会返回一行,休眠使用数据库特定的功能来限制结果。休眠不会拾取 100 万行,但 db 会,然后选择第一行(此语句是关于休眠生成的查询,而不是 )。ROWNUM
假设您有一个名为 的表,其中有 8 行。user
+----+-----------+-------+
| id | name | score |
+----+-----------+-------+
| 1 | Xyz | 500 |
| 2 | Name3 | 200 |
| 3 | Name2 | 300 |
| 4 | Name4 | 100 |
| 5 | SomeName | 600 |
| 6 | BSomeName | 150 |
| 7 | Asomename | 80 |
| 8 | Csomename | 700 |
+----+-----------+-------+
现在,您运行以下条件。
criteria.add(Restriction.le("score", 500));
criteria.addOrder(Order.asc("name"));
criteria.setMaxResults(2);
以下由 Hibernate 生成的查询。
select * from(select * from user where score <= 500 order by name) where ROWNUM < 3;
DB 将按以下顺序执行它。
- 查找分数小于或等于 500 的所有行。在这里,它将找到6行。
- 按名称按升序对所有行进行排序。
- 分配给每一行。
ROWNUM
- 查找所有小于 3 的行并返回它们。
ROWNUM
结果会是。
+----+-----------+-------+
| id | name | score |
+----+-----------+-------+
| 7 | ASomeName | 80 |
| 6 | Bsomename | 150 |
+----+-----------+-------+
无论有多少条记录,DB都会执行上述步骤,因此当您有订单并且有许多行满足条件时,Query将非常慢。
我不明白ROWNUM是在检索记录之前还是之后应用。我希望“之前”是有效的,而“之后”则不适用于大型结果集。
ROWNUMS
是给定给满足所有给定条件的行的索引。DB将继续检查每行应用WHERE子句中提供的所有条件,如果everythig都很好,则为该行分配一个数字,然后转到下一行。正如文档所说,这意味着所有条件都得到满足。ROWNUM is evaluated AFTER records are selected from the database
在执行 ORDER BY 条款之前。
ROWNUM
与其他数据库(MySQL,Postgrage等)中的LIMIT不同。即 LIMIT 查找所有行,对它们进行排序,然后返回有限的结果。而 ROWNUM 将在满足所有条件后立即分配给行。这就是休眠生成的内部查询以获得一致的排序结果的原因。
如果使用上表中给出的相同数据,则执行以下查询。
select * from user where score <= 500 where row_num < 3 order by name;
您将获得以下结果。
+----+-----------+-------+
| id | name | score |
+----+-----------+-------+
| 3 | Name2 | 300 |
| 2 | Name3 | 200 |
+----+-----------+-------+
这是因为 DB 开始查找满足条件的行(得分 <= 500),为每个行提供 ROWNUM 索引,直到 ROWNUM < 3,然后按名称对行进行排序。Oracle 将在基于查询的其余部分将行标识为结果集的一部分后立即应用 rownum 谓词
阅读这篇文章和这篇文章,他们真的很详细。