当前位置:首页 » 编程语言 » sql效率分析

sql效率分析

发布时间: 2023-10-26 20:54:32

① 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这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免

② 执行效率的方法,从哪些方面,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语句性能如何分析

一段SQL代码写好以后,可以通过查看SQL的执行计划,初步预测该SQL在运行时的性能好坏,尤其是在发现某个SQL语句的效率较差时,我们可以通过查看执行计划,分析出该SQL代码的问题所在。

1、 打开熟悉的查看工具:PL/SQL Developer。
在PL/SQL Developer中写好一段SQL代码后,按F5,PL/SQL Developer会自动打开执行计划窗口,显示该SQL的执行计划。

2、 查看总COST,获得资源耗费的总体印象
一般而言,执行计划第一行所对应的COST(即成本耗费)值,反应了运行这段SQL的总体估计成本,单看这个总成本没有实际意义,但可以拿它与相同逻辑不同执行计划的SQL的总体COST进行比较,通常COST低的执行计划要好一些。

3、 按照从左至右,从上至下的方法,了解执行计划的执行步骤
执行计划按照层次逐步缩进,从左至右看,缩进最多的那一步,最先执行,如果缩进量相同,则按照从上而下的方法判断执行顺序,可粗略认为上面的步骤优先执行。每一个执行步骤都有对应的COST,可从单步COST的高低,以及单步的估计结果集(对应ROWS/基数),来分析表的访问方式,连接顺序以及连接方式是否合理。

4、 分析表的访问方式
表的访问方式主要是两种:全表扫描(TABLE ACCESS FULL)和索引扫描(INDEX SCAN),如果表上存在选择性很好的索引,却走了全表扫描,而且是大表的全表扫描,就说明表的访问方式可能存在问题;若大表上没有合适的索引而走了全表扫描,就需要分析能否建立索引,或者是否能选择更合适的表连接方式和连接顺序以提高效率。

5、 分析表的连接方式和连接顺序
表的连接顺序:就是以哪张表作为驱动表来连接其他表的先后访问顺序。
表的连接方式:简单来讲,就是两个表获得满足条件的数据时的连接过程。主要有三种表连接方式,嵌套循环(NESTED LOOPS)、哈希连接(HASH JOIN)和排序-合并连接(SORT MERGE JOIN)。我们常见得是嵌套循环和哈希连接。
嵌套循环:最适用也是最简单的连接方式。类似于用两层循环处理两个游标,外层游标称作驱动表,Oracle检索驱动表的数据,一条一条的代入内层游标,查找满足WHERE条件的所有数据,因此内层游标表中可用索引的选择性越好,嵌套循环连接的性能就越高。
哈希连接:先将驱动表的数据按照条件字段以散列的方式放入内存,然后在内存中匹配满足条件的行。哈希连接需要有合适的内存,而且必须在CBO优化模式下,连接两表的WHERE条件有等号的情况下才可以使用。哈希连接在表的数据量较大,表中没有合适的索引可用时比嵌套循环的效率要高。

热点内容
诺安成长与鑫灵活配置哪个好 发布:2025-01-31 19:58:54 浏览:604
b树磁盘存储 发布:2025-01-31 19:42:53 浏览:837
联想小新air15怎么配置环境 发布:2025-01-31 19:06:57 浏览:968
什么配置玩3a 发布:2025-01-31 19:05:22 浏览:586
phpoa系统 发布:2025-01-31 18:58:42 浏览:10
值e的编程 发布:2025-01-31 18:57:06 浏览:977
安卓手机的软件认证在哪里 发布:2025-01-31 18:57:01 浏览:535
android弹出来 发布:2025-01-31 18:56:56 浏览:232
办公室白领新解压方法 发布:2025-01-31 18:55:23 浏览:558
摩斯密码短长是什么意思 发布:2025-01-31 18:50:17 浏览:587