mysql—如何有效地将最新行保留在with recursive语句中?

n53p2ov0  于 2021-06-21  发布在  Mysql
关注(0)|答案(2)|浏览(417)

我在表中有一些初始行。我想用递归调用修改它们。在我的示例代码中,这个函数是2的简单乘法,我想执行5次:

WITH RECURSIVE cte (n,v) AS
(

  -- initial values
  SELECT 0,2
  UNION ALL
  SELECT 0,3

  UNION ALL

  -- generator
  SELECT n + 1, v * 2 FROM cte WHERE n < 5
)
SELECT v FROM cte where n = 5;

它可以工作,但我的问题是它只过滤掉查询末尾不需要的值。如果我从更多的行开始,它会降低性能,因为我在内存中有更多的行。是否可以只在每次迭代中保留最新的值?
sqlfiddle:http://sqlfiddle.com/#!5/9eecb7/6761号

kgqe7b3p

kgqe7b3p1#

在sqlite中可以使用offset子句
offset子句(如果存在并且具有正值n)将阻止前n行添加到递归表中。前n行仍然由递归select处理—它们只是没有添加到递归表中。在跳过所有偏移行之前,不会对满足限制的行进行计数。
演示:http://sqlfiddle.com/#!5/9eecb7/6804号

WITH RECURSIVE cte (n,v) AS
(

  -- initial values
  SELECT 0,2
  UNION ALL
  SELECT 0,3

  UNION ALL

  -- generator
  SELECT n + 1, v * 2 FROM cte WHERE n < 5 LIMIT 1000 OFFSET 10

)
SELECT * FROM cte

| n |  v |
|---|----|
| 5 | 64 |
| 5 | 96 |

在上述示例中,偏移量的计算方式为初始选择中的初始行数(2行)乘以迭代次数(5)=>2*5=10
顺便说一下,在这个具体的例子中,更好的解决方案是计算简单 X * 2^5 (x乘以2到5的幂)而不是递归。

kknvjkwl

kknvjkwl2#

在sqlite中,cte被实现为一个协程(如explain输出所示),因此只有当前行保留在内存中,并且性能不会因为内存使用而降低。
mysql不允许在递归选择部分进行限制。如果我正确解释了wl#3634,那么8.0版中的实现总是完全实现递归CTE。
所以在sqlite中,您不需要做任何事情,而在mysql中,您不能做任何事情。

相关问题