自己的系统在大量用户同时注册登陆时,程序端的负载很大,因为注册和登陆时,不仅要检查用户的账户,还需要修改读取用户相关的一揽子信息表。于是打算把这一堆东西扔进存储过程和函数里,于是就写了,写出来后,发现执行一次存储过程就让mysql的cpu占用从0.1迅速蹦到1.3(linux下用top命令观察),这让我感觉不太好,后来找了个在数据库有几年经验的人看了一下我的存储过程。他提出以下观点:
1.你的存储过程里,居然有随机生成字符串,拼接字符串,sha1加密字符串这些操作,对mysql来说,负担太大
2.不要使用LAST_INSERT_ID()获取上一条插入记录的id,这个命令效率很低,远不如select
3.以上说的这些,其实换在MSSQL和oracle是没啥问题的,这两家的脚本引擎非常成熟,效率很高,而mysql的连脚本都算不上,所以在存储过程和函数里只做CRUD,别干别的,干别的话都会拖慢效率。
我想知道(尤其是第三点)是真的吗,mysql的存储过程执行效率差这么多吗
附上存储过程源码
-- 自动注册用存储过程
DROP PROCEDURE IF EXISTS `AutoRegister`;
-- 改变提交符号
delimiter //
CREATE PROCEDURE `AutoRegister`
(
_ip varchar(255) -- ip地址
)
BEGIN
DECLARE _allChar,_smallLetter,_bigLetter,_numberChar varchar(255);
DECLARE _userName,_password,_passwordSHA1,_nickName varchar(255); -- 定义用户名,密码,密码加密后,昵称
DECLARE _count,_id,_goodsId,_goodsNum INT; -- 计算记录数目,用户id,道具id,道具原始数量
DECLARE _sex tinyint; -- 性别
DECLARE _nowData DATE; -- 定义当前日期
DECLARE _boolLoginReward INT DEFAULT 0; -- 是否有登陆奖励的标志
DECLARE _curDone,_ERROR int DEFAULT 0; -- 游标完成标志符,错误符号
DECLARE goodsCur CURSOR FOR SELECT `id`,`defaultNum` FROM t_Goods WHERE t_Goods.isDelete = 0; -- 游标必须定义在变量之后,HANDLER之前
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION, SQLWARNING set _ERROR = -1; -- 有任何错误就回滚
DECLARE CONTINUE HANDLER FOR not found set _curDone = 1; -- 遍历游标结束后设置为1
-- 设置用于生成随机字符串的基础数据
SET _allChar ='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
SET _smallLetter = 'abcdefghijklmnopqrstuvwxyz';
SET _bigLetter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
SET _numberChar = '0123456789';
start_auto_register: LOOP
SET _userName = CONCAT(fun_CreateString(6,_smallLetter),fun_CreateString(6,_numberChar));
SET _password = CONCAT(fun_CreateString(6,_smallLetter),fun_CreateString(6,_numberChar));
SET _passwordSHA1 = SHA1(_password); -- SHA1加密
SET _nickName = CONCAT('游客',fun_CreateString(4,_numberChar)); -- 生成昵称
SET _sex = CAST(fun_CreateString(1,'01') AS SIGNED); -- 生成性别
-- 事务开始
START TRANSACTION;
insert into t_UserInfo (`userName`, `password`, `userNickName`, `userSex`) VALUES (_userName,_passwordSHA1,_nickName,_sex); -- 用户注册
IF (_ERROR <> 0) THEN
ROLLBACK; -- 插入出错,回滚
SET _ERROR = 0; -- 重置错误符
ITERATE start_auto_register; -- 从头再次循环
END IF;
-- 注册成功,获取刚才注册成功的玩家id
SET _id = LAST_INSERT_ID();
OPEN goodsCur; -- 打开游标
REPEAT
FETCH goodsCur INTO _goodsId,_goodsNum; -- 注意变量名不能和列名一样,否则fetch into失效
SELECT COUNT(`id`) INTO _count FROM t_GoodsInfo WHERE t_GoodsInfo.userId = _id AND t_GoodsInfo.goodsId = _goodsId;
IF (_count < 1) THEN
INSERT INTO t_GoodsInfo (`userId`,`goodsId`,`goodsNum`) VALUES (_id,_goodsId,_goodsNum); -- 初始化玩家物品信息表记录
END IF;
UNTIL _curDone >= 1
END REPEAT;
CLOSE goodsCur; -- 关闭游标
SET _curDone = 0; -- 设置游标遍历到结尾标志符号为默认值
-- 初始化游戏统计数据记录
SELECT COUNT(`id`) INTO _count FROM t_PlayRecordStatisticsInfo WHERE t_PlayRecordStatisticsInfo.`id` = _id;
IF (_count < 1) THEN
INSERT INTO t_PlayRecordStatisticsInfo (`id`) VALUES (_id);
END IF;
-- 初始化当日游戏统计记录
SET _nowData = curdate();
SELECT COUNT(`id`) INTO _count FROM t_PlayRecordStatisticsInfoDay WHERE t_PlayRecordStatisticsInfoDay.`userId` = _id AND t_PlayRecordStatisticsInfoDay.`statisticsDay` = _nowData;
IF (_count < 1) THEN
INSERT INTO t_PlayRecordStatisticsInfoDay (`userId`,`statisticsDay`) VALUES (_id,_nowData);
END IF;
-- 检查本日登陆奖励
CALL sp_LoginReward(_id,_nowData,_boolLoginReward);
-- 插入登陆纪录
INSERT INTO t_UserLoginInfo (`userId`,`userName`,`loginIP`) values (_id,_userName,_ip);
IF _ERROR = 0 THEN
COMMIT;
LEAVE start_auto_register; -- 全部数据插入正常,离开循环
ELSE
ROLLBACK; -- 插入出错,回滚
SET _ERROR = 0; -- 重置错误符
ITERATE start_auto_register; -- 从头再次循环
END IF;
END LOOP start_auto_register;
-- 返回用户基本数据
SELECT `id`,`userName`,_password AS `password`,`userNickName`,`userSex`,`email`,`headPhotoId`,`headPhoto`,`donateLevel`,`vipLevel` FROM t_UserInfo WHERE t_UserInfo.`id` = _id;
-- 返回用户持有道具表
-- 返回玩家游戏记录统计总表
-- 返回玩家当日游戏记录统计总表
-- 返回玩家已经完成的当日任务记录
-- 返回玩家的成就记录
CALL sp_GetPlayerInfo(_id,_nowData);
-- 返回登陆奖励
IF _boolLoginReward = 1 THEN
SELECT * FROM t_LoginRewardInfo WHERE t_LoginRewardInfo.`userId` = _id AND t_LoginRewardInfo.`rewardDate` = _nowData;
ELSE
SELECT NULL;
END IF;
END
//
-- 改回提交符号
delimiter ;
-- 获取玩家的相关信息
DROP PROCEDURE IF EXISTS `sp_GetPlayerInfo`;
-- 改变提交符号
delimiter //
CREATE PROCEDURE `sp_GetPlayerInfo`
(
_id INT,
_nowData DATE
)
BEGIN
-- 返回用户持有道具表
SELECT * FROM t_GoodsInfo WHERE t_GoodsInfo.`userId` = _id;
-- 返回玩家游戏记录统计总表
SELECT * FROM t_PlayRecordStatisticsInfo WHERE t_PlayRecordStatisticsInfo.`id` = _id;
-- 返回玩家当日游戏记录统计总表
SELECT * FROM t_PlayRecordStatisticsInfoDay WHERE t_PlayRecordStatisticsInfoDay.`userId` = _id AND t_PlayRecordStatisticsInfoDay.`statisticsDay` = _nowData;
-- 返回玩家已经完成的当日任务记录
SELECT * FROM t_TaskDailyInfo WHERE t_TaskDailyInfo.`userId` = _id AND t_TaskDailyInfo.`taskDate` = _nowData;
-- 返回玩家的成就记录
SELECT * FROM t_AchievementInfo WHERE t_AchievementInfo.`userId` = _id ;
END
//
-- 改回提交符号
delimiter ;
相关推荐
比较MySQL与其他数据库系统(如Oracle、SQL Server)的存储过程和函数,虽然基本概念相似,但在语法和功能上可能存在细微差别。例如,Oracle支持PL/SQL,具有更强大的编程特性,而SQL Server的存储过程可以使用T-SQL...
MySQL存储过程编程是数据库应用开发中的一个重要环节,它可以帮助开发者将一系列的数据库操作封装起来,以提高程序的可维护性和运行效率。在MySQL 5.0及以上版本中,存储过程、函数和触发器的支持为数据库提供了更...
MySQL和Oracle的存储过程和函数语法有较大差异,需要逐个转换。例如,Oracle支持PL/SQL,而MySQL支持的是SQL-based存储过程。 7. **触发器和事件**: MySQL的事件调度器需要转换为Oracle的调度器或者触发器。 8....
sql,mysql,oracle常用的函数
- Oracle使用`CREATE OR REPLACE PROCEDURE/FUNCTION`来创建或替换存储过程和函数,而MySQL则需要先使用`DROP PROCEDURE/FUNCTION IF EXISTS`删除已存在的同名对象,再创建新的。 - 在Oracle中,如果存在同名的...
总之,掌握 MySQL 和 Oracle 的函数用法是数据库开发与管理的重要技能,它们可以帮助我们更高效地完成数据存储、检索和分析任务。通过深入学习这两个文档,你可以进一步提升数据库操作的专业水平。
增加一个月,可以使用 ADD_MONTHS 函数在 Oracle 中,而 MySQL 使用 DATE_ADD 函数。截取字符串方面,Oracle 使用 SUBSTR 函数,而 MySQL 使用 SUBSTRING 函数。在 MySQL 中,从子句后的表如果是子查询形式,那么...
至于"mysql的_etl函数",MySQL本身并没有专门的ETL函数,但可以通过SQL语句和存储过程实现ETL任务。例如,使用SELECT...INTO OUTFILE将数据导出为文本文件,然后在MySQL中使用LOAD DATA INFILE导入。也可以编写...
7. **视图和存储过程**:Oracle的视图和存储过程可能需要在MySQL中重新编写,因为两者的语法和权限管理不同。 OracleSqlConvert4MysqlSqlTool.java这个源码工具,根据描述,应该是实现了自动读取Oracle SQL语句,...
在IT行业中,数据库是数据管理和存储的核心,而MySQL和Oracle是两种广泛应用的关系型数据库管理系统(RDBMS)。本文将深入探讨这两个数据库系统及其在实际应用中的相关知识点。 MySQL是一款开源、免费的SQL数据库,...
1. **兼容性**:确保使用的Oracle版本支持Java存储过程。 2. **安全性**:在使用Java函数时,需要注意SQL注入等安全问题。 3. **性能考虑**:虽然CRC32算法本身较为高效,但在大量数据处理时仍需关注性能瓶颈。 4. *...
Java-Hibernate 调用 MySQL 过程和函数的方式知识 Java-Hibernate 框架中调用 MySQL 数据库中的过程和函数是通过 CallableStatement 对象来实现的。下面将详细介绍如何调用 MySQL 中的过程和函数。 调用函数 在 ...
### ORACLE存储过程学习知识点详解 ...以上内容涵盖了Oracle存储过程的基础知识和常用操作方法,希望对初学者有所帮助。在实际应用中,可以根据具体需求灵活运用这些技术来构建高效可靠的数据库应用程序。
### Oracle与MySQL语法定义及函数的不同之处及解决方案 #### 数据迁移常见问题及处理方法 **问题一:** 扫描件表数据转移过程中出现数据量不一致。 **可能原因及解决办法:** 1. **扫描件本身损坏**:检查源...
(1) 高度兼容 MySQL:TiDB 支持 MySQL 的大部分语法和函数,使得从 MySQL 迁移到 TiDB 变得容易。 (2) 水平弹性扩展:TiDB 采用无中心的设计,可以方便地添加或减少节点,实现存储和计算资源的水平扩展。 (3) ...
Oracle、MySQL 和 PostgreSQL 都支持存储过程和函数。Oracle 还支持包,或者说是存储过程的集合,以及几乎没有人用过的各种面向对象特征的集合。存储过程可以提高数据库的性能,因为它可以减少网络传输的数据量,...
在开发方面,MySQL主要通过存储过程和函数实现代码的复用和逻辑处理,但不支持DDL触发器。Oracle支持更为丰富的对象类型,包括记录类型、表类型、机器类型等,并且支持在触发器中取消对表的更改操作。 总的来说,...
3. 存储过程和函数:MySQL和Oracle的存储过程语法略有不同,转换时需注意。 4. 触发器:Oracle支持更多的触发器类型,如行级触发器和语句级触发器,而MySQL只有行级触发器。 5. 索引:Oracle支持函数索引和位图索引...