我有下表
id INT UNSIGED PRIMARY KEY
attrib1 INT
attrib2 INT
creationTime TIMESTAMP
我有一个函数,它可以从属性中计算出非常复杂的结果。它可以通过外部的值进行参数化,因此我不能将结果存储为另一个属性。此外,函数不是确定性的。
MY_FUNC(param1, attrib1, attrib2)
现在我想获取最后 15 行(按时间戳排序),我也想获得MY_FUNC
的结果。我试过了:
SELECT *, MY_FUNC(2, attrib1, attrib2) FROM myTable ORDER BY creationTime LIMIT 0, 15;
Hovewer,此查询执行时间很长(当表有 5000 行时>> 2 秒)。
我想出了一个技巧:
SELECT *, MY_FUNC(2, attrib1, attrib2) FROM (
SELECT * FROM myTable ORDER BY creationTime LIMIT 0, 15
) AS temp;
哪个有效,并且工作速度很快(同一张表<0.1 秒)。但我不喜欢这个解决方案。
我想在第一个查询中,MySQL 对每条记录运行MY_FUNC
,而不仅仅是我正在查询的 15 条记录。我说的对吗?有没有办法配置 MySQL/查询,以便仅针对所选行计算函数?为什么MySQL会为所有这些计算它,尽管这些结果是无用的?
我知道,如果将它们用于WHERE
或ORDER
条款中,它们不会毫无用处。但事实并非如此。
为什么MySQL计算所有行的函数? 这就是数据库的工作方式(而不仅仅是MySQL)。ORDER BY
子句在处理SELECT
、FROM
、WHERE
、GROUP BY
和HAVING
子句后应用于结果集。 为了创建结果集,必须处理所有行的值。LIMIT
应用于ORDER BY
的结果。
您已经找到了获得所需性能的方法:
SELECT t.*, MY_FUNC(2, attrib1, attrib2)
FROM (SELECT t.*
FROM myTable t
ORDER BY creationTime
LIMIT 0, 15
) t;
这不是"黑客",而是解决问题的非常合理的方法。 一个参数,它改变了MySQL和所有其他数据库引擎进行此处理的方式。 那将是一个黑客。
请注意:如果您没有索引,myTable(creationTime)
索引将有助于此查询的性能。