DELIMITER $$

DROP PROCEDURE IF EXISTS `test_release`.`Sp_JP_A_NotifyBegin`$$

CREATE DEFINER=`encysys48`@`%` PROCEDURE `Sp_JP_A_NotifyBegin`(
OUT v_Result varchar(10),
OUT v_OrderID varchar(500),
OUT v_HFserialid varchar(500),
OUT v_ChargeSerialID varchar(500),
OUT v_ErrorCode varchar(100),
OUT v_FullMoney varchar(200),
OUT v_PlatId varchar(200),
OUT v_NotifyCount varchar(4),
OUT v_PHONERESMONEY varchar(200),
OUT v_AGENTID varchar(500)
)
MODIFIES SQL DATA
SQL SECURITY INVOKER
BEGIN
label2: BEGIN
DECLARE l_hforderid varchar(30);
DECLARE l_hfserialid varchar(30);
DECLARE l_errorcode varchar(10);
DECLARE l_charserialid varchar(50);
DECLARE l_fullmoney decimal(10, 2);
DECLARE l_platid int(10);
DECLARE l_notofynum int(4);
DECLARE l_status int(4);
DECLARE l_increce int(10);
DECLARE l_nowtime timestamp;
DECLARE l_phoneresmoney varchar(30);
DECLARE l_agentid varchar(30);
DECLARE l_CheckCode varchar(100);
DECLARE l_PlatCheckResult varchar(10);
DECLARE l_stop_flag int(2);
DECLARE l_flag int(2);
DECLARE l_cursorEmpty int(2) DEFAULT 0; #游标是否为空标记位,0-为空 ;1-不为空
DECLARE l_cursorOpen int(2) DEFAULT 0; #游标是否打开标记位,0-没打开;1-已打开
DECLARE l_cursorClose int(2) DEFAULT 0; #游标是否关闭标记位,0-未关闭;1-已关闭 #定义游标
DECLARE cur_notify CURSOR FOR
SELECT a.hf_serialid
FROM (SELECT hf_serialid
FROM jp_fullnote s
WHERE charge_status IN (0, 3)
AND (notify_flag = 1 OR (notify_flag = 2 AND DATE_ADD(end_time, INTERVAL 3 MINUTE) < l_nowtime))
AND DATE_ADD(begin_time, INTERVAL 48 HOUR) > l_nowtime
AND DATE_ADD(begin_time, INTERVAL 3 HOUR) < l_nowtime
ORDER BY DATE_ADD(end_time, INTERVAL notify_count MINUTE) ASC
) a
LIMIT 0, 10; #其他异常
DECLARE EXIT HANDLER FOR SQLWARNING, SQLEXCEPTION, NOT FOUND
BEGIN
#先判断是否需要关闭游标:如果游标“已打开且未关闭”,则需要关闭
IF l_cursorOpen = 1 AND l_cursorClose = 0 THEN
CLOSE cur_notify;
END IF; IF l_cursorEmpty = 0 THEN
SET v_OrderID = '-1';
SET v_HFserialid = '-1';
SET v_ErrorCode = '-1';
SET v_FullMoney = '-1';
SET v_PlatId = '-1';
SET v_result = '';
SET v_PHONERESMONEY = '-1';
SET v_AGENTID = '-1';
ROLLBACK;
ELSE
SET v_result = '';
SET v_notifycount = l_increce;
COMMIT;
END IF;
END; #赋初始值
SET v_result = '';
SET v_OrderID = '';
SET v_HFserialid = '';
SET v_ChargeSerialID = '';
SET v_ErrorCode = '';
SET v_FullMoney = '';
SET v_PlatId = '';
SET l_notofynum = 0;
SET l_increce = 0;
SET v_PHONERESMONEY = '';
SET v_AGENTID = '';
SET l_nowtime = now();
SET l_stop_flag = 0;
SET l_flag = 0; #自动流程监控
SELECT CONCAT('ChPlat', t.sys_id, '_A8002_NotifyHF') INTO l_CheckCode
FROM jp_sysplat t;
CALL Sp_MO_PlatAutoCheck(l_CheckCode, '3B', l_PlatCheckResult); #使用游标
BEGIN
DECLARE EXIT HANDLER FOR SQLSTATE ''
BEGIN
SET l_stop_flag = 1;
END; #打开游标
OPEN cur_notify;
SET l_cursorOpen = 1; #打开游标后,把游标打开的标记位置为1,表示已打开 FETCH cur_notify INTO l_hfserialid;
#进入游标循环
label1: WHILE l_stop_flag < 1 DO
#每次循环计数
SET l_cursorEmpty = l_cursorEmpty + 1; SELECT charge_status,ERROR_CODE,hf_orderid,hf_serialid,finish_money,
f.senderobj,charge_serialid,PHONE_RESMONEY,AGENT_ID
INTO l_status, l_errorcode, l_hforderid, l_hfserialid, l_fullmoney,
l_platid, l_charserialid, l_phoneresmoney, l_agentid
FROM jp_fullnote f
WHERE hf_serialid = l_hfserialid; IF l_status = 3 THEN
SET l_fullmoney = 0;
END IF; BEGIN
DECLARE EXIT HANDLER FOR SQLWARNING, SQLEXCEPTION, NOT FOUND
SET l_flag = 1; SELECT notify_return_code
INTO l_errorcode
FROM jp_return_code r
WHERE r.error_code = l_errorcode;
END; IF l_flag = 1 THEN
FETCH cur_notify INTO l_hfserialid;
ITERATE label1;
END IF; SET v_OrderID = CONCAT(v_OrderID, l_hforderid, ',');
SET v_HFserialid = CONCAT(v_HFserialid, l_hfserialid, ',');
SET v_ChargeSerialID = CONCAT(v_ChargeSerialID, l_charserialid, ',');
SET v_ErrorCode = CONCAT(v_ErrorCode, l_errorcode, ',');
SET v_FullMoney = CONCAT(v_FullMoney, l_fullmoney, ',');
SET v_PlatId = CONCAT(v_PlatId, l_platid, ','); IF l_phoneresmoney > 10000 THEN
SET v_PHONERESMONEY = CONCAT(v_PHONERESMONEY, '', ',');
ELSE
SET v_PHONERESMONEY = CONCAT(v_PHONERESMONEY, l_phoneresmoney, ',');
END IF; SET v_AGENTID = CONCAT(v_AGENTID, l_agentid, ','); UPDATE jp_fullnote
SET notify_flag = 2,
notify_count = notify_count + 1,
end_time = l_nowtime
WHERE hf_serialid = l_hfserialid; SET l_increce = l_increce + 1;
COMMIT; FETCH cur_notify INTO l_hfserialid;
END WHILE label1;
END; #关闭游标
CLOSE cur_notify;
SET l_cursorClose = 1; #关闭游标后,把游标关闭的标记位置为1,表示已关闭 #判断游标是否为空
IF l_cursorEmpty = 0 THEN
SET v_OrderID = '-1';
SET v_HFserialid = '-1';
SET v_ChargeSerialID = '-1';
SET v_ErrorCode = '-1';
SET v_FullMoney = '-1';
SET v_PlatId = '-1';
SET v_PHONERESMONEY = '-1';
SET v_AGENTID = '-1';
LEAVE label2;
END IF; SET v_NotifyCount = l_increce;
SET v_result = '';
COMMIT;
END;
END$$ DELIMITER ;

优化前

DELIMITER $$

DROP PROCEDURE IF EXISTS `encysys48`.`sp_jp_a_notifyBegin_acc`$$

CREATE DEFINER=`encysys48`@`%` PROCEDURE `sp_jp_a_notifyBegin_acc`(
IN v_num VARCHAR(2), #流水号最后一位除10,所得余数
OUT v_Result varchar(10), #结果码
OUT v_OrderID varchar(500), #订单号
OUT v_HFserialid varchar(500), #话费流水号
OUT v_ChargeSerialID varchar(500), #对端流水
OUT v_ErrorCode varchar(100), #结果码
OUT v_FullMoney varchar(200), #充值金额
OUT v_PlatId varchar(200), #中心平台号
OUT v_NotifyCount varchar(4), #数量
OUT v_PHONERESMONEY varchar(200), #充值后手机余额
OUT v_AGENTID varchar(500)
)
MODIFIES SQL DATA
SQL SECURITY INVOKER
BEGIN
label2: BEGIN
DECLARE l_num INT(2); #流水号最后一位除10,所得余数
DECLARE l_hforderid varchar(30);
DECLARE l_hfserialid varchar(30);
DECLARE l_errorcode varchar(10);
DECLARE l_charserialid varchar(50);
DECLARE l_fullmoney decimal(10, 2);
DECLARE l_platid int(10);
DECLARE l_notofynum int(4);
DECLARE l_status int(4);
DECLARE l_increce int(10);
DECLARE l_nowtime timestamp;
DECLARE l_phoneresmoney varchar(20);
DECLARE l_agentid varchar(30);
DECLARE l_CheckCode varchar(100);
DECLARE l_PlatCheckResult varchar(10);
DECLARE l_stop_flag int(2);
DECLARE l_flag int(2);
DECLARE l_str VARCHAR(50);
DECLARE l_cursorEmpty int(2) DEFAULT 0; #游标是否为空标记位,0-为空 ;1-不为空
DECLARE l_cursorOpen int(2) DEFAULT 0; #游标是否打开标记位,0-没打开;1-已打开
DECLARE l_cursorClose int(2) DEFAULT 0; #游标是否关闭标记位,0-未关闭;1-已关闭
declare l_search_times INT(2) DEFAULT 0; #循环执行游标的次数
DECLARE l_start_time TIMESTAMP; #游标搜索的起始时间
DECLARE l_end_time TIMESTAMP; #游标搜索的结束时间
#定义游标
DECLARE cur_notify CURSOR FOR
SELECT a.hf_serialid
FROM (SELECT hf_serialid
FROM jp_fullnote s
WHERE charge_status IN (0, 3)
AND (notify_flag = 1 OR (notify_flag = 2 AND DATE_ADD(end_time, INTERVAL 3 MINUTE) < l_nowtime))
AND MOD(SUBSTRING(hf_serialid, CHAR_LENGTH(hf_serialid), 1), 10) = l_num
AND begin_time >= l_start_time and begin_time < l_end_time
ORDER BY DATE_ADD(end_time, INTERVAL notify_count MINUTE) ASC
) a
LIMIT 0, 10; #其他异常
DECLARE EXIT HANDLER FOR SQLWARNING, SQLEXCEPTION, NOT FOUND
BEGIN
#先判断是否需要关闭游标:如果游标“已打开且未关闭”,则需要关闭
IF l_cursorOpen = 1 AND l_cursorClose = 0 THEN
CLOSE cur_notify;
END IF; IF l_cursorEmpty = 0 THEN
SET v_OrderID = '-1';
SET v_HFserialid = '-1';
SET v_ErrorCode = '-1';
SET v_FullMoney = '-1';
SET v_PlatId = '-1';
SET v_result = '';
SET v_PHONERESMONEY = '-1';
SET v_AGENTID = '-1';
ROLLBACK;
ELSE
SET v_result = '';
SET v_notifycount = l_increce;
COMMIT;
END IF;
CALL sp_SN_dbwarning(1, 'Sp_JP_A_NotifyBegin_Acc', '', "", NULL, NULL);
END; #赋初始值
SET v_result = '';
SET v_OrderID = '';
SET v_HFserialid = '';
SET v_ChargeSerialID = '';
SET v_ErrorCode = '';
SET v_FullMoney = '';
SET v_PlatId = '';
SET l_notofynum = 0;
SET l_increce = 0;
SET v_PHONERESMONEY = '';
SET v_AGENTID = '';
SET l_nowtime = now();
SET l_stop_flag = 0;
SET l_flag = 0;
SET l_num = v_Num;
#自动流程监控
BEGIN
DECLARE EXIT HANDLER FOR SQLWARNING, SQLEXCEPTION, NOT FOUND SET l_CheckCode = 'unknown_A80??_Charge_General?';
SELECT
CASE v_Num
WHEN 0 THEN '_A8040_Charge_General0'
WHEN 1 THEN '_A8041_Charge_General1'
WHEN 2 THEN '_A8042_Charge_General2'
WHEN 3 THEN '_A8043_Charge_General3'
WHEN 4 THEN '_A8044_Charge_General4'
WHEN 5 THEN '_A8045_Charge_General5'
WHEN 6 THEN '_A8046_Charge_General6'
WHEN 7 THEN '_A8047_Charge_General7'
WHEN 8 THEN '_A8048_Charge_General8'
WHEN 9 THEN '_A8049_Charge_General9' ELSE '_A80??_Charge_General?' END INTO l_str
FROM DUAL;
SELECT CONCAT('ChPlat', t.sys_id, l_str) INTO l_CheckCode
FROM jp_sysplat t;
CALL Sp_MO_PlatAutoCheck(l_CheckCode, '3B', l_PlatCheckResult);
END;
set l_start_time = now();
#使用游标
looplabel: while ((l_increce < 10) and (l_search_times < 18)) do
set l_end_time = l_start_time;
set l_start_time = DATE_ADD(l_end_time, INTERVAL -10 MINUTE);
set l_stop_flag = 0;
BEGIN
DECLARE EXIT HANDLER FOR SQLSTATE ''
BEGIN
SET l_stop_flag = 1;
END;
#打开游标
OPEN cur_notify;
SET l_cursorOpen = 1; #打开游标后,把游标打开的标记位置为1,表示已打开 FETCH cur_notify INTO l_hfserialid;
INSERT INTO w_help(char_content) VALUES(l_increce);
#进入游标循环
label1: WHILE l_stop_flag < 1 and l_increce < 10 DO
#每次循环计数
SET l_cursorEmpty = l_cursorEmpty + 1; SELECT charge_status,ERROR_CODE,hf_orderid,hf_serialid,finish_money,
senderobj,charge_serialid,PHONE_RESMONEY,AGENT_ID
INTO l_status, l_errorcode, l_hforderid, l_hfserialid, l_fullmoney,
l_platid, l_charserialid, l_phoneresmoney, l_agentid
FROM jp_fullnote f
WHERE hf_serialid = l_hfserialid; #判断订单是否是失败
IF l_status = 3 THEN
SET l_fullmoney = 0;
END IF; #获取错误码
BEGIN
DECLARE EXIT HANDLER FOR SQLWARNING, SQLEXCEPTION, NOT FOUND
SET l_flag = 1; SELECT notify_return_code
INTO l_errorcode
FROM jp_return_code r
WHERE r.error_code = l_errorcode;
END; IF l_flag = 1 THEN
FETCH cur_notify INTO l_hfserialid;
ITERATE label1;
END IF; #拼接参数
SET v_OrderID = CONCAT(v_OrderID, l_hforderid, ',');
SET v_HFserialid = CONCAT(v_HFserialid, l_hfserialid, ',');
SET v_ChargeSerialID = CONCAT(v_ChargeSerialID, l_charserialid, ',');
SET v_ErrorCode = CONCAT(v_ErrorCode, l_errorcode, ',');
SET v_FullMoney = CONCAT(v_FullMoney, l_fullmoney, ',');
SET v_PlatId = CONCAT(v_PlatId, l_platid, ','); IF l_phoneresmoney > 10000 THEN
SET v_PHONERESMONEY = CONCAT(v_PHONERESMONEY, '', ',');
ELSE
SET v_PHONERESMONEY = CONCAT(v_PHONERESMONEY, l_phoneresmoney, ',');
END IF; SET v_AGENTID = CONCAT(v_AGENTID, l_agentid, ','); UPDATE jp_fullnote
SET notify_flag = 2,
notify_count = notify_count + 1,
end_time = l_nowtime
WHERE hf_serialid = l_hfserialid; SET l_increce = l_increce + 1;
INSERT INTO w_help(char_content) VALUES(l_increce);
COMMIT; #进入下一次循环
FETCH cur_notify INTO l_hfserialid;
END WHILE label1;
END;
#关闭游标
CLOSE cur_notify;
SET l_cursorClose = 1; #关闭游标后,把游标关闭的标记位置为1,表示已关闭
set l_search_times = l_search_times + 1;
INSERT INTO w_help(char_content) VALUES(l_search_times);
END WHILE looplabel;
#判断游标是否为空
IF l_cursorEmpty = 0 THEN
SET v_OrderID = '-1';
SET v_HFserialid = '-1';
SET v_ChargeSerialID = '-1';
SET v_ErrorCode = '-1';
SET v_FullMoney = '-1';
SET v_PlatId = '-1';
SET v_PHONERESMONEY = '-1';
SET v_AGENTID = '-1';
LEAVE label2;
END IF; SET v_NotifyCount = l_increce;
insert into w_help(char_content) values(l_increce);
SET v_result = '';
COMMIT;
END;
END$$ DELIMITER ;

优化后

优化的核心是:

  优化前,搜索三小时以内的满足条件的订单,十条;

  优化后,搜索十分钟以内的,满足条件的,搜索结果数目大于10,返回10条搜素结果;

      搜索结果数目小于10,继续搜索10~20分钟之间的,总共之和大于10,返回结果;

      总共结果小于10,继续搜索20~30分钟之间的。

这样,即使搜索三小时以内的,速度也明显的快。

MySQL SQL优化——分片搜索的更多相关文章

  1. mysql sql优化实例

    mysql sql优化实例 优化前: pt-query-degist分析结果: # Query 3: 0.00 QPS, 0.00x concurrency, ID 0xDC6E62FA021C85B ...

  2. Mysql SQL优化&执行计划

    SQL优化准则 禁用select * 使用select count(*) 统计行数 尽量少运算 尽量避免全表扫描,如果可以,在过滤列建立索引 尽量避免在where子句对字段进行null判断 尽量避免在 ...

  3. 18.Mysql SQL优化

    18.SQL优化18.1 优化SQL语句的一般步骤 18.1.1 通过show status命令了解各种SQL的执行频率show [session|global] status; -- 查看服务器状态 ...

  4. mysql sql优化及注意事项

    sql优化分析 通过slow_log等方式可以捕获慢查询sql,然后就是减少其对io和cpu的使用(不合理的索引.不必要的数据访问和排序)当我们面对具体的sql时,首先查看其执行计划A.看其是否使用索 ...

  5. MySQL sql优化(摘抄自文档)

    前言 有人反馈之前几篇文章过于理论缺少实际操作细节,这篇文章就多一些可操作性的内容吧. 注:这篇文章是以 MySQL 为背景,很多内容同时适用于其他关系型数据库,需要有一些索引知识为基础. 优化目标 ...

  6. MySQL SQL优化

    一.优化数据库的一般步骤: (A) 通过 show status 命令了解各种SQL的执行频率. (B) 定位执行效率较低的SQL语句,方法两种: 事后查询定位:慢查询日志:--log-slow-qu ...

  7. Mysql SQL 优化

    1. 查询缓存 多数MySQL服务器都开启了查询缓存,相同的查询被执行多次,查询结果会被放到一个缓存中,这样,后续的相同的查询就不用操作表而直接访问缓存结果了. // 查询缓存不开启 $r = mys ...

  8. MySQL SQL优化之in与range查询【转】

    本文来自:http://myrock.github.io/ 首先我们来说下in()这种方式的查询.在<高性能MySQL>里面提及用in这种方式可以有效的替代一定的range查询,提升查询效 ...

  9. MySql Sql 优化技巧分享

    有天发现一个带inner join的sql 执行速度虽然不是很慢(0.1-0.2),但是没有达到理想速度.两个表关联,且关联的字段都是主键,查询的字段是唯一索引. sql如下: SELECT p_it ...

随机推荐

  1. Linux启动新进程的几种方法及比较[转]

    有时候,我们需要在自己的程序(进程)中启动另一个程序(进程)来帮助我们完成一些工作,那么我们需要怎么才能在自己的进程中启动其他的进程呢?在Linux中提供了不少的方法来实现这一点,下面就来介绍一个这些 ...

  2. Python虚拟环境的配置

    Python中,配置虚拟环境主要是为了防止版本之间的冲突,我是这么理解的: 1.用虚拟环境可以在一个电脑中使用多个Python解释器以及扩展: 2.可以方便的在同一台电脑中使用多个版本的代码. 虚拟环 ...

  3. json解析的函数eval_r() 和 JSON.parse()

              eval_r()解析的字符串格式是'({"data":"hello","num":"5"})'   ...

  4. Redis持久存储-AOF&RDB

    Redis中数据存储模式有2种:cache-only,persistence;cache-only即只做为"缓存"服务,不持久数据,数据在服务终止后将消失,此模式下也将不存在&qu ...

  5. LeetCode OJ 53. Maximum Subarray

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

  6. 监控mysql主从

    这里记录了,每次都百度查询多次. zabbix默认包含mysql监控 其中包含 mysql的基本状态监控 MySQL主从监控需要结合自定义 1)目前项目需求 只对 Slave_IO_Running . ...

  7. 【Machine Learning in Action --5】逻辑回归(LogisticRegression)

    1.概述 Logistic regression(逻辑回归)是当前业界比较常用的机器学习方法,用于估计某种事物的可能性. 在经典之作<数学之美>中也看到了它用于广告预测,也就是根据某广告被 ...

  8. PIVOT就是行转列,UNPIVOT就是列传行

    PIVOT通过将表达式某一列中的唯一值转换为输出中的多个列来旋转表值表达式,并在必要时对最终输出中所需的任何其余列值执行聚合.UNPIVOT与PIVOT执行相反的操作,将表值表达式的列转换为列值. 通 ...

  9. centos 安装ftp服务器

    CentOS下搭建FTP服务器简单记录. 1.安装vsftpd yum install vsftpd 2.编辑iptablesvi /etc/sysconfig/iptables -A INPUT - ...

  10. js通过keyCode值判断单击键盘上某个键,然后触发指定的事件

    当单击按键时触发事件    document.onkeydown = function (e) {             e = e || event;             if (e.keyC ...