查询mysql中执行效率低的sql语句的方法 |
本文标签:执行效率,sql语句 一些小技巧 复制代码 代码如下: # Set long query time to 8 seconds long_query_time=8 2. 如何查询某表的索引? 复制代码 代码如下: SHOW INDEX FROM [表名] 3. 如何查询某条语句的索引使用情况? 复制代码 代码如下: CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB; 如果你不再需要导出到错误日志文件,只要删除该表即可: 复制代码 代码如下: DROP TABLE innodb_monitor; 5. 如何定期删除庞大的日志文件? 复制代码 代码如下: expire_logs_days=10 经验教训 ID:主键;
首先,我们在日志文件中查到下面语句的执行比较慢,超过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; 哦,原来在88143条记录中要查出符合条件的295条记录,那当然慢了 。赶紧用EXPLAIN语句看一下索引使用情况吧: +----+-------------+----------+------+----------------------------------------------------------+------------------------------------+---------+-------+--------+-------------+
再看一下TSK_TASK表的索引情况吧: +----------+------------------------------------+-------------+-------------+
复制代码 代码如下: EXPLAIN select * from TSK_TASK WHERE MON_TIME >= 2007-11-22 and MON_TIME < 2007-11-23 and STATUS_ID = 1064; 但是没什么效果,MySQL还是选用系统建立的STATUS_ID外键索引 。 仔细分析一下,看来Cardinality属性(即索引中的唯一值的个数)对索引的选择起了极其重要的作用,MySQL选择了索引值唯一值个数小的那个索引作为整条语句的索引 。 针对这条语句,如果使用FK_task_status_id_TO_SYS_HIER_INFO做索引,而TSK_TASK表中存放很多天数据的话,那扫描的记录数会很多,速度较慢 。可以有以下几个优化方案: 如果一天的任务数不多的话,我们删除索引FK_task_status_id_TO_SYS_HIER_INFO,那MySQL会使用索引TSK_TASK_KEY_MON_TIME,然后在该天的数据中在扫描STATUS_ID为1064的记录,那速度也不慢;
对随时间推移数据量不断增长的表,我们可以根据时间来区分实时数据和历史数据,可以使用后台服务程序定期移动实时表中的数据到历史表中,从而控制实时表的记录数,提高查询和操作效率 。但注意每次移动的时间要足够短,不要影响正常程序的数据写入 。如果占用时间太长,可能会造成死锁问题 。 数据散列可以考虑采用federeated或sharded方式,网上有不少这方面的资料 。 复制代码 代码如下: # Set long query time to 8 seconds long_query_time=8 2. 如何查询某表的索引? 复制代码 代码如下: SHOW INDEX FROM [表名] 3. 如何查询某条语句的索引使用情况? 可用EXPLAIN语句来看一下某条SELECT语句的索引使用情况 。如果是UPDATE或DELETE语句,需要先转换为SELECT语句 。 4. 如何把导出INNODB引擎的内容到错误日志文件中? 我们可以使用SHOW INNODB STATUS命令来查看INNODB引擎的很多有用的信息,如当前进程、事务、外键错误、死锁问题和其它一些统计数据 。如何让该信息能记录在日志文件中呢?只要使用如下语句创建innodb_monitor表,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表用于保存系统监测任务,相关字段及索引如下: ID:主键;
首先,我们在日志文件中查到下面语句的执行比较慢,超过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; 哦,原来在88143条记录中要查出符合条件的295条记录,那当然慢了 。赶紧用EXPLAIN语句看一下索引使用情况吧: +----+-------------+----------+------+----------------------------------------------------------+------------------------------------+---------+-------+--------+-------------+
再看一下TSK_TASK表的索引情况吧: +----------+------------------------------------+-------------+-------------+
复制代码 代码如下: EXPLAIN select * from TSK_TASK WHERE MON_TIME >= 2007-11-22 and MON_TIME < 2007-11-23 and STATUS_ID = 1064; 但是没什么效果,MySQL还是选用系统建立的STATUS_ID外键索引 。 仔细分析一下,看来Cardinality属性(即索引中的唯一值的个数)对索引的选择起了极其重要的作用,MySQL选择了索引值唯一值个数小的那个索引作为整条语句的索引 。 针对这条语句,如果使用FK_task_status_id_TO_SYS_HIER_INFO做索引,而TSK_TASK表中存放很多天数据的话,那扫描的记录数会很多,速度较慢 。可以有以下几个优化方案: 如果一天的任务数不多的话,我们删除索引FK_task_status_id_TO_SYS_HIER_INFO,那MySQL会使用索引TSK_TASK_KEY_MON_TIME,然后在该天的数据中在扫描STATUS_ID为1064的记录,那速度也不慢;
对随时间推移数据量不断增长的表,我们可以根据时间来区分实时数据和历史数据,可以使用后台服务程序定期移动实时表中的数据到历史表中,从而控制实时表的记录数,提高查询和操作效率 。但注意每次移动的时间要足够短,不要影响正常程序的数据写入 。如果占用时间太长,可能会造成死锁问题 。 数据散列可以考虑采用federeated或sharded方式,网上有不少这方面的资料 。 复制代码 代码如下: # Set long query time to 8 seconds long_query_time=8 2. 如何查询某表的索引? 可使用SHOW INDEX语句,如: 复制代码 代码如下: SHOW INDEX FROM [表名] 3. 如何查询某条语句的索引使用情况? 复制代码 代码如下: CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB; 如果你不再需要导出到错误日志文件,只要删除该表即可: 复制代码 代码如下: DROP TABLE innodb_monitor; 5. 如何定期删除庞大的日志文件? 只要在启动配置文件中设置日志过期时间即可: 复制代码 代码如下: expire_logs_days=10 经验教训 1. 重点关注索引 下面以表TSK_TASK表为例说明SQL语句优化过程 。TSK_TASK表用于保存系统监测任务,相关字段及索引如下: ID:主键;
首先,我们在日志文件中查到下面语句的执行比较慢,超过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; 哦,原来在88143条记录中要查出符合条件的295条记录,那当然慢了 。赶紧用EXPLAIN语句看一下索引使用情况吧: +----+-------------+----------+------+----------------------------------------------------------+------------------------------------+---------+-------+--------+-------------+
再看一下TSK_TASK表的索引情况吧: +----------+------------------------------------+-------------+-------------+
复制代码 代码如下: EXPLAIN select * from TSK_TASK WHERE MON_TIME >= 2007-11-22 and MON_TIME < 2007-11-23 and STATUS_ID = 1064; 但是没什么效果,MySQL还是选用系统建立的STATUS_ID外键索引 。 仔细分析一下,看来Cardinality属性(即索引中的唯一值的个数)对索引的选择起了极其重要的作用,MySQL选择了索引值唯一值个数小的那个索引作为整条语句的索引 。 针对这条语句,如果使用FK_task_status_id_TO_SYS_HIER_INFO做索引,而TSK_TASK表中存放很多天数据的话,那扫描的记录数会很多,速度较慢 。可以有以下几个优化方案: 如果一天的任务数不多的话,我们删除索引FK_task_status_id_TO_SYS_HIER_INFO,那MySQL会使用索引TSK_TASK_KEY_MON_TIME,然后在该天的数据中在扫描STATUS_ID为1064的记录,那速度也不慢;
对随时间推移数据量不断增长的表,我们可以根据时间来区分实时数据和历史数据,可以使用后台服务程序定期移动实时表中的数据到历史表中,从而控制实时表的记录数,提高查询和操作效率 。但注意每次移动的时间要足够短,不要影响正常程序的数据写入 。如果占用时间太长,可能会造成死锁问题 。 数据散列可以考虑采用federeated或sharded方式,网上有不少这方面的资料 。 复制代码 代码如下: # Set long query time to 8 seconds long_query_time=8 2. 如何查询某表的索引? 可使用SHOW INDEX语句,如: 复制代码 代码如下: SHOW INDEX FROM [表名] 3. 如何查询某条语句的索引使用情况? 可用EXPLAIN语句来看一下某条SELECT语句的索引使用情况 。如果是UPDATE或DELETE语句,需要先转换为SELECT语句 。 4. 如何把导出INNODB引擎的内容到错误日志文件中? 我们可以使用SHOW INNODB STATUS命令来查看INNODB引擎的很多有用的信息,如当前进程、事务、外键错误、死锁问题和其它一些统计数据 。如何让该信息能记录在日志文件中呢?只要使用如下语句创建innodb_monitor表,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表用于保存系统监测任务,相关字段及索引如下: ID:主键;
首先,我们在日志文件中查到下面语句的执行比较慢,超过10秒了: # Query_time: 18 Lock_time: 0 Rows_sent: 295 Rows_examined: 88143
+----+-------------+----------+------+----------------------------------------------------------+------------------------------------+---------+-------+--------+-------------+
再看一下TSK_TASK表的索引情况吧: +----------+------------------------------------+-------------+-------------+
复制代码 代码如下: EXPLAIN select * from TSK_TASK WHERE MON_TIME >= 2007-11-22 and MON_TIME < 2007-11-23 and STATUS_ID = 1064; 但是没什么效果,MySQL还是选用系统建立的STATUS_ID外键索引 。 仔细分析一下,看来Cardinality属性(即索引中的唯一值的个数)对索引的选择起了极其重要的作用,MySQL选择了索引值唯一值个数小的那个索引作为整条语句的索引 。 针对这条语句,如果使用FK_task_status_id_TO_SYS_HIER_INFO做索引,而TSK_TASK表中存放很多天数据的话,那扫描的记录数会很多,速度较慢 。可以有以下几个优化方案: 如果一天的任务数不多的话,我们删除索引FK_task_status_id_TO_SYS_HIER_INFO,那MySQL会使用索引TSK_TASK_KEY_MON_TIME,然后在该天的数据中在扫描STATUS_ID为1064的记录,那速度也不慢;
对随时间推移数据量不断增长的表,我们可以根据时间来区分实时数据和历史数据,可以使用后台服务程序定期移动实时表中的数据到历史表中,从而控制实时表的记录数,提高查询和操作效率 。但注意每次移动的时间要足够短,不要影响正常程序的数据写入 。如果占用时间太长,可能会造成死锁问题 。 数据散列可以考虑采用federeated或sharded方式,网上有不少这方面的资料 。 复制代码 代码如下: select @a=DRClass1, @b=DRClass2, @c=DRClass3, @d=DRClass4, @e=DRClass5 from Teacher Where TeacherID = @TeacherID create table classname(classname char(50)) if (@c is not null) if (@d is not null) select * from classname 以上这些SQL语句能不能转成一个存储过程?我自己试了下 复制代码 代码如下: ALTER PROCEDURE Pr_GetClass @TeacherID int, select @a=DRClass1, @b=DRClass2, @c=DRClass3, @d=DRClass4, @e=DRClass5 from Teacher Where TeacherID = @TeacherID insert into classname (classname) values (@a) if (@c is not null) if (@d is not null) select * from classname 但是这样的话,这个存储过程就有6个变量,实际上应该只提供一个变量就可以了 主要的问题就是自己没搞清楚 @a,@b,@C,@d 等是临时变量,是放在as后面重新做一些申明的,而不是放在开头整个存储过程的变量定义 。 (标准化越来越近了):namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 实战SQL语句收集(不断更新中--) 前言:这里将我编程实践中遇到的有价值的sql语句一路记下来,一方面方便自己查用,一方面也夯实下即将遗忘的回忆 。整个过程中我会不断更新,直到不能再加为止,同时,这里只记录最实用的咚咚,不效仿学院派的那一套 。
一、常用SQL语句荟萃 1,查询: 1.1,简单查询:select * from table where 1.2,连接查询: 什么是连接查询?顾名释义,就是查询时涉及多个表的查询 。是以说到连接,废话一下,要知道连接还是关系数据库的主要特点呢 。 连接查询分为三种:外连接(OUTER JOIN),内连接(INNER JOIN),交叉连接(CROSS JOIN) 。 (标准化越来越近了):namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />1.2.1,内连接(INNER JOIN)使用比较运算符进行表间某(些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行 。根据所使用的比较方式不同,内连接又分为等值连接、自然连接和不等连接三种 。 1.2.2,外连接分为左外连接(LEFT OUTER JOIN或LEFT JOIN)、右外连接(RIGHT OUTER JOIN或RIGHT JOIN)和全外连接(FULL OUTER JOIN或FULL JOIN)三种 。与内连接不同的是,外连接不只列出与连接条件相匹配的行,而是列出左表(左外连接时)、右表(右外连接时)或两个表(全外连接时)中所有符合搜索条件的数据行 。 1.2.3,交叉连接(CROSS JOIN)没有WHERE 子句,它返回连接表中所有数据行的笛卡尔积,其结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数 。连接操作中的ON (join_condition) 子句指出连接条件,它由被连接表中的列和比较运算符、逻辑运算符等构成 。 1.2.4,无论哪种连接都不能对text、ntext和image数据类型列进行直接连接,但可以对这三种列进行间接连接 。例如: SELECT p1.pub_id,p2.pub_id,p1.pr_info 1.2.5,使用WHERE子句设置查询条件 WHERE子句设置查询条件,过滤掉不需要的数据行 。例如下面语句查询年龄大于20的数据: 复制代码 代码如下: SELECT * FROM usertable WHERE age>20 WHERE子句可包括各种条件运算符: 比较运算符(大小比较):>、>=、=、<、<=、<>、!>、!< 范围运算符(表达式值是否在指定的范围):BETWEEN…AND… NOT BETWEEN…AND… 列表运算符(判断表达式是否为列表中的指定项):IN (项1,项2……) NOT IN (项1,项2……) 模式匹配符(判断值是否与指定的字符通配格式相符):LIKE、NOT LIKE 空值判断符(判断表达式是否为空):IS NULL、NOT IS NULL 逻辑运算符(用于多条件的逻辑连接):NOT、AND、OR 1、范围运算符例:age BETWEEN 10 AND 30相当于age>=10 AND age<=30 2、列表运算符例:country IN (Germany,China) 3、模式匹配符例:常用于模糊查找,它判断列值是否与指定的字符串格式相匹配 。可用于char、varchar、text、ntext、datetime和smalldatetime等类型查询 。 可使用以下通配字符: 百分号%:可匹配任意类型和长度的字符,如果是中文,请使用两个百分号即%% 。 下划线_:匹配单个任意字符,它常用来限制表达式的字符长度 。 方括号[]:指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个 。 [^]:其取值也[] 相同,但它要求所匹配对象为指定字符以外的任一个字符 。 例如: 限制以Publishing结尾,使用LIKE %Publishing 限制以A开头:LIKE [A]% 限制以A开头外:LIKE [^A]% 空值判断符例:WHERE age IS NULL 2,更新:update table
3,插入: 3.1,一般插入: 复制代码 代码如下: INSERT INTO publishers (pub_id, pub_name, city, state) VALUES (9001, Acme Publishing, New York, NY) 3.2,插入多行 使用 INSERT 语句可以向表添加多行数据 。这些多行数据是从已经存有这些数据的另一个表中选取的 。本例中,向 pubhold 表中添加有关在加利福尼亚和德克萨斯州的出版商的数据 。这些数据可从 publishers 表中获得 。 复制代码 代码如下: INSERT pubhpold SELECT * FROM publishers WHERE state = CA OR state = TX 4,删除: 4.1,Delete语句联合删除: 复制代码 代码如下: DELETE FROM uu_SuiteToMinClassroomSect WHERE min_classroom_sect_id IN (SELECT min_classroom_sect_id FROM uu_MinClassroomSect WHERE min_classroom_id = 112) 二、视图使用细则 1,一个典型的视图 复制代码 代码如下: CREATE VIEW View_uuGroupTaxis AS SELECT uu_GroupInfo.group_id, uu_GroupInfo.group_name, uu_GroupType.main_type, uu_GroupType.group_type_name, uu_GroupInfo.group_icon_url, ISNULL ((SELECT COUNT(*) FROM uu_GroupUser WHERE uu_GroupInfo.group_id = uu_GroupUser.group_id), 0) * 50 + ISNULL(uu_GroupInfo.fundCount, 0) + ISNULL ((SELECT COUNT(*) FROM Dv_Topic WHERE Dv_Topic.BoardID = uu_GroupInfo.subforum_id), 0) * 5 + ISNULL ((SELECT COUNT(*) FROM uu_GroupPhotos WHERE uu_GroupPhotos.group_id = uu_GroupInfo.group_id), 0) * 10 + ISNULL(uu_GroupInfo.topic_account, 0) * 2 + ISNULL(uu_GroupInfo.hit_account, 0) AS group_ActiveDegree, ISNULL ((SELECT COUNT(*) FROM uu_GroupUser WHERE uu_GroupInfo.group_id = uu_GroupUser.group_id), 0) AS group_memberNum, ISNULL(uu_GroupInfo.fundCount, 0) AS fundCount, (SELECT COUNT(*) FROM Dv_Topic WHERE Dv_Topic.BoardID = uu_GroupInfo.subforum_id) AS group_articleNum, (SELECT COUNT(*) FROM uu_GroupPhotos WHERE uu_GroupPhotos.group_id = uu_GroupInfo.group_id) AS group_PhotoNum, uu_GroupInfo.topic_account, uu_GroupInfo.hit_account, (SELECT user_name FROM uu_RegisterUser WHERE uu_RegisterUser.user_id = uu_GroupInfo.creator_id) AS group_CreatorName, uu_GroupInfo.create_time FROM uu_GroupInfo INNER JOIN uu_GroupType ON uu_GroupInfo.group_type_id = uu_GroupType.group_type_id 三,存储过程的创建和调用 1,存储过程的调用 复制代码 代码如下: Execute procedureName @param=value 2,一个典型的带参数存储过程 复制代码 代码如下: CREATE PROCEDURE P_delMiniclassProc @miniClassroom_id int AS declare @billtag varchar(4) set nocount on IF @miniClassroom_id is null begin return(-1) end else BEGIN TRANSACTION --删除套餐信息 DELETE FROM uu_SuiteToMinClassroomSect WHERE min_classroom_sect_id IN (SELECT min_classroom_sect_id FROM uu_MinClassroomSect WHERE min_classroom_id =@miniClassroom_id) --删除小课堂段信息 delete from uu_MinClassroomSect where min_classroom_id = @miniClassroom_id --删除小课堂用户购买记录 delete from uu_UserBuyMinClassroom where min_classroom_id = @miniClassroom_id --删除对应小课堂年级学科信息 delete from uu_MinClassroomToGradeClass where min_classroom_id = @miniClassroom_id --删除小课堂发言 delete from uu_MinClassroomDiscuss where min_classroom_id = @miniClassroom_id --删除课程讨论 DELETE FROM uu_CourseDiscuss WHERE course_id IN (SELECT course_id FROM uu_CourseInfo WHERE min_classroom_id = @miniClassroom_id) --删除用户课程收藏 SQL语句的优化是将性能低下的SQL语句转换成目的相同的性能优异的SQL语句 。 人工智能自动SQL优化就是使用人工智能技术,自动对SQL语句进行重写,从而找到性能最好的等效SQL语句 。 数据库性能的优化
数据库的优化通常可以通过对网络、硬件、操作系统、数据库参数和应用程序的优化来进行 。最常见的优化手段就是对硬件的升级 。根据统计,对网络、硬件、操作系统、数据库参数进行优化所获得的性能提升,全部加起来只占数据库系统性能提升的40%左右,其余的60%系统性能提升来自对应用程序的优化 。许多优化专家认为,对应用程序的优化可以得到80%的系统性能的提升 。 应用程序的优化 应用程序的优化通常可分为两个方面:源代码和SQL语句 。由于涉及到对程序逻辑的改变,源代码的优化在时间成本和风险上代价很高,而对数据库系统性能的提升收效有限 。 为什么要优化SQL语句 . SQL语句是对数据库进行操作的惟一途径,对数据库系统的性能起着决定性的作用 。 . SQL语句消耗了70%至90%的数据库资源 。 . SQL语句独立于程序设计逻辑,对SQL语句进行优化不会影响程序逻辑 。 . SQL语句有不同的写法,在性能上的差异非常大 。 . SQL语句易学,但难精通 。 优化SQL语句的传统方法是通过手工重写来对SQL语句进行优化 。DBA或资深程序员通过对SQL语句执行计划的分析,依靠经验,尝试重写SQL语句,然后对结果和性能进行比较,以试图找到性能较佳的SQL语句 。这种传统上的作法无法找出SQL语句的所有可能写法,且依赖于人的经验,非常耗费时间 。 SQL优化技术的发展历程 第一代SQL优化工具是执行计划分析工具 。这类工具针对输入的SQL语句,从数据库提取执行计划,并解释执行计划中关键字的含义 。 第二代SQL优化工具只能提供增加索引的建议,它通过对输入的SQL语句的执行计划的分析,来产生是否要增加索引的建议 。 第三代SQL优化工具不仅分析输入SQL语句的执行计划,还对输入的SQL语句本身进行语法分析,经过分析产生写法上的改进建议 。 人工智能自动SQL优化 SQL语句性能优化--LECCO SQL Expert 人工智能自动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语句 。 LECCO SQL Expert自动优化实例 假设我们从源代码中抽取出这条SQL语句(也可以通过内带的扫描器或监视器获得SQL语句): 复制代码 代码如下: SELECT COUNT(*) FROM EMPLOYEE swheresEXISTS (SELECT X FROM DEPARTMENT swheresEMP_DEPT=DPT_ID AND DPT_NAME LIKE AC%) AND EMP_ID IN (SELECT SAL_EMP_ID FROM EMP_SAL_HIST B swheresSAL_SALARY > 70000) 按下“优化”按钮后,经过10几秒,SQL Expert就完成了优化的过程,并在这10几秒的时间里重写产生了2267 条等价的SQL语句,其中136条SQL语句有不同的执行计划 。 接下来,我们可以对自动重写产生的136条SQL语句进行批运行测试,以选出性能最佳的等效SQL语句 。按下“批运行” 按钮,在“终止条件” 页选择“最佳运行时间SQL语句”,按“确定” 。 经过几分钟的测试运行后,我们可以发现SQL124的运行时间和反应时间最短 。运行速度约有22.75倍的提升(源SQL语句运行时间为2.73秒,SQL124运行时间为0.12秒) 。现在我们就可以把SQL124放入源代码中,结束一条SQL语句的优化工作了 。 “边做边学式训练”提升SQL开发水平 LECCO SQL Expert不仅能够找到最佳的SQL语句,它所提供的“边做边学式训练”还能够教开发人员和数据库管理员如何写出性能最好的SQL语句 。LECCO SQL Expert的“SQL比较器”可以标明源SQL和待选SQL间的不同之处 。 以上面优化的结果为例,为了查看源SQL语句和SQL124在写法上有什么不同,我们可以按下“比较器” 按钮,对SQL124和源SQL语句进行比较 。“SQL 比较器”将SQL124相对于源SQL语句的不同之处以蓝颜色表示了出来 。如果选择“双向比较”复选框,“SQL 比较器”可以将两条SQL语句的不同之处以蓝色表示 。当然,我们也可以从源语句和重写后的SQL 语句中任选两条进行比较 。 从比较的结果可以看到,重写后的SQL124把第一个Exists改写成了In;在字段DPT_ID上进行了合并空字符串的操作,以诱导数据库先执行子查询中的 复制代码 代码如下: (SELECT DPT_ID|| FROM DEPARTMENT WHERE DPT_NAME LIKE AC%) 在子查询完成后,再与EMPLOYEE表进行嵌套循环连接(Nested Loop Join) 。 如果觉得对写法的改变难以理解,还可以点中“执行计划”复选框,通过比较两条SQL语句的执行计划的不同,来了解其中的差异 。在查看执行计划过程中,如果有什么不明白的地方,可以点中“SQL信息按钮”,再点击执行计划看不明白的地方,LECCO SQL Expert的上下文敏感帮助系统将提供执行计划该处的解释 。 在“SQL比较器”中,选中“统计信息”复选框后,可得到详细的两条SQL语句运行时的统计信息比较,这对于学习不同的SQL写法对数据库资源的消耗很有帮助 。 LECCO SQL Expert优化模块的特点 LECCO SQL Expert优化模块的特点主要表现为:自动优化SQL语句;以独家的人工智能知识库“反馈式搜索引擎”来重写性能优异的SQL语句;找出所有等效的SQL语句及可能的执行计划;保证产生相同的结果;先进的SQL语法分析器能处理最复杂的SQL语句;可以重写SELECT、SELECT INTO、UPDATE、INSERT和DELETE语句;通过测试运行,为应用程序和数据库自动找到性能最好的SQL语句;提供微秒级的计时,能够优化Web应用程序和有大量用户的在线事务处理中运行时间很短的SQL语句;为开发人员提供“边做边学式训练”,迅速提高开发人员的SQL编程技能;提供上下文敏感的执行计划帮助系统和SQL运行状态帮助;不是猜测或建议,而是独一无二的SQL重写解决方案 。 写出专家级的SQL语句 LECCO SQL Expert的出现,使SQL的优化变得极其简单,只要能够写出SQL语句,它就能帮用户找到最好性能的写法 。LECCO SQL Expert不仅能在很短的时间内找到所有可能的优化方案,而且能够通过实际测试,确定最有效的优化方案 。同以往的数据库优化手段相比较,LECCO SQL Expert将数据库优化技术带到了一个崭新的技术高度,依赖人的经验、耗费大量时间、受人的思维束缚的数据库优化手段已经被高效、省时且准确的自动优化软件所取代了 。通过内建的“LECCO小助手”的帮助,即使是SQL的开发新手,也能快速且简单地写出专家级的SQL语句 。 比如现在有一人员表 (表名: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 可以实现上述效果. select语句前加: Transact_SQL小手册 *******************Transact_SQL******************** --语 句 功 能 复制代码 代码如下: ---局部变量 declare @id char(10) --set @id = 10010001 select @id = 10010001 ---全局变量 --IF ELSE --CASE --WHILE CONTINUE BREAK --WAITFOR ***SELECT*** select *(列名) from table_name(表名) where column_name operator value select stockname from table1 ***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(/*常用函数*/)*** ----统计函数---- 复制代码 代码如下: --AVG use pangu select avg(e_wage) as dept_avgWage from employee group by dept_id --MAX --STDEV() --STDEVP() --VAR() --VARP() ----算术函数---- /***三角函数***/
QUOTENAME() --函数返回被特定字符括起来的字符串 /*select quotename(abc, {) quotename(abc) REPLICATE() --函数返回一个重复character_expression 指定次数的字符串 REVERSE() --函数将指定的字符串的字符排列顺序颠倒 SPACE() --函数返回一个有指定长度的空白字符串
select cast(100+99 as char) convert(varchar(12), getdate()) ----日期函数---- ----系统函数---- |