mysql存储过程效率
mysql中使用存储过程进行查询效率高吗
能,存储过程是在服务器端运行的。 1、执行速度比普通的SQL语句快 再运行存储过程前,数据库已对其进行了语法和句法分析,并给出了优化执行方案。这种已经编译好的过程可极大地改善SQL语句的性能。
B. 关于存mysql存贮过程与sql的效率问题
存储过程不仅仅是为了方便你少打字而用的。也不仅仅是一个方法那么简单。
仅讨论效率的话,通常情况下,执行存储过程所需的SQL语句远短于直接执行SQL语句。而且存储过程在数据库内部会被优化,所以也比直接执行效率更高。
以下是SQL 2K8帮助的说明:
======================================
Microsoft SQL Server 中的存储过程与其他编程语言中的过程类似,原因是存储过程可以:
接受输入参数并以输出参数的格式向调用过程或批处理返回多个值。
包含用于在数据库中执行操作(包括调用其他过程)的编程语句。
向调用过程或批处理返回状态值,以指明成功或失败(以及失败的原因)。
可以使用 Transact-SQL EXECUTE 语句来运行存储过程。存储过程与函数不同,因为存储过程不返回取代其名称的值,也不能直接在表达式中使用。
在 SQL Server 中使用存储过程而不使用存储在客户端计算机本地的 Transact-SQL 程序的好处包括:
存储过程已在服务器注册。
存储过程具有安全特性(例如权限)和所有权链接,以及可以附加到它们的证书。
用户可以被授予权限来执行存储过程而不必直接对存储过程中引用的对象具有权限。
存储过程可以强制应用程序的安全性。
参数化存储过程有助于保护应用程序不受 SQL Injection 攻击。有关详细信息,请参阅 SQL Injection。
存储过程允许模块化程序设计。
存储过程一旦创建,以后即可在程序中调用任意多次。这可以改进应用程序的可维护性,并允许应用程序统一访问数据库。
存储过程是命名代码,允许延迟绑定。
这提供了一个用于简单代码演变的间接级别。
存储过程可以减少网络通信流量。
一个需要数百行 Transact-SQL 代码的操作可以通过一条执行过程代码的语句来执行,而不需要在网络中发送数百行代码。
C. mysql 存储过程怎么进行性能优化
在数据库的开发过程中,经常会遇到复杂的业务逻辑和对数据库的操作,这个时候就会用存储过程来封装数据库操作。如果项目的存储过程较多,书写又没有一定的规范,将会影响以后的系统维护困难和大存储过程逻辑的难以理解,另外如果数据库的数据量大或者项目对存储过程的性能要求很,就会遇到优化的问题,否则速度有可能很慢,经过亲身经验,一个经过优化过的存储过程要比一个性能差的存储过程的效率甚至高几百倍。下面介绍某一个MySQL存储过程优化的整个过程。
在本文中,需要被优化的存储过程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30)
)
pr_dealtestnum_label:begin
insert into tb_testnum select boxnumber,usertype from tb_testnum_tmp where boxnumber= p_boxnumber;
leave pr_dealtestnum_label;
end;
//
delimiter ;
select 'create procere pr_dealtestnumok';
在存储过程中使用到的表tb_testnum结构如下:
drop table if exists tb_testnum;
create table tb_testnum
(
boxnumber varchar(30) not null,
usertype int not null
);
create unique index idx1_tb_testnum ontb_testnum(boxnumber);
在存储过程中使用到的另外一张表tb_testnum_tmp结构如下:
drop table if exists tb_testnum_tmp;
create table tb_testnum_tmp
(
boxnumber varchar(30) not null,
usertype int not null
);
create unique index idx1_tb_testnum_tmp ontb_testnum_tmp(boxnumber);
从两个表的结构可以看出,tb_testnum和tb_testnum_tmp所包含的字段完全相同,存储过程pr_dealtestnum的作用是根据输入参数将tb_testnum_tmp表的数据插入到tb_testnum表中。
很明显,虽然能够实现预期的功能,但存储过程pr_dealtestnum的代码还有改进的地方。
下面,我们一步一步来对其进行优化。
优化一
存储过程pr_dealtestnum的主体是一条insert语句,但这条insert语句里面又包含了select语句,这样的编写是不规范的。因此,我们要把这条insert语句拆分成两条语句,即先把数据从tb_testnum_tmp表中查找出来,再插入到tb_testnum表中。修改之后的存储过程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30)
)
pr_dealtestnum_label:begin
declare p_usertype int;
select usertype into p_usertype from tb_testnum_tmp where boxnumber=p_boxnumber;
insert into tb_testnum values(p_boxnumber,p_usertype);
leave pr_dealtestnum_label;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
优化二
在向tb_testnum表插入数据之前,要判断该条数据在表中是否已经存在了,如果存在,则不再插入数据。同理,在从tb_testnum_tmp表中查询数据之前,要先判断该条数据在表中是否存在,如果存在,才能从表中查找数据。修改之后的存储过程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30)
)
pr_dealtestnum_label:begin
declare p_usertype int;
declare p_datacount int;
select count(*) into p_datacount from tb_testnum_tmp where boxnumber=p_boxnumber;
if p_datacount > 0 then
begin
select usertype into p_usertype fromtb_testnum_tmp where boxnumber=p_boxnumber;
end;
else
begin
leave pr_dealtestnum_label;
end;
end if;
select count(*) into p_datacount from tb_testnum where boxnumber=p_boxnumber;
if p_datacount = 0 then
begin
insert into tb_testnum values(p_boxnumber,p_usertype);
leave pr_dealtestnum_label;
end;
else
begin
leave pr_dealtestnum_label;
end;
end if;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
优化三
不管向tb_testnum表插入数据的操作执行成功与否,都应该有一个标识值来表示执行的结果,这样也方便开发人员对程序流程的追踪和调试。也就是说,在每条leave语句之前,都应该有一个返回值,我们为此定义一个输出参数。修改之后的存储过程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30),
out p_result int -- 0-succ, other-fail
)
pr_dealtestnum_label:begin
declare p_usertype int;
declare p_datacount int;
select count(*) into p_datacount from tb_testnum_tmp where boxnumber=p_boxnumber;
if p_datacount > 0 then
begin
select usertype into p_usertype from tb_testnum_tmp where boxnumber=p_boxnumber;
end;
else
begin
set p_result = 1;
leave pr_dealtestnum_label;
end;
end if;
select count(*) into p_datacount from tb_testnum where boxnumber=p_boxnumber;
if p_datacount = 0 then
begin
insert into tb_testnum values(p_boxnumber,p_usertype);
set p_result = 0;
leave pr_dealtestnum_label;
end;
else
begin
set p_result = 2;
leave pr_dealtestnum_label;
end;
end if;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
优化四
我们注意到“insert into tb_testnum values(p_boxnumber,p_usertype);”语句中,tb_testnum表之后没有列出具体的字段名,这个也是不规范的。如果在以后的软件版本中,tb_testnum表中新增了字段,那么这条insert语句极有可能会报错。因此,规范的写法是无论tb_testnum表中有多少字段,在执行insert操作时,都要列出具体的字段名。修改之后的存储过程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30),
out p_result int -- 0-succ, other-fail
)
pr_dealtestnum_label:begin
declare p_usertype int;
declare p_datacount int;
select count(*) into p_datacount from tb_testnum_tmp where boxnumber=p_boxnumber;
if p_datacount > 0 then
begin
select usertype into p_usertype from tb_testnum_tmp where boxnumber=p_boxnumber;
end;
else
begin
set p_result = 1;
leave pr_dealtestnum_label;
end;
end if;
select count(*) into p_datacount from tb_testnum where boxnumber=p_boxnumber;
if p_datacount = 0 then
begin
insert into tb_testnum(boxnumber,usertype) values(p_boxnumber,p_usertype);
set p_result = 0;
leave pr_dealtestnum_label;
end;
else
begin
set p_result = 2;
leave pr_dealtestnum_label;
end;
end if;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
优化五
在执行insert语句之后,要用MySQL中自带的@error_count参数来判断插入数据是否成功,方便开发人员跟踪执行结果。如果该参数的值不为0,表示插入失败,那么我们就用一个返回参数值来表示操作失败。修改之后的存储过程如下:
drop procere if exists pr_dealtestnum;
delimiter //
create procere pr_dealtestnum
(
in p_boxnumber varchar(30),
out p_result int -- 0-succ, other-fail
)
pr_dealtestnum_label:begin
declare p_usertype int;
declare p_datacount int;
select count(*) into p_datacount from tb_testnum_tmp where boxnumber=p_boxnumber;
if p_datacount> 0 then
begin
select usertype into p_usertype from tb_testnum_tmp where boxnumber=p_boxnumber;
end;
else
begin
set p_result = 1;
leave pr_dealtestnum_label;
end;
end if;
select count(*) into p_datacount from tb_testnum where boxnumber=p_boxnumber;
if p_datacount = 0then
begin
insert into tb_testnum(boxnumber,usertype) values(p_boxnumber,p_usertype);
if @error_count<>0 then
begin
set p_result= 3;
end;
else
begin
set p_result= 0;
end;
end if;
end;
else
begin
set p_result = 2;
end;
end if;
leave pr_dealtestnum_label;
end;
//
delimiter ;
select 'create procere pr_dealtestnum ok';
D. MySQL的存储过程和函数效率不如MSSQL和oracle吗
这两家的脚本引擎非常成熟,效率很高,而mysql的连脚本都算不上,所以在存储过程和函数里只做CRUD,别干别的,干别的话都会拖慢效率。
E. mysql存储过程的if判断有多个条件该怎么优化效率
这个应该不会太慢吧,我建议你看一下,你是不是循环做了太多次的插入/更新操作。
mysql默认的配置中,每次事务提交都要写binlog和redo log,如果循环太多次——比如循环插入10w条记录——就会非常慢。一般优化思路分两种:
1 修改 sync_binlog为一个100-1000间的值,让binlog每隔100-1000个事务后再写一次;修改innodb_flush_log_at_trx_commit =2; 这么搞的好处是降低了写log的次数和消耗的时间,缺点是,中间出错的话,会丢失一部分的binlog和redolog导致无法通过他们来在出问题是恢复生产库数据。
2 将所有的插入/更新操作放到一个事务中进行。这样,显然就只需要一次写binlong和redolog咯。
F. mysql 存储过程的执行速度不快
大致看了下,用了2个游标,2个临时表,n个insert、update操作。。。
游标是不推荐使用的,慢,如果真得用,那还是放到后台php去循环好。
主要是没弄懂你要做的操作和逻辑,不然mysql用join来操作,把游标去掉,换成mysql自己每行去遍历,估计也就毫秒级。(估计你目前整个表的数据也就几万而已)
G. mysql 存储过程执行太慢怎么优化
1.当我们请求mysql服务器的时候,MySQL前端会有一个监听,请求到了之后,服务器得到相关的SQL语句,执行之前(虚线部分为执行),还会做权限的判断
2.通过权限之后,SQL就到MySQL内部,他会在查询缓存中,看该SQL有没有执行过,如果有查询过,则把缓存结果返回,说明在MySQL内部,也有一个查询缓存.但是这个查询缓存,默认是不开启的,这个查询缓存,和我们的Hibernate,Mybatis的查询缓存是一样的,因为查询缓存要求SQL和参数都要一样,所以这个命中率是非常低的(没什么卵用的意思)。
3.如果我们没有开启查询缓存,或者缓存中没有找到对应的结果,那么就到了解析器,解析器主要对SQL语法进行解析
4.解析结束后就变成一颗解析树,这个解析树其实在Hibernate里面也是有的,大家回忆一下,在以前做过Hibernate项目的时候,是不是有个一个antlr.jar。这个就是专门做语法解析的工具.因为在Hibernate里面有HQL,它就是通过这个工具转换成SQL的,我们编程语言之所以有很多规范、语法,其实就是为了便于这个解析器解析,这个学过编译原理的应该知道.
5.得到解析树之后,不能马上执行,这还需要对这棵树进行预处理,也就是说,这棵树,我没有经过任何优化的树,预处理器会这这棵树进行一些预处理,比如常量放在什么地方,如果有计算的东西,把计算的结果算出来等等...
6.预处理完毕之后,此时得到一棵比较规范的树,这棵树就是要拿去马上做执行的树,比起之前的那棵树,这棵得到了一些优化
7.查询优化器,是MySQL里面最关键的东西,我们写任何一条SQL,比如SELECT * FROM USER WHERE USERNAME = toby AND PASSWORD = 1,它会怎么去执行?它是先执行username = toby还是password = 1?每一条SQL的执行顺序查询优化器就是根据MySQL对数据统计表的一些信息,比如索引,比如表一共有多少数据,MySQL都是有缓存起来的,在真正执行SQL之前,他会根据自己的这些数据,进行一个综合的判定,判断这一次在多种执行方式里面,到底选哪一种执行方式,可能运行的最快.这一步是MySQL性能中,最关键的核心点,也是我们的优化原则.我们平时所讲的优化SQL,其实说白了,就是想让查询优化器,按照我们的想法,帮我们选择最优的执行方案,因为我们比MySQL更懂我们的数据.MySQL看数据,仅仅只是自己收集到的信息,这些信息可能是不准确的,MySQL根据这些信息选了一个它自认为最优的方案,但是这个方案可能和我们想象的不一样.
8.这里的查询执行计划,也就是MySQL查询中的执行计划,比如要先执行username = toby还是password = 1
9.这个执行计划会传给查询执行引擎,执行引擎选择存储引擎来执行这一份传过来的计划,到磁盘中的文件中去查询,这个时候重点来了,影响这个查询性能最根本的原因是什么?就是硬盘的机械运动,也就是我们平时熟悉的IO,所以一条查询语句是快还是慢,就是根据这个时间的IO来确定的.那怎么执行IO又是什么来确定的?就是传过来的这一份执行计划.(优化就是制定一个我们认为最快的执行方案,最节省IO,和执行最快)
10.如果开了查询缓存,则返回结果给客户端,并且查询缓存也放一份。
H. 用mysql数据库的存储过程使用游标效率低下怎么解决
不知道你 什么版本的 mysql
1、
我使用的 mysql, 好像没有 create or replace procere 这样的语法。
只能 create procere
可能是我的 mysql 版本太低了吧...
2、
MySQL 存储过程名字后面的“()”是必须的,即使没有一个参数,也需要“()”
这个不知道是不是也是我mysql 版本太低的问题。
create or replace procere proc_updateDist
修改为
create procere proc_updateDist ()
3、游标部分, 缺少了 DECLARE CONTINUE HANDLER
以及 判断什么时候退出循环的语句。
I. mysql 存储过程中 用临时表 性能消耗大吗
1、首选在编译安装MySQL的时候指定两个参数使用utf8编码。
2、次选在配置文件my.cnf或my.ini设定两个参数,同时设置init_connect参数。
3、第三在配置文件my.cnf或my.ini设定两个参数,同时客户端的连接指定set names命令。
4、在配置文件my.cnf里的client和server处加入default-character-set参数方便管理。
J. mysql 是否推荐使用存储过程mysql的存储过程能带来什么优势以及有什么缺点呢一般适用于什么情况
优势就是提前编译好了的存储过程,少了些分析和解释的过程提高效率,缺点就是不灵活,只能进行传入一些固定的参数进行流程化的运行。适用于接收几个参数进行多次资源操作的情况。