我有一张桌子line_item { id: int, price: decimal, quantity: int, [other:...] }
。这个桌子很大,大约。2800万行。现在我想获得前1000行order by f(price, quantity, [other...])
,f
是一个任意函数。最好的方法是什么?
我认为2解决方案:
order by
和limit
。这种方式可能很慢,因为我认为MySQL计算f
每一行的结果然后对其进行排序。f
。这种方式不利于可伸缩性,因为我可能想在不同的上下文中使用多个函数f
(f1
,f2
...)。我真的希望有比他们更好的第三种解决方案。
(对不起,这是一个否定的答案,但这就是生活。)
如果您接受“最佳解决方案”的速度是您所经历的速度的两倍,那么请接受@Zsuzsa的解决方案。
我在这里告诉您,如果不对f(...)进行某些处理,就无法对其进行优化。原因如下:
优化器看不到WHERE子句,但是看到带有表达式的ORDER BY。因此,它认识到评估查询的唯一方法是执行“表扫描”(即读取所有行),评估每一行的功能,将结果保存在tmp表(包含28M行)中,排序该tmp表,并提供1000行。
可以将该函数中的任何一个复制到WHERE子句中以过滤掉某些行吗?如果是这样,tmp表可能会更小。或者,如果幸运的话,也许可以设计一些INDEX,以便不必进行全表扫描。
您是否正在修改所有行?还是这种“只写”表?也就是说,一行一旦写完,就不会改变吗?在此基础上,是否可以为所有“旧”行预先计算f()?如果是这样,请将其存储在某处并添加索引-Poof!即时结果。
f()的常见部分是某个日期范围内的测试吗?(大表通常有某种日期。大表上的查询经常询问“最近”的项。)如果这样,可以将其从f()中取出。然后,我们可以考虑按日期对表进行分区。这样,即使在f中无法优化其他任何东西,“分区修剪”也可能会限制要处理的行数。
请显示表并讨论此处的某些想法是否可行。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句