sql语句效率
Ⅰ 项目中优化sql语句执行效率的方法是什么
1. SQL优化的原则是:将一次操作需要读取的BLOCK数减到最低,即在最短的时间达到最大的数据吞吐量。 调整不良SQL通常可以从以下几点切入: ? 检查不良的SQL,考虑其写法是否还有可优化内容 ? 检查子查询 考虑SQL子查询是否可以用简单连接的方式进行重新书写 ? 检查优化索引的使用 ? 考虑数据库的优化器 2. 避免出现SELECT * FROM table 语句,要明确查出的字段。 3. 在一个SQL语句中,如果一个where条件过滤的数据库记录越多,定位越准确,则该where条件越应该前移。 4. 查询时尽可能使用索引覆盖。即对SELECT的字段建立复合索引,这样查询时只进行索引扫描,不读取数据块。 5. 在判断有无符合条件的记录时建议不要用SELECT COUNT (*)和select top 1 语句。 6. 使用内层限定原则,在拼写SQL语句时,将查询条件分解、分类,并尽量在SQL语句的最里层进行限定,以减少数据的处理量。 7. 应绝对避免在order by子句中使用表达式。 8. 如果需要从关联表读数据,关联的表一般不要超过7个。 9. 小心使用 IN 和 OR,需要注意In集合中的数据量。建议集合中的数据不超过200个。 10. <> 用 < 、 > 代替,>用>=代替,<用<=代替,这样可以有效的利用索引。 11. 在查询时尽量减少对多余数据的读取包括多余的列与多余的行。 12. 对于复合索引要注意,例如在建立复合索引时列的顺序是F1,F2,F3,则在where或order by子句中这些字段出现的顺序要与建立索引时的字段顺序一致,且必须包含第一列。只能是F1或F1,F2或F1,F2,F3。否则不会用到该索引。 13. 多表关联查询时,写法必须遵循以下原则,这样做有利于建立索引,提高查询效率。格式如下select sum(table1.je) from table1 table1, table2 table2, table3 table3 where (table1的等值条件(=)) and (table1的非等值条件) and (table2与table1的关联条件) and (table2的等值条件) and (table2的非等值条件) and (table3与table2的关联条件) and (table3的等值条件) and (table3的非等值条件)。 注:关于多表查询时from 后面表的出现顺序对效率的影响还有待研究。 14. 子查询问题。对于能用连接方式或者视图方式实现的功能,不要用子查询。例如:select name from customer where customer_id in ( select customer_id from order where money>1000)。应该用如下语句代替:select name from customer inner join order on customer.customer_id=order.customer_id where order.money>100。 15. 在WHERE 子句中,避免对列的四则运算,特别是where 条件的左边,严禁使用运算与函数对列进行处理。比如有些地方 substring 可以用like代替。 16. 如果在语句中有not in(in)操作,应考虑用not exists(exists)来重写,最好的办法是使用外连接实现。 17. 对一个业务过程的处理,应该使事物的开始与结束之间的时间间隔越短越好,原则上做到数据库的读操作在前面完成,数据库写操作在后面完成,避免交叉。 18. 请小心不要对过多的列使用列函数和order by,group by等,谨慎使用disti软件开发t。 19. 用union all 代替 union,数据库执行union操作,首先先分别执行union两端的查询,将其放在临时表中,然后在对其进行排序,过滤重复的记录。 当已知的业务逻辑决定query A和query B中不会有重复记录时,应该用union all代替union,以提高查询效率。
Ⅱ 如何提高sql语句的执行效率
1、使用ordered提示
Oracle必须花费大量的时间来剖析多表的合并,用以确定表合并的最佳顺序。SQL表达式涉及七个乃至更多的表合并,那么有时就会需要超过30分钟的时间来剖析,Ordered这个提示(hint)和其他的提示一起使用能够产生合适的合并顺序。
2、使用ordered_predicates
ordered_predicates提示在查询的WHERE子句里指定的,并被用来指定布尔判断(Booleanpredicate)被评估的顺序。在没有ordered_predicates的情况下,Oracle会使用下面这些步骤来评估SQL判断的顺序:子查询的评估先于外层WHERE子句里的Boolean条件。
所有没有内置函数或者子查询的布尔条件都按照其在WHERE子句里相反的顺序进行评估,即最后一条判断最先被评估。每个判断都带有内置函数的布尔判断都依据其预计的评估值按递增排列。
3、限制表格合并评估的数量
提高SQL剖析性能的最后一种方法是强制取代Oracle的一个参数,这个参数控制着在评估一个查询的时候,基于消耗的优化器所评估的可能合并数量。
(2)sql语句效率扩展阅读:
1、表设计的优化,数据行的长度不要超过8020字节,如果超过这个长度的话在物理页中这条数据会占用两行从而造成存储碎片,降低查询效率。
2、语句的查询优化,保证在实现功能的基础上,尽量减少对数据库的访问次数;
3、建立高效的索引创建索引一般有以下两个目的:维护被索引列的唯一性和提供快速访问表中数据的策略。
大型数据库有两种索引即簇索引和非簇索引,一个没有簇索引的表是按堆结构存储数据,所有的数据均添加在表的尾部,而建立了簇索引的表,其数据在物理上会按照簇索引键的顺序存储。个表只允许有一个簇索引。
4、强制查询转换,有时候oracle 的优化器未必能走正确的查询路线,这个时候就需要添加一些hint 之类的来规定他的执行路线。当然了,这个未必是最好的处理方案。因为虽然现在走这个路线是对的,以为因为数据的变化到这这个HINT 变得不可取。
Ⅲ 在sql语句多表连接中,in、exists、join哪个效率更高一点
EXISTS、IN与JOIN,都可以用来实现形如“查询A表中在(或不在)B表中的记录”的查询逻辑。
在查询的两个表大小相当的情况下,3种查询方式的执行时间通常是:
EXISTS <= IN <= JOIN
NOT EXISTS <= NOT IN <= LEFT JOIN
只有当表中字段允许NULL时,NOT IN的方式最慢:
NOT EXISTS <= LEFT JOIN <= NOT IN
但是如果两个表中一个较小,一个较大,则子查询表大的用exists,子查询表小的用in,因为in 是把外表和内表作hash 连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。而无论那个表大,用not exists都比not in要快。这是因为如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。
IN的好处是逻辑直观简单(通常是独立子查询);缺点是只能判断单字段,并且当NOT IN时效率较低,而且NULL会导致不想要的结果。
EXISTS的好处是效率高,可以判断单字段和组合字段,并不受NULL的影响;缺点是逻辑稍微复杂(通常是相关子查询)。
JOIN用在这种场合,往往是吃力不讨好。JOIN的用途是联接两个表,而不是判断一个表的记录是否在另一个表。
Ⅳ 怎样提升SQL语句的查询速度
1.选择最有效率的表名顺序。ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理. 在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表。
2.WHERE子句中的连接顺序。ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。
3.SELECT子句中尽量避免使用 ‘* ’。
4.使用DECODE函数来减少处理时间。
5.查询结果能不排序就不排序。尽量不用Order by,distinct,union,MINUS,INTERSECT。
6.用表连接代替子查询in。
7.用索引提高查询效率。但是索引不能随便用,还要搞清楚每种索引适用的情况,比如B*索引、复合索引、函数索引、bitmap索引等。虽然使用索引能得到查询效率的提高,但是也必须注意到它的代价. 索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时, 索引本身也会被修改. 这意味着每条记录的INSERT , DELETE , UPDATE将为此多付出几 次的磁盘I/O,因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢。
8.不能再索引列上适用not、<>、is null、not is null、做四则运算,否则索引会被抑制,不起作用,变成全表扫描。
9.用>=替代>。比如SELECT * FROM S WHERE ID>=4效率SELECT * FROM S WHERE ID>3高。两者的区别在于, 前者DBMS将直接跳到第一个ID等于4的记录,而后者将首先定位到ID=3的记录并且向前扫描到第一个DEPT大于3的记录。
10.如果表的数据量很大,可以为该表建分区。经常使用的子查询可以建成视图。
.
.
.
.
.
.
.
.
Ⅳ MySQL中如何查看“慢查询”,如何分析执行SQL的效率
一、MySQL数据库有几个配置选项可以帮助我们及时捕获低效SQL语句x0dx0ax0dx0a1,slow_query_logx0dx0a这个参数设置为ON,可以捕获执行时间超过一定数值的SQL语句。x0dx0ax0dx0a2,long_query_timex0dx0a当SQL语句执行时间超过此数值时,就会被记录到日志中,建议设置为1或者更短。x0dx0ax0dx0a3,slow_query_log_filex0dx0a记录日志的文件名。x0dx0ax0dx0a4,log_queries_not_using_indexesx0dx0a这个参数设置为ON,可以捕获到所有未使用索引的SQL语句,尽管这个SQL语句有可能执行得挺快。x0dx0ax0dx0a二、检测mysql中sql语句的效率的方法x0dx0ax0dx0a1、通过查询日志x0dx0a(1)、Windows下开启MySQL慢查询x0dx0aMySQL在Windows系统中的配置文件一般是是my.ini找到[mysqld]下面加上x0dx0a代码如下x0dx0alog-slow-queries = F:/MySQL/log/mysqlslowquery。logx0dx0along_query_time = 2x0dx0ax0dx0a(2)、Linux下启用MySQL慢查询x0dx0aMySQL在Windows系统中的配置文件一般是是my.cnf找到[mysqld]下面加上x0dx0a代码如下x0dx0alog-slow-queries=/data/mysqldata/slowquery。logx0dx0along_query_time=2x0dx0a说明x0dx0alog-slow-queries = F:/MySQL/log/mysqlslowquery。x0dx0a为慢查询日志存放的位置,一般这个目录要有MySQL的运行帐号的可写权限,一般都将这个目录设置为MySQL的数据存放目录;x0dx0along_query_time=2中的2表示查询超过两秒才记录;x0dx0ax0dx0a2.show processlist 命令x0dx0ax0dx0aSHOW PROCESSLIST显示哪些线程正在运行。您也可以使用mysqladmin processlist语句得到此信息。x0dx0a各列的含义和用途:x0dx0aID列x0dx0a一个标识,你要kill一个语句的时候很有用,用命令杀掉此查询 /*/mysqladmin kill 进程号。x0dx0auser列x0dx0a显示单前用户,如果不是root,这个命令就只显示你权限范围内的sql语句。x0dx0ahost列x0dx0a显示这个语句是从哪个ip的哪个端口上发出的。用于追踪出问题语句的用户。x0dx0adb列x0dx0a显示这个进程目前连接的是哪个数据库。x0dx0acommand列x0dx0a显示当前连接的执行的命令,一般就是休眠(sleep),查询(query),连接(connect)。x0dx0atime列x0dx0a此这个状态持续的时间,单位是秒。x0dx0astate列x0dx0a显示使用当前连接的sql语句的状态,很重要的列,后续会有所有的状态的描述,请注意,state只是语句执行中的某一个状态,一个 sql语句,以查询为例,可能需要经过ing to tmp table,Sorting result,Sending data等状态才可以完成x0dx0ainfo列x0dx0a显示这个sql语句,因为长度有限,所以长的sql语句就显示不全,但是一个判断问题语句的重要依据。x0dx0ax0dx0a这个命令中最关键的就是state列,mysql列出的状态主要有以下几种:x0dx0aChecking tablex0dx0a正在检查数据表(这是自动的)。x0dx0aClosing tablesx0dx0a正在将表中修改的数据刷新到磁盘中,同时正在关闭已经用完的表。这是一个很快的操作,如果不是这样的话,就应该确认磁盘空间是否已经满了或者磁盘是否正处于重负中。x0dx0aConnect Outx0dx0a复制从服务器正在连接主服务器。x0dx0ax0dx0aCopying to tmp table on diskx0dx0a由于临时结果集大于tmp_table_size,正在将临时表从内存存储转为磁盘存储以此节省内存。x0dx0aCreating tmp tablex0dx0a正在创建临时表以存放部分查询结果。x0dx0adeleting from main tablex0dx0a服务器正在执行多表删除中的第一部分,刚删除第一个表。x0dx0adeleting from reference tablesx0dx0a服务器正在执行多表删除中的第二部分,正在删除其他表的记录。x0dx0ax0dx0aFlushing tablesx0dx0a正在执行FLUSH TABLES,等待其他线程关闭数据表。x0dx0aKilledx0dx0a发送了一个kill请求给某线程,那么这个线程将会检查kill标志位,同时会放弃下一个kill请求。MySQL会在每次的主循环中检查kill标志位,不过有些情况下该线程可能会过一小段才能死掉。如果该线程程被其他线程锁住了,那么kill请求会在锁释放时马上生效。x0dx0aLockedx0dx0a被其他查询锁住了。x0dx0aSending datax0dx0a正在处理SELECT查询的记录,同时正在把结果发送给客户端。x0dx0ax0dx0aSorting for groupx0dx0a正在为GROUP BY做排序。x0dx0aSorting for orderx0dx0a正在为ORDER BY做排序。x0dx0aOpening tablesx0dx0a这个过程应该会很快,除非受到其他因素的干扰。例如,在执ALTER TABLE或LOCK TABLE语句行完以前,数据表无法被其他线程打开。正尝试打开一个表。x0dx0aRemoving plicatesx0dx0a正在执行一个SELECT DISTINCT方式的查询,但是MySQL无法在前一个阶段优化掉那些重复的记录。因此,MySQL需要再次去掉重复的记录,然后再把结果发送给客户端。x0dx0ax0dx0aReopen tablex0dx0a获得了对一个表的锁,但是必须在表结构修改之后才能获得这个锁。已经释放锁,关闭数据表,正尝试重新打开数据表。x0dx0aRepair by sortingx0dx0a修复指令正在排序以创建索引。x0dx0aRepair with keycachex0dx0a修复指令正在利用索引缓存一个一个地创建新索引。它会比Repair by sorting慢些。x0dx0aSearching rows for updatex0dx0a正在讲符合条件的记录找出来以备更新。它必须在UPDATE要修改相关的记录之前就完成了。x0dx0aSleepingx0dx0a正在等待客户端发送新请求.x0dx0ax0dx0aSystem lockx0dx0a正在等待取得一个外部的系统锁。如果当前没有运行多个mysqld服务器同时请求同一个表,那么可以通过增加--skip-external-locking参数来禁止外部系统锁。x0dx0aUpgrading lockx0dx0aINSERT DELAYED正在尝试取得一个锁表以插入新记录。x0dx0aUpdatingx0dx0a正在搜索匹配的记录,并且修改它们。x0dx0ax0dx0aUser Lockx0dx0a正在等待GET_LOCK()。x0dx0aWaiting for tablesx0dx0a该线程得到通知,数据表结构已经被修改了,需要重新打开数据表以取得新的结构。然后,为了能的重新打开数据表,必须等到所有其他线程关闭这个表。以下几种情况下会产生这个通知:FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE,或OPTIMIZE TABLE。x0dx0awaiting for handler insertx0dx0aINSERT DELAYED已经处理完了所有待处理的插入操作,正在等待新的请求。x0dx0a大部分状态对应很快的操作,只要有一个线程保持同一个状态好几秒钟,那么可能是有问题发生了,需要检查一下。x0dx0a还有其他的状态没在上面中列出来,不过它们大部分只是在查看服务器是否有存在错误是才用得着。x0dx0ax0dx0a例如如图:x0dx0ax0dx0a3、explain来了解SQL执行的状态x0dx0aexplain显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。x0dx0a使用方法,在select语句前加上explain就可以了:x0dx0a例如:x0dx0aexplain select surname,first_name form a,b where a.id=b.idx0dx0a结果如图x0dx0ax0dx0aEXPLAIN列的解释x0dx0atablex0dx0a显示这一行的数据是关于哪张表的x0dx0atypex0dx0a这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALLx0dx0apossible_keysx0dx0a显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句x0dx0akeyx0dx0a实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MYSQL会选择优化不足的索引。这种情况下,可以在SELECT语句 中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MYSQL忽略索引x0dx0akey_lenx0dx0a使用的索引的长度。在不损失精确性的情况下,长度越短越好x0dx0arefx0dx0a显示索引的哪一列被使用了,如果可能的话,是一个常数x0dx0arowsx0dx0aMYSQL认为必须检查的用来返回请求数据的行数x0dx0aExtrax0dx0a关于MYSQL如何解析查询的额外信息。将在表4.3中讨论,但这里可以看到的坏的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,结果是检索会很慢x0dx0ax0dx0aextra列返回的描述的意义x0dx0aDistinctx0dx0a一旦MYSQL找到了与行相联合匹配的行,就不再搜索了x0dx0aNot existsx0dx0aMYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,就不再搜索了x0dx0aRange checked for each Record(index map:#)x0dx0a没有找到理想的索引,因此对于从前面表中来的每一个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一x0dx0aUsing filesortx0dx0a看到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行x0dx0aUsing indexx0dx0a列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候x0dx0aUsing temporaryx0dx0a看到这个的时候,查询需要优化了。这里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上x0dx0aWhere usedx0dx0a使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index,这就会发生,或者是查询有问题不同连接类型的解释(按照效率高低的顺序排序)x0dx0aconstx0dx0a表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)。因为只有一行,这个值实际就是常数,因为MYSQL先读这个值然后把它当做常数来对待x0dx0aeq_refx0dx0a在连接中,MYSQL在查询时,从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用x0dx0arefx0dx0a这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生。对于之前的表的每一个行联合,全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好x0dx0arangex0dx0a这个连接类型使用索引返回一个范围中的行,比如使用>或<查找东西时发生的情况x0dx0aindexx0dx0a这个连接类型对前面的表中的每一个记录联合进行完全扫描(比ALL更好,因为索引一般小于表数据)x0dx0aALLx0dx0a这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免