Ⅰ 如何解决sql查询速度太慢
1. 执行计划中明明有使用到索引,为什么执行还是这么慢?
2. 执行计划中显示扫描行数为 644,为什么 slow log 中显示 100 多万行?
a. 我们先看执行计划,选择的索引 “INDX_BIOM_ELOCK_TASK3(TASK_ID)”。结合 sql 来看,因为有 "ORDER BY TASK_ID DESC" 子句,排序通常很慢,如果使用了文件排序性能会更差,优化器选择这个索引避免了排序。
那为什么不选 possible_keys:INDX_BIOM_ELOCK_TASK 呢?原因也很简单,TASK_DATE 字段区分度太低了,走这个索引需要扫描的行数很大,而且还要进行额外的排序,优化器综合判断代价更大,所以就不选这个索引了。不过如果我们强制选择这个索引(用 force index 语法),会看到 SQL 执行速度更快少于 10s,那是因为优化器基于代价的原则并不等价于执行速度的快慢;
b. 再看执行计划中的 type:index,"index" 代表 “全索引扫描”,其实和全表扫描差不多,只是扫描的时候是按照索引次序进行而不是行,主要优点就是避免了排序,但是开销仍然非常大。
Extra:Using where 也意味着扫描完索引后还需要回表进行筛选。一般来说,得保证 type 至少达到 range 级别,最好能达到 ref。
在第 2 点中提到的“慢日志记录Rows_examined: 1161559,看起来是全表扫描”,这里更正为“全索引扫描”,扫描行数确实等于表的行数;
c. 关于执行计划中:“rows:644”,其实这个只是估算值,并不准确,我们分析慢 SQL 时判断准确的扫描行数应该以 slow log 中的 Rows_examined 为准。
4. 优化建议:添加组合索引 IDX_REL_DEVID_TASK_ID(REL_DEVID,TASK_ID)
优化过程:
TASK_DATE 字段存在索引,但是选择度很低,优化器不会走这个索引,建议后续可以删除这个索引:
select count(*),count(distinct TASK_DATE) from T_BIOMA_ELOCK_TASK;+------------+---------------------------+| count(*) | count(distinct TASK_DATE) |+------------+---------------------------+| 1161559 | 223 |+------------+---------------------------+
在这个 sql 中 REL_DEVID 字段从命名上看选择度较高,通过下面 sql 来检验确实如此:
select count(*),count(distinct REL_DEVID) from T_BIOMA_ELOCK_TASK;+----------+---------------------------+| count(*) | count(distinct REL_DEVID) |+----------+---------------------------+| 1161559 | 62235 |+----------+---------------------------+
由于有排序,所以得把 task_id 也加入到新建的索引中,REL_DEVID,task_id 组合选择度 100%:
select count(*),count(distinct REL_DEVID,task_id) from T_BIOMA_ELOCK_TASK;+----------+-----------------------------------+| count(*) | count(distinct REL_DEVID,task_id) |+----------+-----------------------------------+| 1161559 | 1161559 |+----------+-----------------------------------+
在测试环境添加 REL_DEVID,TASK_ID 组合索引,测试 sql 性能:alter table T_BIOMA_ELOCK_TASK add index idx_REL_DEVID_TASK_ID(REL_DEVID,TASK_ID);
添加索引后执行计划:
这里还要注意一点“隐式转换”:REL_DEVID 字段数据类型为 varchar,需要在 sql 中加引号:AND T.REL_DEVID = 000000025xxx >> AND T.REL_DEVID = '000000025xxx'
执行时间从 10s+ 降到 毫秒级别:
1 row in set (0.00 sec)
结论
一个典型的 order by 查询的优化,添加更合适的索引可以避免性能问题:执行计划使用索引并不意味着就能执行快。
Ⅱ 查询特别慢 如何优化SQL
思路:
首先,要确定使用的是什么数据,
若是MSSQL,那么需要看一下查询计划,然后逐一解决慢的问题;
若是Access,那么就要看表的索引创建是否合适,另外Access还有一个弊病,就是数据库大于10MB后,速度和性能将极大的下降
Ⅲ 如何查找MySQL中查询慢的SQL语句
如何查找MySQL中查询慢的SQL语句
一、MySQL数据库有几个配置选项可以帮助我们及时捕获低效SQL语句
1,slow_query_log
这个参数设置为ON,可以捕获执行时间超过一定数值的SQL语句。
2,long_query_time
当SQL语句执行时间超过此数值时,就会被记录到日志中,建议设置为1或者更短。
3,slow_query_log_file
记录日志的文件名。
4,log_queries_not_using_indexes
这个参数设置为ON,可以捕获到所有未使用索引的SQL语句,尽管这个SQL语句有可能执行得挺快。
二、检测mysql中sql语句的效率的方法
1、通过查询日志
(1)、Windows下开启MySQL慢查询
MySQL在Windows系统中的配置文件一般是是my.ini找到[mysqld]下面加上
代码如下
log-slow-queries = F:/MySQL/log/mysqlslowquery。log
long_query_time = 2
(2)、Linux下启用MySQL慢查询
MySQL在Windows系统中的配置文件一般是是my.cnf找到[mysqld]下面加上
代码如下
log-slow-queries=/data/mysqldata/slowquery。log
long_query_time=2
说明
log-slow-queries = F:/MySQL/log/mysqlslowquery。
为慢查询日志存放的位置,一般这个目录要有MySQL的运行帐号的可写权限,一般都将这个目录设置为MySQL的数据存放目录;
long_query_time=2中的2表示查询超过两秒才记录;
2.show processlist 命令
SHOW PROCESSLIST显示哪些线程正在运行。您也可以使用mysqladmin processlist语句得到此信息。
各列的含义和用途:
ID列
一个标识,你要kill一个语句的时候很有用,用命令杀掉此查询 /*/mysqladmin kill 进程号。
user列
显示单前用户,如果不是root,这个命令就只显示你权限范围内的sql语句。
host列
显示这个语句是从哪个ip的哪个端口上发出的。用于追踪出问题语句的用户。
db列
显示这个进程目前连接的是哪个数据库。
command列
显示当前连接的执行的命令,一般就是休眠(sleep),查询(query),连接(connect)。
time列
此这个状态持续的时间,单位是秒。
state列
显示使用当前连接的sql语句的状态,很重要的列,后续会有所有的状态的描述,请注意,state只是语句执行中的某一个状态,一个 sql语句,以查询为例,可能需要经过ing to tmp table,Sorting result,Sending data等状态才可以完成
info列
显示这个sql语句,因为长度有限,所以长的sql语句就显示不全,但是一个判断问题语句的重要依据。
这个命令中最关键的就是state列,mysql列出的状态主要有以下几种:
Checking table
正在检查数据表(这是自动的)。
Closing tables
正在将表中修改的数据刷新到磁盘中,同时正在关闭已经用完的表。这是一个很快的操作,如果不是这样的话,就应该确认磁盘空间是否已经满了或者磁盘是否正处于重负中。
Connect Out
复制从服务器正在连接主服务器。
Copying to tmp table on disk
由于临时结果集大于tmp_table_size,正在将临时表从内存存储转为磁盘存储以此节省内存。
Creating tmp table
正在创建临时表以存放部分查询结果。
deleting from main table
服务器正在执行多表删除中的第一部分,刚删除第一个表。
deleting from reference tables
服务器正在执行多表删除中的第二部分,正在删除其他表的记录。
Flushing tables
正在执行FLUSH TABLES,等待其他线程关闭数据表。
Killed
发送了一个kill请求给某线程,那么这个线程将会检查kill标志位,同时会放弃下一个kill请求。MySQL会在每次的主循环中检查kill标志位,不过有些情况下该线程可能会过一小段才能死掉。如果该线程程被其他线程锁住了,那么kill请求会在锁释放时马上生效。
Locked
被其他查询锁住了。
Sending data
正在处理SELECT查询的记录,同时正在把结果发送给客户端。
Sorting for group
正在为GROUP BY做排序。
Sorting for order
正在为ORDER BY做排序。
Opening tables
这个过程应该会很快,除非受到其他因素的干扰。例如,在执ALTER TABLE或LOCK TABLE语句行完以前,数据表无法被其他线程打开。正尝试打开一个表。
Removing plicates
正在执行一个SELECT DISTINCT方式的查询,但是MySQL无法在前一个阶段优化掉那些重复的记录。因此,MySQL需要再次去掉重复的记录,然后再把结果发送给客户端。
Reopen table
获得了对一个表的锁,但是必须在表结构修改之后才能获得这个锁。已经释放锁,关闭数据表,正尝试重新打开数据表。
Repair by sorting
修复指令正在排序以创建索引。
Repair with keycache
修复指令正在利用索引缓存一个一个地创建新索引。它会比Repair by sorting慢些。
Searching rows for update
正在讲符合条件的记录找出来以备更新。它必须在UPDATE要修改相关的记录之前就完成了。
Sleeping
正在等待客户端发送新请求.
System lock
正在等待取得一个外部的系统锁。如果当前没有运行多个mysqld服务器同时请求同一个表,那么可以通过增加--skip-external-locking参数来禁止外部系统锁。
Upgrading lock
INSERT DELAYED正在尝试取得一个锁表以插入新记录。
Updating
正在搜索匹配的记录,并且修改它们。
User Lock
正在等待GET_LOCK()。
Waiting for tables
该线程得到通知,数据表结构已经被修改了,需要重新打开数据表以取得新的结构。然后,为了能的重新打开数据表,必须等到所有其他线程关闭这个表。以下几种情况下会产生这个通知:FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE,或OPTIMIZE TABLE。
waiting for handler insert
INSERT DELAYED已经处理完了所有待处理的插入操作,正在等待新的请求。
大部分状态对应很快的操作,只要有一个线程保持同一个状态好几秒钟,那么可能是有问题发生了,需要检查一下。
还有其他的状态没在上面中列出来,不过它们大部分只是在查看服务器是否有存在错误是才用得着。
例如如图:
3、explain来了解SQL执行的状态
explain显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。
使用方法,在select语句前加上explain就可以了:
例如:
explain select surname,first_name form a,b where a.id=b.id
结果如图
EXPLAIN列的解释
table
显示这一行的数据是关于哪张表的
type
这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALL
possible_keys
显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句
key
实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MYSQL会选择优化不足的索引。这种情况下,可以在SELECT语句 中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MYSQL忽略索引
key_len
使用的索引的长度。在不损失精确性的情况下,长度越短越好
ref
显示索引的哪一列被使用了,如果可能的话,是一个常数
rows
MYSQL认为必须检查的用来返回请求数据的行数
Extra
关于MYSQL如何解析查询的额外信息。将在表4.3中讨论,但这里可以看到的坏的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,结果是检索会很慢
extra列返回的描述的意义
Distinct
一旦MYSQL找到了与行相联合匹配的行,就不再搜索了
Not exists
MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,就不再搜索了
Range checked for each Record(index map:#)
没有找到理想的索引,因此对于从前面表中来的每一个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一
Using filesort
看到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行
Using index
列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候
Using temporary
看到这个的时候,查询需要优化了。这里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上
Where used
使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index,这就会发生,或者是查询有问题不同连接类型的解释(按照效率高低的顺序排序)
const
表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)。因为只有一行,这个值实际就是常数,因为MYSQL先读这个值然后把它当做常数来对待
eq_ref
在连接中,MYSQL在查询时,从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用
ref
这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生。对于之前的表的每一个行联合,全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好
range
这个连接类型使用索引返回一个范围中的行,比如使用>或<查找东西时发生的情况
index
这个连接类型对前面的表中的每一个记录联合进行完全扫描(比ALL更好,因为索引一般小于表数据)
ALL
Ⅳ 如何解决SQL Server查询速度缓慢的问题
1.查询的模糊匹配
尽量避免在一个复杂查询里面使用 LIKE '%parm1%'——红色标识位置的百分号会导致相关列的索引无法使用,最好不要用.
解决办法:
其实只需要对该脚本略做改进,查询速度便会提高近百倍。改进方法如下:
a、修改前台程序——把查询条件的供应商名称一栏由原来的文本输入改为下拉列表,用户模糊输入供应商名称时,直接在前台就帮忙定位到具体的供应商,这样在调用后台程序时,这列就可以直接用等于来关联了。
b、直接修改后台——根据输入条件,先查出符合条件的供应商,并把相关记录保存在一个临时表里头,然后再用临时表去做复杂关联
2.索引问题
在做性能跟踪分析过程中,经常发现有不少后台程序的性能问题是因为缺少合适索引造成的,有些表甚至一个索引都没有。这种情况往往都是因为在设计表时,没去定义索引,而开发初期,由于表记录很少,索引创建与否,可能对性能没啥影响,开发人员因此也未多加重视。然一旦程序发布到生产环境,随着时间的推移,表记录越来越多
这时缺少索引,对性能的影响便会越来越大了。
这个问题需要数据库设计人员和开发人员共同关注
法则:不要在建立的索引的数据列上进行下列操作:
◆避免对索引字段进行计算、函数、类型转换
◆避免在索引字段上使用not,<>,!=
◆避免在索引列上使用空值、IS NULL和IS NOT NULL
3.复杂操作
部分UPDATE、SELECT 语句写得很复杂(经常嵌套多级子查询)——可以考虑适当拆成几步,先生成一些临时数据表,再进行关联操作
4.update
同一个表的修改在一个过程里出现好几十次,如:
update table1
set col1=...
where col2=...;
update table1
set col1=...
where col2=...
......
象这类脚本其实可以很简单就整合在一个UPDATE语句来完成(前些时候在协助xxx项目做性能问题分析时就发现存在这种情况)
5.在可以使用UNION ALL的语句里,使用了UNION
UNION 因为会将各查询子集的记录做比较,故比起UNIONALL ,通常速度都会慢上许多。一般来说,如果使用UNION ALL能满足要求的话,务必使用UNION ALL。还有一种情况大家可能会忽略掉,就是虽然要求几个子集的并集需要过滤掉重复记录,但由于脚本的特殊性,不可能存在重复记录,这时便应该使用UNION ALL,如xx模块的某个查询程序就曾经存在这种情况,见,由于语句的特殊性,在这个脚本中几个子集的记录绝对不可能重复,故可以改用UNION ALL)
6.在WHERE 语句中,尽量避免对索引字段进行计算操作
这个常识相信绝大部分开发人员都应该知道,但仍有不少人这么使用,我想其中一个最主要的原因可能是为了编写写简单而损害了性能,那就不可取了
9月份在对XX系统做性能分析时发现,有大量的后台程序存在类似用法,如:
......
where trunc(create_date)=trunc(:date1)
虽然已对create_date 字段建了索引,但由于加了TRUNC,使得索引无法用上。此处正确的写法应该是
where create_date>=trunc(:date1) andcreate_date
或者是
where create_date between trunc(:date1) andtrunc(:date1)+1-1/(24*60*60)
注意:因between 的范围是个闭区间(greater than or equal to low value and less than or equal to highvalue.),
故严格意义上应该再减去一个趋于0的小数,这里暂且设置成减去1秒(1/(24*60*60)),如果不要求这么精确的话,可以略掉这步。
7.对Where 语句的法则
7.1避免在WHERE子句中使用in,not in,or 或者having。
可以使用 exist 和not exist代替 in和not in。
可以使用表链接代替 exist。Having可以用where代替,如果无法代替可以分两步处理。
例子
SELECT * FROM ORDERS WHERE CUSTOMER_NAME NOT IN
(SELECT CUSTOMER_NAME FROM CUSTOMER)
优化
SELECT * FROM ORDERS WHERE CUSTOMER_NAME not exist
(SELECT CUSTOMER_NAME FROM CUSTOMER)
7.2 不要以字符格式声明数字,要以数字格式声明字符值。(日期同样)否则会使索引无效,产生全表扫描。
例子使用:
SELECT emp.ename, emp.jobFROM emp WHERE emp.empno = 7369;
不要使用:SELECT emp.ename,emp.job FROM emp WHERE emp.empno = ‘7369’
8.对Select语句的法则
在应用程序、包和过程中限制使用select * from table这种方式。看下面例子
使用SELECT empno,ename,categoryFROM emp WHERE empno = '7369‘
而不要使用SELECT * FROM empWHERE empno = '7369'
9. 排序
避免使用耗费资源的操作,带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎 执行,耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序
10.临时表
慎重使用临时表可以极大的提高系统性能
所谓的优化就是WHERE子句利用了索引,不可优化即发生了表扫描或额外开销。经验显示,SQL Server性能的最大改进得益于逻辑的数据库设计、索引设计和查询设计方面。反过来说,最大的性能问题常常是由其中这些相同方面中的不足引起的。其实SQL优化的实质就是在结果正确的前提下,用优化器可以识别的语句,充份利用索引,减少表扫描的I/O次数,尽量避免表搜索的发生。
其实SQL的性能优化是一个复杂的过程,上述这些只是在应用层次的一种体现,深入研究还会涉及数据库层的资源配置、网络层的流量控制以及操作系统层的总体设计。
Ⅳ 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 server数据库查询慢怎么优化
在安装有SQLServer数据库的计算机上,我们在使用数据库的过程中,有时候会在任务管理器里发现sqlservr.exe这个进程的内存和CPU占用率较高。
接下来我们来看一下,如何解决上面这个问题,需要设置SQLServer数据库的内存配置。登录数据库,这里使用的是SQLServer2008,右键点击最上方的服务器名,在弹出的菜单中,点击【属性】
打开服务器属性窗口。默认显示的是第一项【常规】内容,点击第二项【内存】进行内存配置。
点击【内存】后,打开服务器内存选项配置界面。这里的【使用AWE分配内存】可以对内存进行扩展支持,我们要做的是更改下方的最大服务器内存。这个数值根据自己服务器内存大小来做适当设置。
5
个人建议设置本机内存的一半或稍微高一点,如机器内存为2G,那么我们这里填写1000。需要注意的是内存设置调小以后,在数据库执行较复杂SQL语句的时候,可能会比较慢,出现这种情况,我们再适当上调最大内存配置大小。
Ⅶ 如何用慢查询快速定位执行慢的SQL
慢查询可以帮助企业找到执行慢的SQL,开启了慢查询日志,并设置了相应的慢查询时间阈值之后,只需要查询时间大于这个阈值的SQL语句都会保存在慢查询日志中,然后就可以通过工具提取到想要查找的SQL语句了。对于懂这方面知道的技术人才可能并不是很难,但对于没有接触过的人员来说还是比较复杂的,其实你可以可以找第三方提供商帮你做这些服务,听云有了解过吗?听云提供数字化业务运维解决方案,围绕企业的信息化与数字化业务提供一套覆盖用户端、网络、服务器端全栈实时的监控与大数据智能分析平台,对于慢的SQL就可以快递的跟踪定位问题、解决问题。
Ⅷ 如何优化慢查询的SQL语句
优化方法一般从几个方面这几个考虑:
1、根据业务情况,精简代码逻辑,
2、根据读写方式,降低数据表读写量
3、关键条件列增加合适的索引
4、对于碎片多的索引进行重建
多数情况下只需要考虑前两条就能解决很大的效率问题,业务模式可能在最初开发的时候,因需求分析不彻底,或者需求理解不深入,导致逻辑不合理,或者后续多次变动业务模式,新增功能与最初的开发理念发生变化,这时就应该对代码的逻辑进行重新优化改写。