加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

MYSQL数据库查询mysql中执行效率低的sql语句的方法

发布时间:2020-12-12 01:16:31 所属栏目:MySql教程 来源:网络整理
导读:《MYSQL数据库查询mysql中执行效率低的sql语句的方法》要点: 本文介绍了MYSQL数据库查询mysql中执行效率低的sql语句的方法,希望对您有用。如果有疑问,可以联系我们。 MYSQL入门 一些小技巧 1. 如何查出效率低的语句? 在MySQL下,在启动参数中设置 --log-sl

《MYSQL数据库查询mysql中执行效率低的sql语句的方法》要点:
本文介绍了MYSQL数据库查询mysql中执行效率低的sql语句的方法,希望对您有用。如果有疑问,可以联系我们。

MYSQL入门一些小技巧
1. 如何查出效率低的语句?
在MySQL下,在启动参数中设置 --log-slow-queries=[文件名],就可以在指定的日志文件中记录执行时间超过long_query_time(缺省为10秒)的SQL语句.你也可以在启动配置文件中修改long query的时间,如:

代码如下:
?# Set long query time to 8 seconds
??? long_query_time=8

MYSQL入门2. 如何查询某表的索引?
可使用SHOW INDEX语句,如:

代码如下:
?SHOW INDEX FROM [表名]

MYSQL入门3. 如何查询某条语句的索引使用情况?
可用EXPLAIN语句来看一下某条SELECT语句的索引使用情况.如果是UPDATE或DELETE语句,需要先转换为SELECT语句.
4. 如何把导出INNODB引擎的内容到错误日志文件中?
我们可以使用SHOW INNODB STATUS命令来查看INNODB引擎的很多有用的信息,如当前进程、事务、外键错误、死锁问题和其它一些统计数据.如何让该信息能记录在日志文件中呢?只要使用如下语句创建innodb_monitor表,MySQL就会每15秒钟把该系统写入到错误日志文件中:

代码如下:
CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB;

MYSQL入门如果你不再需要导出到错误日志文件,只要删除该表即可:

代码如下:
?DROP TABLE innodb_monitor;

MYSQL入门5. 如何定期删除庞大的日志文件?
只要在启动配置文件中设置日志过期时间即可:

代码如下:
?expire_logs_days=10

MYSQL入门经验教训
1. 重点关注索引
下面以表TSK_TASK表为例说明SQL语句优化过程.TSK_TASK表用于保存系统监测任务,相关字段及索引如下:

MYSQL入门??? ID:主键;
??? MON_TIME:监测时间;建了索引;
??? STATUS_ID:任务状态;与SYS_HIER_INFO.ID建立了外键关系.

MYSQL入门
注MySQL自动会为外键建立索引,在本次优化过程中,发现这些自动建立的外键索引会对SQL语句的效率产生不必要的干扰,需要特别注意!

MYSQL入门首先,我们在日志文件中查到下面语句的执行比较慢,超过10秒了:

代码如下:
?# Query_time: 18 Lock_time: 0 Rows_sent: 295 Rows_examined: 88143
??? select * from TSK_TASK WHERE STATUS_ID = 1064 and MON_TIME >= '2007-11-22' and MON_TIME < '2007-11-23';

MYSQL入门哦,原来在88143条记录中要查出符合条件的295条记录,那当然慢了.赶紧用EXPLAIN语句看一下索引使用情况吧:

MYSQL入门??? +----+-------------+----------+------+----------------------------------------------------------+------------------------------------+---------+-------+--------+-------------+
??? | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
??? +----+-------------+----------+------+----------------------------------------------------------+------------------------------------+---------+-------+--------+-------------+
??? | 1 | SIMPLE | TSK_TASK | ref | FK_task_status_id_TO_SYS_HIER_INFO,TSK_TASK_KEY_MON_TIME | FK_task_status_id_TO_SYS_HIER_INFO | 9 | const | 276168 | Using where |
??? +----+-------------+----------+------+----------------------------------------------------------+------------------------------------+---------+-------+--------+-------------+

MYSQL入门
可以看出,有两个索引可用FK_task_status_id_TO_SYS_HIER_INFO,TSK_TASK_KEY_MON_TIME,而最终执行语句时采用了STATUS_ID上的外键索引.

MYSQL入门再看一下TSK_TASK表的索引情况吧:

MYSQL入门??? +----------+------------------------------------+-------------+-------------+
??? | Table | Key_name | Column_name | Cardinality |
??? +----------+------------+------------------------------------+--------------+
??? | TSK_TASK | PRIMARY | ID | 999149 |
??? | TSK_TASK | FK_task_status_id_TO_SYS_HIER_INFO | STATUS_ID | 16 |
??? | TSK_TASK | TSK_TASK_KEY_MON_TIME | MON_TIME | 13502 |
??? +----------+------------------------------------+-------------+-----------+--

MYSQL入门
在Oracle或其他关系数据库下,WHERE条件中的字段顺序对索引的选择起着很重要的作用.我们调整一下字段顺序,把STATUS_ID放在后面,再EXPLAIN一下:

代码如下:
EXPLAIN select * from TSK_TASK WHERE MON_TIME >= '2007-11-22' and MON_TIME < '2007-11-23' and STATUS_ID = 1064;

MYSQL入门但是没什么效果,MySQL还是选用系统建立的STATUS_ID外键索引.

MYSQL入门仔细分析一下,看来Cardinality属性(即索引中的唯一值的个数)对索引的选择起了极其重要的作用,MySQL选择了索引值唯一值个数小的那个索引作为整条语句的索引.

MYSQL入门针对这条语句,如果使用FK_task_status_id_TO_SYS_HIER_INFO做索引,而TSK_TASK表中存放很多天数据的话,那扫描的记录数会很多,速度较慢.可以有以下几个优化方案:

MYSQL入门??? 如果一天的任务数不多的话,我们删除索引FK_task_status_id_TO_SYS_HIER_INFO,那MySQL会使用索引TSK_TASK_KEY_MON_TIME,然后在该天的数据中在扫描STATUS_ID为1064的记录,那速度也不慢;
??? 如果一天的任务数多的话,我们需删除索引FK_task_status_id_TO_SYS_HIER_INFO和TSK_TASK_KEY_MON_TIME,然后再建立STATUS_ID,MON_TIME的联合索引,这样效率肯定会很高.

MYSQL入门
因此建议,对那些记录数多的表,建议不要使用外键,以避免造成性能效率的严重降低.
2. 尽量控制每张表的记录数
当一张表的记录数很大时,管理和维护就会很麻烦,如索引维护就会占用很长时间,从而会给系统的正常运行造成很大的干扰.

MYSQL入门对随时间推移数据量不断增长的表,我们可以根据时间来区分实时数据和历史数据,可以使用后台服务程序定期移动实时表中的数据到历史表中,从而控制实时表的记录数,提高查询和操作效率.但注意每次移动的时间要足够短,不要影响正常程序的数据写入.如果占用时间太长,可能会造成死锁问题.
3. 数据散列(partition)策略
当客户数达到一定规模后,单个数据库将无法支撑更高的并发访问,此时可以考虑把客户数据散列(partition)到多个数据库中,以分担负载,提高系统的整体性能与效率.

MYSQL入门数据散列可以考虑采用federeated或sharded方式,网上有不少这方面的资料.
一些小技巧
1. 如何查出效率低的语句?
在MySQL下,如:

代码如下:
??? # Set long query time to 8 seconds
??? long_query_time=8

MYSQL入门2. 如何查询某表的索引?
可使用SHOW INDEX语句,如:

代码如下:
? SHOW INDEX FROM [表名]

3. 如何查询某条语句的索引使用情况?
可用EXPLAIN语句来看一下某条SELECT语句的索引使用情况.如果是UPDATE或DELETE语句,MySQL就会每15秒钟把该系统写入到错误日志文件中: 代码如下:
CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB;

MYSQL入门如果你不再需要导出到错误日志文件,只要删除该表即可:

代码如下:
??? DROP TABLE innodb_monitor;

5. 如何定期删除庞大的日志文件?
只要在启动配置文件中设置日志过期时间即可:
代码如下:
??? expire_logs_days=10

经验教训
1. 重点关注索引
下面以表TSK_TASK表为例说明SQL语句优化过程.TSK_TASK表用于保存系统监测任务,相关字段及索引如下:

MYSQL入门??? ID:主键;
??? MON_TIME:监测时间;建了索引;
??? STATUS_ID:任务状态;与SYS_HIER_INFO.ID建立了外键关系.

MYSQL入门
注MySQL自动会为外键建立索引,再EXPLAIN一下:

代码如下:
??? EXPLAIN select * from TSK_TASK WHERE MON_TIME >= '2007-11-22' and MON_TIME < '2007-11-23' and STATUS_ID = 1064;

MYSQL入门但是没什么效果,如:

代码如下:
??? # Set long query time to 8 seconds
??? long_query_time=8

2. 如何查询某表的索引?
可使用SHOW INDEX语句,如:
代码如下:
??? SHOW INDEX FROM [表名]

MYSQL入门3. 如何查询某条语句的索引使用情况?
可用EXPLAIN语句来看一下某条SELECT语句的索引使用情况.如果是UPDATE或DELETE语句,MySQL就会每15秒钟把该系统写入到错误日志文件中:

代码如下:
??? CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB;

如果你不再需要导出到错误日志文件,只要删除该表即可:
代码如下:
??? DROP TABLE innodb_monitor;

5. 如何定期删除庞大的日志文件?
只要在启动配置文件中设置日志过期时间即可:
代码如下:
??? expire_logs_days=10

经验教训
1. 重点关注索引
下面以表TSK_TASK表为例说明SQL语句优化过程.TSK_TASK表用于保存系统监测任务,超过10秒了:

代码如下:
??? # Query_time: 18 Lock_time: 0 Rows_sent: 295 Rows_examined: 88143
??? select * from TSK_TASK WHERE STATUS_ID = 1064 and MON_TIME >= '2007-11-22' and MON_TIME < '2007-11-23';

MYSQL入门哦,如:
代码如下:
??? SHOW INDEX FROM [表名]

3. 如何查询某条语句的索引使用情况?
可用EXPLAIN语句来看一下某条SELECT语句的索引使用情况.如果是UPDATE或DELETE语句,MySQL就会每15秒钟把该系统写入到错误日志文件中:
代码如下:
??? CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB;

如果你不再需要导出到错误日志文件,超过10秒了:

MYSQL入门??? # Query_time: 18 Lock_time: 0 Rows_sent: 295 Rows_examined: 88143
??? select * from TSK_TASK WHERE STATUS_ID = 1064 and MON_TIME >= '2007-11-22' and MON_TIME < '2007-11-23';

MYSQL入门
哦,网上有不少这方面的资料.
配置my.cnf/my.ini,增加 --log-slow-queries 配置,记录所有的slow query,然后挨个优化
本文来源于 WEB开发网

代码如下:
select @a=DRClass1,@b=DRClass2,@c=DRClass3,@d=DRClass4,@e=DRClass5 from Teacher Where TeacherID = @TeacherID

MYSQL入门create table classname(classname char(50))
insert into classname (classname) values (@a)
if (@b is not null)
begin
insert into classname (classname) values (@b)

MYSQL入门if (@c is not null)
begin
insert into classname (classname) values (@c)

MYSQL入门if (@d is not null)
begin
insert into classname (classname) values (@d)
if (@e is not null)
begin
insert into classname (classname) values (@e)
end
end
end
end

MYSQL入门select * from classname


以上这些SQL语句能不能转成一个存储过程?我自己试了下
代码如下:
ALTER PROCEDURE Pr_GetClass

MYSQL入门@TeacherID int,
@a char(50),
@b char(50),
@c char(50),
@d char(50),
@e char(50)
as

MYSQL入门select @a=DRClass1,@e=DRClass5 from Teacher Where TeacherID = @TeacherID
DROP TABLE classname
create table classname(classname char(50))

MYSQL入门insert into classname (classname) values (@a)
if (@b is not null)
begin
insert into classname (classname) values (@b)

MYSQL入门if (@c is not null)
begin
insert into classname (classname) values (@c)

MYSQL入门if (@d is not null)
begin
insert into classname (classname) values (@d)
if (@e is not null)
begin
insert into classname (classname) values (@e)
end
end
end
end

MYSQL入门select * from classname


但是这样的话,这个存储过程就有6个变量,实际上应该只提供一个变量就可以了

MYSQL入门主要的问题就是自己没搞清楚 @a,@b,@C,@d 等是临时变量,是放在as后面重新做一些申明的,而不是放在开头整个存储过程的变量定义.

MYSQL入门(标准化越来越近了):namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

MYSQL入门实战SQL语句收集(不断更新中--)

MYSQL入门前言:这里将我编程实践中遇到的有价值的sql语句一路记下来,一方面方便自己查用,一方面也夯实下即将遗忘的回忆.整个过程中我会不断更新,直到不能再加为止,同时,这里只记录最实用的咚咚,不效仿学院派的那一套.

MYSQL入门 

MYSQL入门一、常用SQL语句荟萃

MYSQL入门1,查询:

MYSQL入门1.1,简单查询:select * from table where

MYSQL入门1.2,连接查询:

MYSQL入门什么是连接查询?顾名释义,就是查询时涉及多个表的查询.是以说到连接,废话一下,要知道连接还是关系数据库的主要特点呢.

MYSQL入门连接查询分为三种:外连接(OUTER JOIN),内连接(INNER JOIN),交叉连接(CROSS JOIN).

MYSQL入门(标准化越来越近了):namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />1.2.1,内连接(INNER JOIN)使用比较运算符进行表间某(些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行.根据所使用的比较方式不同,内连接又分为等值连接、自然连接和不等连接三种.

MYSQL入门1.2.2,外连接分为左外连接(LEFT OUTER JOIN或LEFT JOIN)、右外连接(RIGHT OUTER JOIN或RIGHT JOIN)和全外连接(FULL OUTER JOIN或FULL JOIN)三种.与内连接不同的是,外连接不只列出与连接条件相匹配的行,而是列出左表(左外连接时)、右表(右外连接时)或两个表(全外连接时)中所有符合搜索条件的数据行.

MYSQL入门1.2.3,交叉连接(CROSS JOIN)没有WHERE 子句,它返回连接表中所有数据行的笛卡尔积,其结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数.连接操作中的ON (join_condition) 子句指出连接条件,它由被连接表中的列和比较运算符、逻辑运算符等构成.

MYSQL入门1.2.4,无论哪种连接都不能对text、ntext和image数据类型列进行直接连接,但可以对这三种列进行间接连接.例如:

MYSQL入门SELECT p1.pub_id,p2.pub_id,p1.pr_info
FROM pub_info AS p1 INNER JOIN pub_info AS p2
ON DATALENGTH(p1.pr_info)=DATALENGTH(p2.pr_info)

MYSQL入门1.2.5,使用WHERE子句设置查询条件

MYSQL入门WHERE子句设置查询条件,过滤掉不需要的数据行.例如下面语句查询年龄大于20的数据:

代码如下:
SELECT *

MYSQL入门FROM usertable

MYSQL入门WHERE age>20


WHERE子句可包括各种条件运算符:

MYSQL入门比较运算符(大小比较):>、>=、=、<、<=、<>、!>、!<

MYSQL入门范围运算符(表达式值是否在指定的范围):BETWEEN…AND…

MYSQL入门NOT BETWEEN…AND…

MYSQL入门列表运算符(判断表达式是否为列表中的指定项):IN (项1,项2……)

MYSQL入门NOT IN (项1,项2……)

MYSQL入门模式匹配符(判断值是否与指定的字符通配格式相符):LIKE、NOT LIKE

MYSQL入门空值判断符(判断表达式是否为空):IS NULL、NOT IS NULL

MYSQL入门逻辑运算符(用于多条件的逻辑连接):NOT、AND、OR

MYSQL入门1、范围运算符例:age BETWEEN 10 AND 30相当于age>=10 AND age<=30

MYSQL入门2、列表运算符例:country IN ('Germany','China')

MYSQL入门3、模式匹配符例:常用于模糊查找,它判断列值是否与指定的字符串格式相匹配.可用于char、varchar、text、ntext、datetime和smalldatetime等类型查询.

MYSQL入门可使用以下通配字符:

MYSQL入门百分号%:可匹配任意类型和长度的字符,如果是中文,请使用两个百分号即%%.

MYSQL入门下划线_:匹配单个任意字符,它常用来限制表达式的字符长度.

MYSQL入门方括号[]:指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个.

MYSQL入门[^]:其取值也[] 相同,但它要求所匹配对象为指定字符以外的任一个字符.

MYSQL入门例如:

MYSQL入门限制以Publishing结尾,使用LIKE '%Publishing'

MYSQL入门限制以A开头:LIKE '[A]%'

MYSQL入门限制以A开头外:LIKE '[^A]%'

MYSQL入门空值判断符例:WHERE age IS NULL

MYSQL入门2,更新:update table

MYSQL入门 

MYSQL入门3,插入:

MYSQL入门3.1,一般插入:

代码如下:
INSERT INTO publishers
(pub_id,pub_name,city,state)
VALUES
('9001','Acme Publishing','New York','NY')

3.2,插入多行

MYSQL入门使用 INSERT 语句可以向表添加多行数据.这些多行数据是从已经存有这些数据的另一个表中选取的.本例中,向 pubhold 表中添加有关在加利福尼亚和德克萨斯州的出版商的数据.这些数据可从 publishers 表中获得.

代码如下:
INSERT pubhpold SELECT * FROM publishers
WHERE state = 'CA' OR state = 'TX'

 

MYSQL入门4,删除:

MYSQL入门4.1,Delete语句联合删除:

代码如下:
DELETE FROM uu_SuiteToMinClassroomSect

MYSQL入门WHERE min_classroom_sect_id IN

MYSQL入门?? (SELECT min_classroom_sect_id

MYSQL入门?? FROM uu_MinClassroomSect

MYSQL入门?? WHERE min_classroom_id = '112')


二、视图使用细则

MYSQL入门1,一个典型的视图

代码如下:
CREATE VIEW View_uuGroupTaxis

MYSQL入门AS

MYSQL入门SELECT uu_GroupInfo.group_id,uu_GroupInfo.group_name,

MYSQL入门????? uu_GroupType.main_type,uu_GroupType.group_type_name,

MYSQL入门????? uu_GroupInfo.group_icon_url,ISNULL

MYSQL入门????????? ((SELECT COUNT(*)

MYSQL入门????????? FROM uu_GroupUser

MYSQL入门????????? WHERE uu_GroupInfo.group_id = uu_GroupUser.group_id),0)

MYSQL入门????? * 50 + ISNULL(uu_GroupInfo.fundCount,0) + ISNULL

MYSQL入门????????? ((SELECT COUNT(*)

MYSQL入门????????? FROM Dv_Topic

MYSQL入门????????? WHERE Dv_Topic.BoardID = uu_GroupInfo.subforum_id),0) * 5 + ISNULL

MYSQL入门????????? ((SELECT COUNT(*)

MYSQL入门????????? FROM uu_GroupPhotos

MYSQL入门????????? WHERE uu_GroupPhotos.group_id = uu_GroupInfo.group_id),0)

MYSQL入门????? * 10 + ISNULL(uu_GroupInfo.topic_account,0)

MYSQL入门????? * 2 + ISNULL(uu_GroupInfo.hit_account,0) AS group_ActiveDegree,

MYSQL入门????? ISNULL

MYSQL入门????????? ((SELECT COUNT(*)

MYSQL入门????????? FROM uu_GroupUser

MYSQL入门????????? WHERE uu_GroupInfo.group_id = uu_GroupUser.group_id),0)

MYSQL入门????? AS group_memberNum,ISNULL(uu_GroupInfo.fundCount,0) AS fundCount,

MYSQL入门????????? (SELECT COUNT(*)

MYSQL入门???????? FROM Dv_Topic

MYSQL入门???????? WHERE Dv_Topic.BoardID = uu_GroupInfo.subforum_id) AS group_articleNum,

MYSQL入门????????? (SELECT COUNT(*)

MYSQL入门???????? FROM uu_GroupPhotos

MYSQL入门???????? WHERE uu_GroupPhotos.group_id = uu_GroupInfo.group_id) AS group_PhotoNum,

MYSQL入门????? uu_GroupInfo.topic_account,uu_GroupInfo.hit_account,

MYSQL入门????????? (SELECT user_name

MYSQL入门???????? FROM uu_RegisterUser

MYSQL入门???????? WHERE uu_RegisterUser.user_id = uu_GroupInfo.creator_id)

MYSQL入门????? AS group_CreatorName,uu_GroupInfo.create_time

MYSQL入门FROM uu_GroupInfo INNER JOIN

MYSQL入门????? uu_GroupType ON

MYSQL入门????? uu_GroupInfo.group_type_id = uu_GroupType.group_type_id


三,存储过程的创建和调用

MYSQL入门1,存储过程的调用

代码如下:
Execute procedureName @param='value'

2,一个典型的带参数存储过程
代码如下:
CREATE PROCEDURE P_delMiniclassProc

MYSQL入门@miniClassroom_id int

MYSQL入门AS

MYSQL入门declare @billtag varchar(4)

MYSQL入门set nocount on

MYSQL入门IF @miniClassroom_id is null

MYSQL入门???????? begin

MYSQL入门?????????????????? return(-1)

MYSQL入门???????? end

MYSQL入门else

MYSQL入门?????????????????? BEGIN TRANSACTION

MYSQL入门?????????????????? --删除套餐信息

MYSQL入门?????????????????? DELETE FROM uu_SuiteToMinClassroomSect

MYSQL入门?????????????????? WHERE min_classroom_sect_id IN

MYSQL入门????????????????????? (SELECT min_classroom_sect_id

MYSQL入门????????????????????? FROM uu_MinClassroomSect

MYSQL入门????????????????????? WHERE min_classroom_id =@miniClassroom_id)

MYSQL入门?????????????????? --删除小课堂段信息

MYSQL入门?????????????????? delete from uu_MinClassroomSect

MYSQL入门?????????????????? where min_classroom_id = @miniClassroom_id

MYSQL入门?????????????????? --删除小课堂用户购买记录

MYSQL入门?????????????????? delete from uu_UserBuyMinClassroom

MYSQL入门?????????????????? where min_classroom_id = @miniClassroom_id

MYSQL入门?????????????????? --删除对应小课堂年级学科信息

MYSQL入门?????????????????? delete from uu_MinClassroomToGradeClass

MYSQL入门?????????????????? where min_classroom_id = @miniClassroom_id

MYSQL入门?????????????????? --删除小课堂发言

MYSQL入门?????????????????? delete from uu_MinClassroomDiscuss

MYSQL入门?????????????????? where min_classroom_id = @miniClassroom_id

MYSQL入门?????????????????? --删除课程讨论

MYSQL入门?????????????????? DELETE FROM uu_CourseDiscuss

MYSQL入门?????????????????? WHERE course_id IN

MYSQL入门????????????????????? (SELECT course_id

MYSQL入门????????????????????? FROM uu_CourseInfo

MYSQL入门????????????????????? WHERE min_classroom_id = @miniClassroom_id)

MYSQL入门?????????????????? --删除用户课程收藏


SQL语句的优化是将性能低下的SQL语句转换成目的相同的性能优异的SQL语句.

MYSQL入门  人工智能自动SQL优化就是使用人工智能技术,自动对SQL语句进行重写,从而找到性能最好的等效SQL语句.

MYSQL入门  数据库性能的优化

MYSQL入门
  一个数据库系统的生命周期可以分成:设计、开发和成品三个阶段.在设计阶段进行数据库性能优化的成本最低,收益最大.在成品阶段进行数据库性能优化的成本最高,收益最小.

MYSQL入门  数据库的优化通常可以通过对网络、硬件、操作系统、数据库参数和应用程序的优化来进行.最常见的优化手段就是对硬件的升级.根据统计,对网络、硬件、操作系统、数据库参数进行优化所获得的性能提升,全部加起来只占数据库系统性能提升的40%左右,其余的60%系统性能提升来自对应用程序的优化.许多优化专家认为,对应用程序的优化可以得到80%的系统性能的提升.

MYSQL入门  应用程序的优化

MYSQL入门  应用程序的优化通常可分为两个方面:源代码和SQL语句.由于涉及到对程序逻辑的改变,源代码的优化在时间成本和风险上代价很高,而对数据库系统性能的提升收效有限.

MYSQL入门  为什么要优化SQL语句

MYSQL入门  . SQL语句是对数据库进行操作的惟一途径,对数据库系统的性能起着决定性的作用.

MYSQL入门  . SQL语句消耗了70%至90%的数据库资源.

MYSQL入门  . SQL语句独立于程序设计逻辑,对SQL语句进行优化不会影响程序逻辑.

MYSQL入门  . SQL语句有不同的写法,在性能上的差异非常大.

MYSQL入门  . SQL语句易学,但难精通.

MYSQL入门  优化SQL语句的传统方法是通过手工重写来对SQL语句进行优化.DBA或资深程序员通过对SQL语句执行计划的分析,依靠经验,尝试重写SQL语句,然后对结果和性能进行比较,以试图找到性能较佳的SQL语句.这种传统上的作法无法找出SQL语句的所有可能写法,且依赖于人的经验,非常耗费时间.

MYSQL入门  SQL优化技术的发展历程

MYSQL入门  第一代SQL优化工具是执行计划分析工具.这类工具针对输入的SQL语句,从数据库提取执行计划,并解释执行计划中关键字的含义.

MYSQL入门  第二代SQL优化工具只能提供增加索引的建议,它通过对输入的SQL语句的执行计划的分析,来产生是否要增加索引的建议.

MYSQL入门  第三代SQL优化工具不仅分析输入SQL语句的执行计划,还对输入的SQL语句本身进行语法分析,经过分析产生写法上的改进建议.

MYSQL入门  人工智能自动SQL优化

MYSQL入门SQL语句性能优化--LECCO SQL Expert
图1 人工智能自动SQL优化示意图

MYSQL入门  人工智能自动SQL优化出现在90年代末.目前在商用数据库领域,LECCO Technology Limited(灵高科研有限公司)拥有该技术,并提供使用该技术的自动优化产品LECCO SQL Expert,它支持Oracle(大型网站数据库平台)、Sybase、MS sql server(WINDOWS平台上强大的数据库平台)和IBM DB2数据库平台.该产品针对数据库应用的开发和维护阶段提供的模块有:SQL语法优化器、PL/SQL集成化开发调试环境(IDE)、扫描器、数据库监视器等.其核心模块SQL 语法优化器的工作原理为:①输入一条源SQL语句;②“人工智能反馈式搜索引擎”对输入的SQL语句,结合检测到的数据库结构和索引进行重写,产生N条等效的SQL语句输出;③产生的N条等效SQL语句再送入“人工智能反馈式搜索引擎”进行重写,直至无法产生新的输出或搜索限额满;④对输出的SQL语句进行过滤,选出具有不同执行计划的SQL语句;⑤对得到的SQL语句进行批量测试,找出性能最好的SQL语句.

MYSQL入门  LECCO SQL Expert自动优化实例

MYSQL入门  假设我们从源代码中抽取出这条SQL语句(也可以通过内带的扫描器或监视器获得SQL语句):

代码如下:
  SELECT COUNT(*)

MYSQL入门   FROM EMPLOYEE

MYSQL入门  swheresEXISTS (SELECT 'X'

MYSQL入门   FROM DEPARTMENT

MYSQL入门  swheresEMP_DEPT=DPT_ID

MYSQL入门   AND DPT_NAME LIKE 'AC%')

MYSQL入门  AND EMP_ID IN (SELECT SAL_EMP_ID

MYSQL入门   FROM EMP_SAL_HIST B

MYSQL入门  swheresSAL_SALARY > 70000)


  按下“优化”按钮后,经过10几秒,SQL Expert就完成了优化的过程,并在这10几秒的时间里重写产生了2267 条等价的SQL语句,其中136条SQL语句有不同的执行计划.

MYSQL入门  接下来,我们可以对自动重写产生的136条SQL语句进行批运行测试,以选出性能最佳的等效SQL语句.按下“批运行” 按钮,在“终止条件” 页选择“最佳运行时间SQL语句”,按“确定”.

MYSQL入门  经过几分钟的测试运行后,我们可以发现SQL124的运行时间和反应时间最短.运行速度约有22.75倍的提升(源SQL语句运行时间为2.73秒,SQL124运行时间为0.12秒).现在我们就可以把SQL124放入源代码中,结束一条SQL语句的优化工作了.

MYSQL入门  “边做边学式训练”提升SQL开发水平

MYSQL入门  LECCO SQL Expert不仅能够找到最佳的SQL语句,它所提供的“边做边学式训练”还能够教开发人员和数据库管理员如何写出性能最好的SQL语句.LECCO SQL Expert的“SQL比较器”可以标明源SQL和待选SQL间的不同之处.

MYSQL入门  以上面优化的结果为例,为了查看源SQL语句和SQL124在写法上有什么不同,我们可以按下“比较器” 按钮,对SQL124和源SQL语句进行比较.“SQL 比较器”将SQL124相对于源SQL语句的不同之处以蓝颜色表示了出来.如果选择“双向比较”复选框,“SQL 比较器”可以将两条SQL语句的不同之处以蓝色表示.当然,我们也可以从源语句和重写后的SQL 语句中任选两条进行比较.

MYSQL入门  从比较的结果可以看到,重写后的SQL124把第一个Exists改写成了In;在字段DPT_ID上进行了合并空字符串的操作,以诱导数据库先执行子查询中的

代码如下:
  (SELECT DPT_ID||''

MYSQL入门  FROM DEPARTMENT

MYSQL入门  WHERE DPT_NAME LIKE 'AC%')


  在子查询完成后,再与EMPLOYEE表进行嵌套循环连接(Nested Loop Join).

MYSQL入门  如果觉得对写法的改变难以理解,还可以点中“执行计划”复选框,通过比较两条SQL语句的执行计划的不同,来了解其中的差异.在查看执行计划过程中,如果有什么不明白的地方,可以点中“SQL信息按钮”,再点击执行计划看不明白的地方,LECCO SQL Expert的上下文敏感帮助系统将提供执行计划该处的解释.

MYSQL入门  在“SQL比较器”中,选中“统计信息”复选框后,可得到详细的两条SQL语句运行时的统计信息比较,这对于学习不同的SQL写法对数据库资源的消耗很有帮助.

MYSQL入门  LECCO SQL Expert优化模块的特点

MYSQL入门  LECCO SQL Expert优化模块的特点主要表现为:自动优化SQL语句;以独家的人工智能知识库“反馈式搜索引擎”来重写性能优异的SQL语句;找出所有等效的SQL语句及可能的执行计划;保证产生相同的结果;先进的SQL语法分析器能处理最复杂的SQL语句;可以重写SELECT、SELECT INTO、UPDATE、INSERT和DELETE语句;通过测试运行,为应用程序和数据库自动找到性能最好的SQL语句;提供微秒级的计时,能够优化Web应用程序和有大量用户的在线事务处理中运行时间很短的SQL语句;为开发人员提供“边做边学式训练”,迅速提高开发人员的SQL编程技能;提供上下文敏感的执行计划帮助系统和SQL运行状态帮助;不是猜测或建议,而是独一无二的SQL重写解决方案.

MYSQL入门  写出专家级的SQL语句

MYSQL入门  LECCO SQL Expert的出现,使SQL的优化变得极其简单,只要能够写出SQL语句,它就能帮用户找到最好性能的写法.LECCO SQL Expert不仅能在很短的时间内找到所有可能的优化方案,而且能够通过实际测试,确定最有效的优化方案.同以往的数据库优化手段相比较,LECCO SQL Expert将数据库优化技术带到了一个崭新的技术高度,依赖人的经验、耗费大量时间、受人的思维束缚的数据库优化手段已经被高效、省时且准确的自动优化软件所取代了.通过内建的“LECCO小助手”的帮助,即使是SQL的开发新手,也能快速且简单地写出专家级的SQL语句.

MYSQL入门比如现在有一人员表 (表名:peosons)
若想将姓名、身份证号、住址这三个字段完全相同的记录查询出来

代码如下:
select?? p1.*?? from?? persons?? p1,persons?? p2?? where?? p1.id<>p2.id?? and?? p1.cardid?? =?? p2.cardid?? and?? p1.pname?? =?? p2.pname?? and?? p1.address?? =?? p2.address

可以实现上述效果.

MYSQL入门  select语句前加:
declare @d datetime
set @d=getdate()
并在select语句后加:
select [语句执行花费时间(毫秒)]=datediff(ms,@d,getdate())

MYSQL入门Transact_SQL小手册

MYSQL入门*******************Transact_SQL********************

MYSQL入门--语 句??????????????????????????????? 功 能
--数据操作
SELECT????? --从数据库表中检索数据行和列
INSERT????? --向数据库表添加新数据行
DELETE????? --从数据库表中删除数据行
UPDATE????? --更新数据库表中的数据
--数据定义
CREATE TABLE??? --创建一个数据库表
DROP TABLE???? --从数据库中删除表
ALTER TABLE???? --修改数据库表结构
CREATE VIEW???? --创建一个视图
DROP VIEW???? --从数据库中删除视图
CREATE INDEX??? --为数据库表创建一个索引
DROP INDEX???? --从数据库中删除索引
CREATE PROCEDURE?? --创建一个存储过程
DROP PROCEDURE??? --从数据库中删除存储过程
CREATE TRIGGER??? --创建一个触发器
DROP TRIGGER??? --从数据库中删除触发器
CREATE SCHEMA??? --向数据库添加一个新模式
DROP SCHEMA???? --从数据库中删除一个模式
CREATE DOMAIN??? --创建一个数据值域
ALTER DOMAIN??? --改变域定义
DROP DOMAIN???? --从数据库中删除一个域
--数据控制
GRANT????? --授予用户访问权限
DENY????? --拒绝用户访问
REVOKE????? --解除用户访问权限
--事务控制
COMMIT????? --结束当前事务
ROLLBACK???? --中止当前事务
SET TRANSACTION??? --定义当前事务数据访问特征
--程序化SQL
DECLARE????? --为查询设定游标
EXPLAN????? --为查询描述数据访问计划
OPEN????? --检索查询结果打开一个游标
FETCH????? --检索一行查询结果
CLOSE????? --关闭游标
PREPARE????? --为动态执行准备SQL 语句
EXECUTE????? --动态地执行SQL 语句
DESCRIBE???? --描述准备好的查询

代码如下:
---局部变量
declare @id char(10)
--set @id = '10010001'
select @id = '10010001'

MYSQL入门---全局变量
---必须以@@开头

MYSQL入门--IF ELSE
declare @x int @y int @z int
select @x = 1 @y = 2 @z=3
if @x > @y
print 'x > y' --打印字符串'x > y'
else if @y > @z
print 'y > z'
else print 'z > y'

MYSQL入门--CASE
use pangu
update employee
set e_wage =
case
when job_level = '1' then e_wage*1.08
when job_level = '2' then e_wage*1.07
when job_level = '3' then e_wage*1.06
else e_wage*1.05
end

MYSQL入门--WHILE CONTINUE BREAK
declare @x int @y int @c int
select @x = 1 @y=1
while @x < 3
begin
print @x --打印变量x 的值
while @y < 3
?? begin
??? select @c = 100*@x + @y
??? print @c --打印变量c 的值
??? select @y = @y + 1
?? end
select @x = @x + 1
select @y = 1
end

MYSQL入门--WAITFOR
--例 等待1 小时2 分零3 秒后才执行SELECT 语句
waitfor delay '01:02:03'
select * from employee
--例 等到晚上11 点零8 分后才执行SELECT 语句
waitfor time '23:08:00'
select * from employee

MYSQL入门***SELECT***

MYSQL入门?? select *(列名) from table_name(表名) where column_name operator value
?? ex:(宿主)
select * from stock_information where stockid?? = str(nid)
???? stockname = 'str_name'
???? stockname like '% find this %'
???? stockname like '[a-zA-Z]%' --------- ([]指定值的范围)
???? stockname like '[^F-M]%'?? --------- (^排除指定范围)
???? --------- 只能在使用like关键字的where子句中使用通配符)
???? or stockpath = 'stock_path'
???? or stocknumber < 1000
???? and stockindex = 24
???? not stocksex = 'man'
???? stocknumber between 20 and 100
???? stocknumber in(10,20,30)
???? order by stockid desc(asc) --------- 排序,desc-降序,asc-升序
???? order by 1,2 --------- by列号
???? stockname = (select stockname from stock_information where stockid = 4)
???? --------- 子查询
???? --------- 除非能确保内层select只返回一个行的值,
???? --------- 否则应在外层where子句中用一个in限定符
select distinct column_name form table_name --------- distinct指定检索独有的列值,不重复
select stocknumber,"stocknumber + 10" = stocknumber + 10 from table_name
select stockname,"stocknumber" = count(*) from table_name group by stockname
????????????????????????????????????? --------- group by 将表按行分组,指定列中有相同的值
????????? having count(*) = 2 --------- having选定指定的组

select *
from table1,table2????????????????
where table1.id *= table2.id -------- 左外部连接,table1中有的而table2中没有得以null表示
???? table1.id =* table2.id -------- 右外部连接

MYSQL入门select stockname from table1
union [all] ----- union合并查询结果集,all-保留重复行
select stockname from table2


***insert***
代码如下:
insert into table_name (Stock_name,Stock_number) value ("xxx","xxxx")
????????????? value (select Stockname,Stocknumber from Stock_table2)---value为select语句

***update***
代码如下:
update table_name set Stockname = "xxx" [where Stockid = 3]
???????? Stockname = default
???????? Stockname = null
???????? Stocknumber = Stockname + 4

***delete***
代码如下:
delete from table_name where Stockid = 3
truncate table_name ----------- 删除表中所有行,仍保持表的完整性
drop table table_name --------------- 完全删除表

***alter table*** --- 修改数据库表结构
代码如下:
alter table database.owner.table_name add column_name char(2) null .....
sp_help table_name ---- 显示表已有特征
create table table_name (name char(20),age smallint,lname varchar(30))
insert into table_name select ......... ----- 实现删除列的方法(创建新表)
alter table table_name drop constraint Stockname_default ---- 删除Stockname的default约束
?

***function(/*常用函数*/)***

MYSQL入门----统计函数----
AVG??? --求平均值
COUNT?? --统计数目
MAX??? --求最大值
MIN??? --求最小值
SUM??? --求和

代码如下:
--AVG
use pangu
select avg(e_wage) as dept_avgWage
from employee
group by dept_id

MYSQL入门--MAX
--求工资最高的员工姓名
use pangu
select e_name
from employee
where e_wage =
(select max(e_wage)
from employee)

MYSQL入门--STDEV()
--STDEV()函数返回表达式中所有数据的标准差

MYSQL入门--STDEVP()
--STDEVP()函数返回总体标准差

MYSQL入门--VAR()
--VAR()函数返回表达式中所有值的统计变异数

MYSQL入门--VARP()
--VARP()函数返回总体变异数


----算术函数----

MYSQL入门/***三角函数***/
SIN(float_expression) --返回以弧度表示的角的正弦
COS(float_expression) --返回以弧度表示的角的余弦
TAN(float_expression) --返回以弧度表示的角的正切
COT(float_expression) --返回以弧度表示的角的余切
/***反三角函数***/
ASIN(float_expression) --返回正弦是FLOAT 值的以弧度表示的角
ACOS(float_expression) --返回余弦是FLOAT 值的以弧度表示的角
ATAN(float_expression) --返回正切是FLOAT 值的以弧度表示的角
ATAN2(float_expression1,float_expression2)
??????? --返回正切是float_expression1 /float_expres-sion2的以弧度表示的角
DEGREES(numeric_expression)
?????????????????????? --把弧度转换为角度返回与表达式相同的数据类型可为
??????? --INTEGER/MONEY/REAL/FLOAT 类型
RADIANS(numeric_expression) --把角度转换为弧度返回与表达式相同的数据类型可为
??????? --INTEGER/MONEY/REAL/FLOAT 类型
EXP(float_expression) --返回表达式的指数值
LOG(float_expression) --返回表达式的自然对数值
LOG10(float_expression)--返回表达式的以10 为底的对数值
SQRT(float_expression) --返回表达式的平方根
/***取近似值函数***/
CEILING(numeric_expression) --返回>=表达式的最小整数返回的数据类型与表达式相同可为
??????? --INTEGER/MONEY/REAL/FLOAT 类型
FLOOR(numeric_expression)??? --返回<=表达式的最小整数返回的数据类型与表达式相同可为
??????? --INTEGER/MONEY/REAL/FLOAT 类型
ROUND(numeric_expression)??? --返回以integer_expression 为精度的四舍五入值返回的数据
??????? --类型与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型
ABS(numeric_expression)????? --返回表达式的绝对值返回的数据类型与表达式相同可为
??????? --INTEGER/MONEY/REAL/FLOAT 类型
SIGN(numeric_expression)???? --测试参数的正负号返回0 零值1 正数或-1 负数返回的数据类型
??????? --与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型
PI()?????? --返回值为π 即3.1415926535897936
RAND([integer_expression])?? --用任选的[integer_expression]做种子值得出0-1 间的随机浮点数

MYSQL入门
----字符串函数----
ASCII()???????? --函数返回字符表达式最左端字符的ASCII 码值
CHAR()?? --函数用于将ASCII 码转换为字符
??? --如果没有输入0 ~ 255 之间的ASCII 码值CHAR 函数会返回一个NULL 值
LOWER()?? --函数把字符串全部转换为小写
UPPER()?? --函数把字符串全部转换为大写
STR()?? --函数把数值型数据转换为字符型数据
LTRIM()?? --函数把字符串头部的空格去掉
RTRIM()?? --函数把字符串尾部的空格去掉
LEFT(),RIGHT(),SUBSTRING() --函数返回部分字符串
CHARINDEX(),PATINDEX() --函数返回字符串中某个指定的子串出现的开始位置
SOUNDEX() --函数返回一个四位字符码
??? --SOUNDEX函数可用来查找声音相似的字符串但SOUNDEX函数对数字和汉字均只返回0 值???
DIFFERENCE()??? --函数返回由SOUNDEX 函数返回的两个字符表达式的值的差异
??? --0 两个SOUNDEX 函数返回值的第一个字符不同
??? --1 两个SOUNDEX 函数返回值的第一个字符相同
??? --2 两个SOUNDEX 函数返回值的第一二个字符相同
??? --3 两个SOUNDEX 函数返回值的第一二三个字符相同
??? --4 两个SOUNDEX 函数返回值完全相同
?????????????????????????????????????

MYSQL入门QUOTENAME() --函数返回被特定字符括起来的字符串

MYSQL入门/*select quotename('abc','{') quotename('abc')
运行结果如下
----------------------------------{
{abc} [abc]*/

MYSQL入门REPLICATE()???? --函数返回一个重复character_expression 指定次数的字符串
/*select replicate('abc',3) replicate( 'abc',-2)
运行结果如下
----------- -----------
abcabcabc NULL*/

MYSQL入门REVERSE()?????? --函数将指定的字符串的字符排列顺序颠倒
REPLACE()?????? --函数返回被替换了指定子串的字符串
/*select replace('abc123g','123','def')
运行结果如下
----------- -----------
abcdefg*/

MYSQL入门SPACE()?? --函数返回一个有指定长度的空白字符串
STUFF()?? --函数用另一子串替换字符串指定位置长度的子串

MYSQL入门
----数据类型转换函数----
CAST() 函数语法如下
CAST() (<expression> AS <data_ type>[ length ])
CONVERT() 函数语法如下
CONVERT() (<data_ type>[ length ],<expression> [,style])

MYSQL入门select cast(100+99 as char) convert(varchar(12),getdate())
运行结果如下
------------------------------ ------------
199?? Jan 15 2000

MYSQL入门----日期函数----
DAY()?? --函数返回date_expression 中的日期值
MONTH()?? --函数返回date_expression 中的月份值
YEAR()?? --函数返回date_expression 中的年份值
DATEADD(<datepart>,<number>,<date>)
??? --函数返回指定日期date 加上指定的额外日期间隔number 产生的新日期
DATEDIFF(<datepart>,<date>)
??? --函数返回两个指定日期在datepart 方面的不同之处
DATENAME(<datepart>,<date>) --函数以字符串的形式返回日期的指定部分
DATEPART(<datepart>,<date>) --函数以整数值的形式返回日期的指定部分
GETDATE() --函数以DATETIME 的缺省格式返回系统当前的日期和时间

MYSQL入门----系统函数----
APP_NAME()????? --函数返回当前执行的应用程序的名称
COALESCE() --函数返回众多表达式中第一个非NULL 表达式的值
COL_LENGTH(<'table_name'>,<'column_name'>) --函数返回表中指定字段的长度值
COL_NAME(<table_id>,<column_id>)?? --函数返回表中指定字段的名称即列名
DATALENGTH() --函数返回数据表达式的数据的实际长度
DB_ID(['database_name']) --函数返回数据库的编号
DB_NAME(database_id) --函数返回数据库的名称
HOST_ID()???? --函数返回服务器端计算机的名称
HOST_NAME()???? --函数返回服务器端计算机的名称
IDENTITY(<data_type>[,seed increment]) [AS column_name])
--IDENTITY() 函数只在SELECT INTO 语句中使用用于插入一个identity column列到新表中
/*select identity(int,1,1) as column_name
into newtable
from oldtable*/
ISDATE() --函数判断所给定的表达式是否为合理日期
ISNULL(<check_expression>,<replacement_value>) --函数将表达式中的NULL 值用指定值替换
ISNUMERIC() --函数判断所给定的表达式是否为合理的数值
NEWID()?? --函数返回一个UNIQUEIDENTIFIER 类型的数值
NULLIF(<expression1>,<expression2>)
--NULLIF 函数在expression1 与expression2 相等时返回NULL 值若不相等时则返回expression1 的值

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读