gpt4 book ai didi

mysql - 使用某些逻辑无法创建mysql事件

转载 作者:行者123 更新时间:2023-11-29 02:41:46 36 4
gpt4 key购买 nike

我试图在mysql中创建一个事件
架构:

create event alert_2 ON SCHEDULE EVERY 300 SECOND DO 
BEGIN
DECLARE current_time DATETIME;
DECLARE attempted INT;
DECLARE completed INT;
DECLARE calc_value DECIMAL;
set @current_time = CONVERT_TZ(NOW(), @@session.time_zone, '+0:00');
select count(uniqueid) as @attempted,SUM(CASE WHEN seconds > 0 THEN 1 ELSE 0 END) as @completed from callinfo where date >= DATE_SUB(@current_time, INTERVAL 300 SECOND) AND date <= @current_time;
SET @calc_value = (ROUND((@completed/@attempted)*100,2);
IF @calc_value <= 10.00 THEN
INSERT INTO report(value1) value (@calc_value);
END IF;
END;

问题:
事件不会创建
需要建议:
这会在callinfo表上创建任何重载吗?
如果是的话,你想建议其他方法来实现同样的目标吗?
我可以创建类似的,但在50倍左右。它会创建一个巨大的加载调用信息表。
呼叫信息架构:
CREATE TABLE `callinfo` (
`uniqueid` varchar(60) NOT NULL DEFAULT '',
`accountid` int(11) DEFAULT '0',
`type` tinyint(1) NOT NULL DEFAULT '0',
`callerid` varchar(120) NOT NULL,
`callednum` varchar(30) NOT NULL DEFAULT '',
`seconds` smallint(6) NOT NULL DEFAULT '0',
`trunk_id` smallint(6) NOT NULL DEFAULT '0',
`trunkip` varchar(15) NOT NULL DEFAULT '',
`callerip` varchar(15) NOT NULL DEFAULT '',
`disposition` varchar(45) NOT NULL DEFAULT '',
`date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`debit` decimal(20,6) NOT NULL DEFAULT '0.000000',
`cost` decimal(20,6) NOT NULL DEFAULT '0.000000',
`provider_id` int(11) NOT NULL DEFAULT '0',
`pricelist_id` smallint(6) NOT NULL DEFAULT '0',
`package_id` int(11) NOT NULL DEFAULT '0',
`pattern` varchar(20) NOT NULL,
`notes` varchar(80) NOT NULL,
`invoiceid` int(11) NOT NULL DEFAULT '0',
`rate_cost` decimal(20,6) NOT NULL DEFAULT '0.000000',
`reseller_id` int(11) NOT NULL DEFAULT '0',
`reseller_code` varchar(20) NOT NULL,
`reseller_code_destination` varchar(80) DEFAULT NULL,
`reseller_cost` decimal(20,6) NOT NULL DEFAULT '0.000000',
`provider_code` varchar(20) NOT NULL,
`provider_code_destination` varchar(80) NOT NULL,
`provider_cost` decimal(20,6) NOT NULL DEFAULT '0.000000',
`provider_call_cost` decimal(20,6) NOT NULL,
`call_direction` enum('outbound','inbound') NOT NULL,
`calltype` enum('STANDARD','DID','FREE','CALLINGCARD') NOT NULL DEFAULT 'STANDARD',
`profile_start_stamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`answer_stamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`bridge_stamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`progress_stamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`progress_media_stamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`end_stamp` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`billmsec` int(11) NOT NULL DEFAULT '0',
`answermsec` int(11) NOT NULL DEFAULT '0',
`waitmsec` int(11) NOT NULL DEFAULT '0',
`progress_mediamsec` int(11) NOT NULL DEFAULT '0',
`flow_billmsec` int(11) NOT NULL DEFAULT '0',
`is_recording` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 for On,1 for Off'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='callinfo';
ALTER TABLE `callinfo` ADD UNIQUE KEY `uniqueid` (`uniqueid`), ADD KEY `user_id` (`accountid`);

有关callinfo表的详细信息:
在通话信息表中,大约20K/小时会插入重新记录。
请建议,如果需要在模式中应用任何索引,以获得良好的性能。

最佳答案

一些建议:
用户定义的变量(以@字符开头的变量)是独立的,不同于局部变量
不需要声明不被引用的局部变量
使用局部变量而不是用户定义的变量
@字符开头的列别名(标识符)需要转义(否则MySQL将抛出语法错误)
分配看起来像用户定义变量的列别名(标识符)只是列别名;它不是对用户定义变量的引用
使用SELECT ... INTO将语句返回的标量值赋给局部变量和/或用户定义的变量
声明数据类型DECIMAL等同于指定DECIMAL(10,0)
INSERT ... VALUES语句中,关键字是VALUES而不是VALUE
最佳实践是给出不同于列名的局部变量名
最佳实践是限定所有列引用
只向表中插入一列(计算值)而不插入其他标识值(这不是非法的)有点奇怪。这可能正是规范所要求的。我觉得有点奇怪。我是根据所写的代码来提出来的,因为代码的作者似乎并不熟悉MySQL。)
使用CONVERT_TZ有点奇怪;假设SQL语句中引用的任何datetime值都将在当前会话时区中解释;我们假设date列是DATETIME数据类型,但这只是猜测。
要创建包含分号的MySQL存储程序,需要将会话的DELIMITER更改为存储程序定义中不显示的字符
与其解决存储程序中的每一个单独问题,我将建议一个修订版,该修订版将执行原始代码的预期操作:

DELIMITER $$

CREATE EVENT alert_2 ON SCHEDULE EVERY 300 SECOND DO
BEGIN
DECLARE ld_current_time DATETIME;
DECLARE ln_calc_value DECIMAL(20,2);
-- DECLARE li_attempted INT;
-- DECLARE li_completed INT;

SET ld_current_time = CONVERT_TZ(NOW(), @@session.time_zone, '+0:00');

SELECT ROUND( 100.0
* SUM(CASE WHEN c.seconds > 0 THEN 1 ELSE 0 END)
/ COUNT(c.uniqueid)
,2) AS calc_value
-- , COUNT(c.uniqueid) AS attempted
-- , SUM(CASE WHEN c.seconds > 0 THEN 1 ELSE 0 END) AS completed
FROM callinfo c
WHERE c.date > ld_current_time + INTERVAL -300 SECOND
AND c.date <= ld_current_time
INTO ln_calc_value
-- , li_attempted
-- , li_completed
;
IF ln_calc_value <= 10.00 THEN
INSERT INTO report ( value1 ) VALUES ( ln_calc_value );
END IF;
END$$

DELIMITER ;

为了提高性能,我们希望有一个以日期为前导列的索引
... ON `callinfo` (`date`, ...)

理想情况下(对于这个存储程序中的查询),前面列日期的索引应该是覆盖索引(包括查询中引用的所有列),例如。
... ON `callinfo` (`date`,`seconds`,`uniqueid`)

问:这会在callinfo表上产生任何重载吗?
因为这会对 callinfo表运行查询,所以需要获取共享锁。如果有适当的索引可用,并且假设5分钟的调用信息是一组很小的行,那么我不希望此查询对性能问题或争用问题有显著的贡献。如果它确实引起了问题,我希望这个存储程序中的这个查询不是问题的根本原因,它只会加剧已经存在的问题。
问:如果是的话,你想建议其他方法来实现同样的目标吗?
当我们还没有定义要实现的“事物”时,很难提出实现“事物”的替代方案。
问:我可以在50左右创建相似但多个的。它会在callinfo表上产生巨大的负载吗。
答:只要查询是有效的,通过适当的索引选择一组小的行,并且运行得很快,我就不会期望该查询产生巨大的负载,不。
后续行动
为了获得最佳性能,我们肯定希望索引的前导列为 date
我将删除查询中对 uniqueid的引用。也就是说,用 COUNT(c.uniqueid)替换 SUM(1)。这些结果是等价的(假设uniqueid被保证为非空),除非在没有行的情况下,COUNT()将返回0,SUM()将返回空。
因为我们是用那个表达式来划分的,所以在“没有行”的情况下,“除以零”和“除以零”是不同的。“除以零”操作将在某些sql模式设置下引发错误。如果我除以COUNT(),我想在除法之前将0转换为NULL
   ... / NULLIF(COUNT(...),0)

或者更符合ansi标准
   ... / CASE WHEN COUNT(...) = 0 THEN NULL ELSE COUNT(...) END 

但是我们可以通过使用 SUM(1)来避免这种繁琐的操作,这样我们就不会对“除以零”的情况进行任何特殊处理。但真正让我们信服的是,我们正在删除对uniqueid列的引用。
那么查询的“覆盖索引”只需要两列。
... ON `callinfo` (`date`,`seconds`)

(即 EXPLAIN将在额外列中显示“Using index”,并显示“range”进行访问)
而且,我的大脑并没有被 CONVERT_TZ的需要所包围。

关于mysql - 使用某些逻辑无法创建mysql事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50280781/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com