mysql - 如何将控制流添加到 mysql 函数中?
问题描述
我想优化一个从表中读取设置的 mysql 5.7 函数。如果解析的日期在“第 1 学期”或“第 2 学期”,则该函数返回 1 或 2。第 1 和第 2 学期的日期每年都在变化。我们已经确认 dateIn 是一个有效的日期。
功能是:
DELIMITER //
CREATE function getSemester (dateIN date)
RETURNS INT DETERMINISTIC
BEGIN
DECLARE sem int;
select if( dateIN < a.mindate,1,2) into sem
from (SELECT min(date(value)) mindate FROM `settings` WHERE name = CONCAT(‘sem2_‘,year(dateIN),‘_start’) ) a;
return sem;
END//
DELIMITER ;
设置定义为:
CREATE TABLE `settings` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`value` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
设置数据为:
INSERT INTO `mdl_sap_settings` (`id`, `name`, `value`)
VALUES
(4, 'sem2_2012_start', '2012/7/16'),
(15, 'sem2_2013_start', '2013/7/1'),
(25, 'sem2_2014_start', '2014/6/30'),
(29, 'sem2_2015_start', '2015/6/29'),
(37, 'sem2_2016_start', '2016/6/27'),
(42, 'sem2_2011_start', '2011/7/16'),
(50, 'sem2_2017_start', '2017/6/26'),
(56, 'sem2_2018_start', '2018/6/25'),
(63, 'sem2_2019_start', '2019/6/24');
问题是在 20,000 行上调用该函数时速度很慢。我想通过在函数中进行某种流控制来优化它,例如:
if (year(dateIN) = 2012)
{
return dateIN < '2012-07-16' ? 1 : 2;
}
if (year(dateIN) = 2013)
{
return dateIN < '2013-07-01' ? 1 : 2;
}
... etc.
我们需要保持选择原样查询,因为如果不维护代码,我们希望它返回正确的值。
我只是想知道这种控制流在 mysql 函数中是否可能,或者是否有其他方法来优化函数?
解决方案
我没有 20k 条记录可供测试,但如果我是你,我会像这样重写你的函数,看看是否有帮助。
DELIMITER //
CREATE function getSemester (dateIN date)
RETURNS INT DETERMINISTIC
BEGIN
DECLARE sem int;
DECLARE nameByDate varchar(255);
SET nameByDate = (SELECT CONCAT('sem2_',year(dateIN),'_start') );
select if( dateIN < a.mindate,1,2) into sem
from (SELECT min(date(value)) mindate FROM `test`.`settings` WHERE name = nameByDate ) a;
return sem;
END//
DELIMITER ;
我会避免在 where 子句中添加 concat,因为大型数据集会影响性能。所以我将它从 where 子句中移出并分配给一个变量一次。如果这没有帮助,您还可以尝试使用 explain 进行查询,看看是否提供任何提示。
EXPLAIN select getSemester('2019/6/24');
祝你好运。
推荐阅读
- qt - 编译时不存在自定义属性?“不能分配给不存在的财产”
- c# - 如何将 curl 请求转换为具有 --resolve 的 HttpClient
- html - 有没有办法让 GIF 在鼠标悬停时播放并暂停?
- arrays - 我不明白为什么我的代码适用于我的结构数组,但不适用于包含该结构数组的结构?
- sql - 将监视添加到 SQL 选择语句
- perl - 启用用户选项以覆盖变量的值
- python - How can I find the file name in a directory?
- python - 如何在包含数据的现有数组中添加一层、一排和一列额外的列
- javascript - 工兵。如何全局使用第三方库
- javascript - 无法将 Javascript 符号绑定到 HTMLElement.style