mysql SELECT查询的速度优化详解

总的来说,要想使一个较慢速select ... where更快,应首先检查是否能增加一个索引。不同表之间的引用通常通过索引来完成。你可以使用explain语句来确定select语句使用哪些索引。参见7.4.5节,"mysql教程如何使用索引"和7.2.1节,"explain语法(获取关于select的信息)"。

下面是一些加速对myisam表的查询的一般建议:

·         为了帮助mysql更好地优化查询,在一个装载数据后的表上运行analyze table或myisamchk --analyze。这样为每一个索引更新指出有相同值的行的平均行数的值(当然,如果只有一个索引,这总是1。)mysql使用该方法来决定当你联接两个基于非常量表达式的表时选择哪个索引。你可以使用show index from tbl_name并检查cardinality值来检查表分析结果。myisamchk --description --verbose可以显示索引分布信息。

·         要想根据一个索引排序一个索引和数据,使用myisamchk --sort-index --sort-records=1(如果你想要在索引1上排序)。如果只有一个索引,想要根据该索引的次序读取所有的记录,这是使查询更快的一个好方法。但是请注意,第一次对一个大表按照这种方法排序时将花很长时间!

7.2.4. mysql怎样优化where子句
该节讨论为处理where子句而进行的优化。例子中使用了select语句,但相同的优化也适用delete和update语句中的where子句。

请注意对mysql优化器的工作在不断进行中,因此该节并不完善。mysql执行了大量的优化,本文中所列的并不详尽。

下面列出了mysql执行的部分优化:

·         去除不必要的括号:

·                        ((a and b) and c or (((a and b) and (c and d))))·                -> (a and b and c) or (a and b and c and d)·         常量重叠:

·                   (a<b and b=c) and a=5·                -> b>5 and b=c and a=5·         去除常量条件(由于常量重叠需要):

·                   (b>=5 and b=5) or (b=6 and 5=5) or (b=7 and 5=6)·                -> b=5 or b=6·         索引使用的常数表达式仅计算一次。

对于myisam和heap表,在一个单个表上的没有一个where的count(*)直接从表中检索信息。当仅使用一个表时,对not null表达式也这样做。
无效常数表达式的早期检测。mysql快速检测某些select语句是不可能的并且不返回行。
如果不使用group by或分组函数(count()、min()……),having与where合并。
对于联接内的每个表,构造一个更简单的where以便更快地对表进行where计算并且也尽快跳过记录。
所有常数的表在查询中比其它表先读出。常数表为:
空表或只有1行的表。
与在一个primary key或unique索引的where子句一起使用的表,这里所有的索引部分使用常数表达式并且索引部分被定义为not null。
下列的所有表用作常数表:

mysql> select * from t where primary_key=1;mysql> select * from t1,t2           where t1.primary_key=1 and t2.primary_key=t1.id;尝试所有可能性便可以找到表联接的最好联接组合。如果所有在order by和group by的列来自同一个表,那么当联接时,该表首先被选中。
如果有一个order by子句和不同的group by子句,或如果order by或group by包含联接队列中的第一个表之外的其它表的列,则创建一个临时表。
如果使用sql_small_result,mysql使用内存中的一个临时表。
每个表的索引被查询,并且使用最好的索引,除非优化器认为使用表扫描更有效。是否使用扫描取决于是否最好的索引跨越超过30%的表。优化器更加复杂,其估计基于其它因素,例如表大小、行数和i/o块大小,因此固定比例不再决定选择使用索引还是扫描。
在一些情况下,mysql能从索引中读出行,甚至不查询数据文件。如果索引使用的所有列是数值类,那么只使用索引树来进行查询。
输出每个记录前,跳过不匹配having子句的行。
下面是一些快速查询的例子:

select count(*) from tbl_name; select min(key_part1),max(key_part1) from tbl_name; select max(key_part2) from tbl_name    where key_part1=constant; select ... from tbl_name    order by key_part1,key_part2,... limit 10; select ... from tbl_name    order by key_part1 desc, key_part2 desc, ... limit 10;下列查询仅使用索引树就可以解决(假设索引的列为数值型):

select key_part1,key_part2 from tbl_name where key_part1=val; select count(*) from tbl_name    where key_part1=val1 and key_part2=val2; select key_part2 from tbl_name group by key_part1;下列查询使用索引按排序顺序检索行,不用另外的排序:

select ... from tbl_name    order by key_part1,key_part2,... ; select ... from tbl_name    order by key_part1 desc, key_part2 desc, ... ;7.2.5. 范围优化
7.2.5.1. 单元素索引的范围访问方法
7.2.5.2. 多元素索引的范围访问方法
range访问方法使用单一索引来搜索包含在一个或几个索引值距离内的表记录的子集。可以用于单部分或多元素索引。后面的章节将详细描述如何从where子句提取区间。

7.2.5.1. 单元素索引的范围访问方法
对于单元素索引,可以用where子句中的相应条件很方便地表示索引值区间,因此我们称为范围条件而不是"区间"。

单元素索引范围条件的定义如下:

·         对于btree和hash索引,当使用=、<=>、in、is null或者is not null操作符时,关键元素与常量值的比较关系对应一个范围条件。

·         对于btree索引,当使用>、<、>=、<=、between、!=或者<>,或者like 'pattern'(其中 'pattern'不以通配符开始)操作符时,关键元素与常量值的比较关系对应一个范围条件。

·         对于所有类型的索引,多个范围条件结合or或and则产生一个范围条件。

前面描述的"常量值"系指:

·         查询字符串中的常量

·         同一联接中的const或system表中的列

·         无关联子查询的结果

·         完全从前面类型的子表达式组成的表达式

下面是一些where子句中有范围条件的查询的例子:

select * from t1     where key_col > 1     and key_col < 10; select * from t1     where key_col = 1     or key_col in (15,18,20); select * from t1     where key_col like 'ab%'     or key_col between 'bar' and 'foo'; 请注意在常量传播阶段部分非常量值可以转换为常数。

mysql尝试为每个可能的索引从where子句提取范围条件。在提取过程中,不能用于构成范围条件的条件被放弃,产生重叠范围的条件组合到一起,并且产生空范围的条件被删除。

例如,考虑下面的语句,其中key1是有索引的列,nonkey没有索引:

select * from t1 where   (key1 < 'abc' and (key1 like 'abcde%' or key1 like '%b')) or   (key1 < 'bar' and nonkey = 4) or   (key1 < 'uux' and key1 > 'z');key1的提取过程如下:

1.    用原始where子句开始:

2.    (key1 < 'abc' and (key1 like 'abcde%' or key1 like '%b')) or

3.     (key1 < 'bar' and nonkey = 4) or

4.     (key1 < 'uux' and key1 > 'z')

5.    删除nonkey = 4和key1 like '%b',因为它们不能用于范围扫描。删除它们的正确途径是用true替换它们,以便进行范围扫描时不会丢失匹配的记录。用true替换它们后,可以得到:

6.            (key1 < 'abc' and (key1 like 'abcde%' or true)) or7.            (key1 < 'bar' and true) or8.            (key1 < 'uux' and key1 > 'z')9.    取消总是为true或false的条件:

·         (key1 like 'abcde%' or true)总是true

·         (key1 < 'uux' and key1 > 'z')总是false

用常量替换这些条件,我们得到:

(key1 < 'abc' and true) or (key1 < 'bar' and true) or (false)删除不必要的true和false常量,我们得到

(key1 < 'abc') or (key1 < 'bar')10.将重叠区间组合成一个产生用于范围扫描的最终条件:

11.        (key1 < 'bar')总的来说(如前面的例子所述),用于范围扫描的条件比where子句限制少。mysql再执行检查以过滤掉满足范围条件但不完全满足where子句的行。

范围条件提取算法可以处理嵌套的任意深度的and/or结构,并且其输出不依赖条件在where子句中出现的顺序

时间: 2024-11-05 16:34:28

mysql SELECT查询的速度优化详解的相关文章

MySQL my.cnf参数配置优化详解

MySQL my.cnf参数配置优化详解 本配置文件针对Dell R710,双至强E5620.16G内存的硬件配置.CentOS 5.6 64位系统,MySQL 5.5.x 稳定版.适用于日IP 50-100w,PV 100-300w的站点,主要使用InnoDB存储引擎.其他应用环境请根据实际情况来设置优化. 注:你的MySQL 版本可能和这里用的不同,所以有些参数会废弃,有些被替代,当发现启动异常或者使用异常时,请取消某些配置. # 客户端 # 以下选项会被MySQL客户端应用读取.注意只有M

Mysql慢查询使用与参数详解

慢查询为系统中查询时间超过long_query_time的值,分析慢查询是优化SQL的基础,默认清下Mysql慢查询为关闭状态,可以通过 show variables where Variable_name = 'log_slow_queries'; 来查看是否开启,如果为OFF则需要修改mysql配置文件,在mysqld下面增加以下参数 #慢查询日志地址,需要mysql运行帐号对该目录有写权限 log-slow-queries="/log/slow.log" #当query语句大于2

MySQL Select 语句检索记录使用详解

数据库最普遍的操作就是"插.查.删,改".在前在的日志中,我为大家介绍过MySQL的 insert 插入语句,也为大家介绍过 update 更新语句,以及删除语句 delete 和 truncate语句.今天就为大家来介绍一下,MySQL中唯一的检索数据语句:select语句. select 语句是SQL开发者最常用的语句,也是最强大的武器,幸运在的是,学习这个语句并不是很难. select 语句的定义: 一切都要遵循规矩来办事,所以和之前的教程一样,我们先来看一下手册上面说的 sel

MySQL慢查询日志开启分析详解介绍

(1)配置开启 Linux: 在mysql配置文件 my.cnf 中增加如下语句: log-slow-queries=/var/lib/mysql/slowquery.log #指定日志文件存放位置,可以为空,系统会给一个缺省的文件host_name-slow.log long_query_time=5 #记录超过的时间,默认为10s,这里设置为查询时间超过5s的查询语句 log-queries-not-using-indexes = on # 列出没有使用索引的查询语句 #log-querie

mysql SELECT FOR UPDATE 语句用法详解

以MySQL 的InnoDB 为例,预设的Tansaction isolation level 为REPEATABLE READ,在SELECT 的读取锁定主要分为两种方式: SELECT ... LOCK IN SHARE MODE SELECT ... FOR UPDATE 这两种方式在事务(Transaction) 进行当中SELECT 到同一个数据表时,都必须等待其它事务数据被提交(Commit)后才会执行.而主要的不同在于LOCK IN SHARE MODE 在有一方事务要Update

MySQL数据插入insert性能优化详解

对于一些数据量较大的系统,面临的问题除了是查询效率低下,还有一个很重要的问题就是插入时间长.我们就有一个业务系统,每天的数据导入需要4-5个钟.这种费时的操作其实是很有风险的,假设程序出了问题,想重跑操作那是一件痛苦的事情.因此,提高大数据量系统的MySQL insert效率是很有必要的. 经过对MySQL的测试,发现一些可以提高insert效率的方法,供大家参考参考. 1. 一条SQL语句插入多条数据. 常用的插入语句如:  代码如下 复制代码 INSERTINTO`insert_table`

MySQL慢查询日志配置方法详解

查看 MySQL 服务器的慢查询状态是否开启:     1 show variables like '%slow%';   slow_launch_time,表示超过2秒定义为慢查询 log_slow_queries 和 slow_query_log,表示慢查询已经开启 slow_query_log_file,表示慢查询日志的文件的位置   在 mysql 的配置文件 my.cnf 或 my.ini 的 [mysqld]下加入慢查询的配置语句的设置即可开启慢查询状态:   1 #定义超过指定时间

批量杀死MySQL连接的几种方法详解

批量杀死MySQL连接的几种方法详解 官网:https://dev.mysql.com/doc/refman/5.6/en/kill.html 13.7.6.4 KILL Syntax Press CTRL+C to copy KILL [CONNECTION | QUERY] processlist_id Each connection to mysqld runs in a separate thread. You can kill a thread with the KILL proces

MySql绿色版配置及使用详解

原文:MySql绿色版配置及使用详解           最近在做项目开发时用到了MySql数据库,在看了一些有关MySql的文章后,很快就上手使用了.在使用的过程中还是出现了一些问题,因为使用的是绿色免安装版的MySql所以在配置的时候出现了一些问题,该篇文章就主要针对MySql绿色版的配置及其使用进行讨论. 一.MySql概述        MySql数据库是有瑞典MySql AB公司开发,现在该公司被Oracle收购属于Oracle所有.同SQL Server类似,它也是基于关系型数据库的