一、 通过查询缓冲提高查询速度

  一般我们使用SQL语句进行查询时,数据库服务器每次在收到客户端 发来SQL后,都会执行这条SQL语句。但当在一定间隔内(如1分钟内),接到完全一样的SQL语句,也同样执行它。虽然这样可以保证数据的实时性,但在 大多数时候,数据并不要求完全的实时,也就是说可以有一定的延时。如果是这样的话,在短时间内执行完全一样的SQL就有些得不偿失。
  幸好MySQL为我们提供了查询缓冲的功能(只能在MySQL 4.0.1及以上版本使用查询缓冲)。我们可以通过查询缓冲在一定程度上提高查询性能。

1、我们可以通过在MySQL安装目录中的my.ini文件设置查询缓冲:

  设置也非常简单,只需要将query_cache_type设为1
即可。在设置了这个属性后,MySQL在执行任何SELECT语句之前,都会在它的缓冲区中查询是否在相同的SELECT语句被执行过,如果有,并且执行
结果没有过期,那么就直接取查询结果返回给客户端。但在写SQL语句时注意,MySQL的查询缓冲是区分大小写的。如下列的两条SELECT语句:

SELECT * FROM TABLE1
SELECT * FROM TABLE1

  上面的两条SQL语句对于查询缓冲是完全不同的SELECT。而且查询缓冲并不自动处理空格,因此,在写SQL语句时,应尽量减少空格的使用,尤其是在SQL首和尾的空格(因为,查询缓冲并不自动截取首尾空格)。

2、临时关闭查询缓冲方法:

  虽然不设置查询缓冲,有时可能带来性能上的损失,但有一些SQL语句需要实时地查询数据,或者并不经常使用(可能一天就执行一两次)。这样就需要把缓冲关了。当然,这可以通过设置query_cache_type的值来关闭查询缓冲,但这就将查询缓冲永久地关闭了。
  在MySQL 5.0中提供了一种可以临时关闭查询缓冲的方法:SQL_NO_CACHE。

SELECT SQL_NO_CACHE field1, field2 FROM TABLE1

  以上的SQL语句由于使用了SQL_NO_CACHE,因此,不管这条SQL语句是否被执行过,服务器都不会在缓冲区中查找,每次都会执行它。

3、临时开启查询缓冲方法:

  我们还可以将my.ini中的query_cache_type设成2,这样只有在使用了SQL_CACHE后,才使用查询缓冲。

SELECT SQL_CALHE * FROM TABLE1

二、MySQL对查询的自动优化

  索引对于数据库是非常重要的。在查询时可以通过索引来提高性能。但有时使用索引反而会降低性能。我们可以看如下的SALES表:

CREATETABLE SALES
(
   ID INT(10) UNSIGNED NOTNULL AUTO_INCREMENT,
   NAME VARCHAR(100) NOTNULL,
   PRICE FLOATNOTNULL,
   SALE_COUNT INTNOTNULL,
   SALE_DATE DATE NOTNULL,
 PRIMARYKEY(ID),
 INDEX (NAME),
  INDEX (SALE_DATE)
)

  假设这个表中保存了数百万条数据,而我们要查询商品号为1000的商品在2004年和2005年的平均价格。我们可以写如下的SQL语句:

SELECT AVG(PRICE) FROM SALES
WHERE ID=1000 AND SALE_DATE BETWEEN '2004-01-01' AND '2005-12-31';

  如果这种商品的数量非常多,差不多占了SALES表的记录的50%
或更多。那么使用SALE_DATE字段上索引来计算平均数就有些慢。因为如果使用索引,就得对索引进行排序操作。当满足条件的记录非常多时(如占整个表
的记录的50%或更多的比例),速度会变慢,这样还不如对整个表进行扫描。因此,MySQL会自动根据满足条件的数据占整个表的数据的比例自动决定是否使
用索引进行查询。

对于MySQL来说,上述的查询结果占整个表的记录的比例是30%左右时就不使用索引了,这个比例是MySQL的开发人员根据他们的经验得出的。然而,实际的比例值会根据所使用的数据库引擎不同而不同。

三、 基于索引的排序

  MySQL的弱点之一是它的排序。虽然MySQL可以在1秒中查询
大约15,000条记录,但由于MySQL在查询时最多只能使用一个索引。因此,如果WHERE条件已经占用了索引,那么在排序中就不使用索引了,这将大
大降低查询的速度。我们可以看看如下的SQL语句:

SELECT*FROM SALES WHERE NAME = 'name' ORDERBY SALE_DATE DESC;

在以上的SQL的WHERE子句中已经使用了NAME字段上的索引,因此,在对SALE_DATE进行排序时将不再使用索引。为了解决这个问题,我们可以对SALES表建立复合索引:

ALTERTABLE SALES DROPINDEX NAME, ADDINDEX (NAME, SALE_DATE)

这样再使用上述的SELECT语句进行查询时速度就会大副提升。但要注意,在使用这个方法时,要确保WHERE子句中没有排序字段,在上例中就是不能用SALE_DATE进行查询,否则虽然排序快了,但是SALE_DATE字段上没有单独的索引,因此查询又会慢下来。

SELECT*FROM SALES WHERE NAME = 'name1' AND NAME = 'name2'

以上的查询语句要查找NAME既等于name1又等于name2的记录。很明显,这是一个不可达的查询,WHERE条件一定是假。MySQL在执行SQL

语句之前,会先分析WHERE条件是否是不可达的查询,如果是,就不再执行这条SQL语句了。为了验证这一点。我们首先对如下的SQL使用EXPLAIN
进行测试:

EXPLAIN SELECT*FROM SALES WHERE NAME = ’name1'

上面的查询是一个正常的查询,我们可以看到使用EXPLAIN返回的执行信息数据中table项是SALES。这说明MySQL对SALES进行操作了。再看看下面的语句:

EXPLAIN SELECT*FROM SALES WHERE NAME = ’name1' AND NAME = 'name2'

我们可以看到,table项是空,这说明MySQL并没有对SALES表进行操作。

四、 使用各种查询选择来提高性能

  SELECT语句除了正常的使用外,MySQL还为我们提供了很多可以增强查询性能的选项。如上面介绍的用于控制查询缓冲的SQL_NO_CACHE和SQL_CACHE就是其中两个选项。在这一部分,我将介绍几个常用的查询选项。

1、STRAIGHT_JOIN:强制连接顺序

当我们将两个或多个表连接起来进行查询时,我们并不用关心MySQL先连哪个表,后连哪个表。而这一切都是由MySQL内部通过一系列的计算、评估,最后得出的一个连接顺序决定的。如下列的SQL语句中,TABLE1和TABLE2并不一定是谁连接谁:

SELECT TABLE1.FIELD1, TABLE2.FIELD2 FROM TABLE1 ,TABLE2 WHERE …

如果开发人员需要人为地干预连接的顺序,就得使用STRAIGHT_JOIN关键字,如下列的SQL语句:

SELECT TABLE1.FIELD1, TABLE2.FIELD2 FROM TABLE1 STRAIGHT_JOIN TABLE2 WHERE …

  由上面的SQL语句可知,通过STRAIGHT_JOIN强迫MySQL按TABLE1、TABLE2的顺序连接表。如果你认为按自己的顺序比MySQL推荐的顺序进行连接的效率高的话,就可以通过STRAIGHT_JOIN来确定连接顺序。

2、干预索引使用,提高性能

  在上面已经提到了索引的使用。一般情况下,在查询时MySQL将自己决定是否使用索引,使用哪一个索引。
  但在一些特殊情况下,我们希望MySQL只使用一个或几个索引,或者不希望使用某个索引。这就需要使用MySQL的控制索引的一些查询选项。

(1)限制使用索引的范围:

  有时我们在数据表里建立了很多索引,当MySQL对索引进行选择时,这些索引都在考虑的范围内。但有时我们希望MySQL只考虑几个索引,而不是全部的索引,这就需要用到USE INDEX对查询语句进行设置。

SELECT*FROM TABLE1 USEINDEX (FIELD1, FIELD2) …

  从以上SQL语句可以看出,无论在TABLE1中已经建立了多少个索引,MySQL在选择索引时,只考虑在FIELD1和FIELD2上建立的索引。

(2)限制不使用索引的范围:

  如果我们要考虑的索引很多,而不被使用的索引又很少时,可以使用IGNORE INDEX进行反向选取。在上面的例子中是选择被考虑的索引,而使用IGNORE INDEX是选择不被考虑的索引。

SELECT*FROM TABLE1 IGNORE INDEX (FIELD1, FIELD2) …

在上面的SQL语句中,TABLE1表中只有FIELD1和FIELD2上的索引不被使用。

(3)强迫使用某一个索引:

  上面的两个例子都是给MySQL提供一个选择,也就是说MySQL并不一定要使用这些索引。而有时我们希望MySQL必须要使用某一个索引(由于MySQL在查询时只能使用一个索引,因此只能强迫MySQL使用一个索引)。这就需要使用FORCE INDEX来完成这个功能。

SELECT*FROM TABLE1 FORCE INDEX (FIELD1) …

  以上的SQL语句只使用建立在FIELD1上的索引,而不使用其它字段上的索引。

3. 使用临时表提供查询性能

当我们查询的结果集中的数据比较多时,可以通过SQL_BUFFER_RESULT选项强制将结果集放到临时表中,这样就可以很快地释放MySQL的表锁(这样其它的SQL语句就可以对这些记录进行查询了),并且可以长时间地为客户端提供大记录集。

  SELECT SQL_BUFFER_RESULT * FROM TABLE1 WHERE …

和SQL_BUFFER_RESULT选项类似的还有SQL_BIG_RESULT,这个选项一般用于分组或DISTINCT关键字,这个选项通知MySQL,如果有必要,就将查询结果放到临时表中,甚至在临时表中进行排序。

SELECT SQL_BUFFER_RESULT FIELD1, COUNT(*) FROM TABLE1 GROUPBY FIELD1

转载:http://do-found.blog.163.com/blog/static/2837184200842810115882/

MYSQL查询优化(Ⅰ)的更多相关文章

  1. Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析

    Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析     Atitit Mysql查询优化器 存取类型 范围存取类型 索引存取类型 AND or的分析1 存 ...

  2. MySQL查询优化之explain的深入解析

    在分析查询性能时,考虑EXPLAIN关键字同样很管用.EXPLAIN关键字一般放在SELECT查询语句的前面,用于描述MySQL如何执行查询操作.以及MySQL成功返回结果集需要执行的行数.expla ...

  3. 1025WHERE执行顺序以及MySQL查询优化器

    转自http://blog.csdn.net/zhanyan_x/article/details/25294539 -- WHERE执行顺序-- 过滤比较多的放在前面,然后更加容易匹配,从左到右进行执 ...

  4. MySQL查询优化:查询慢原因和解决技巧

    在开发的朋友特别是和mysql有接触的朋友会碰到有时mysql查询很慢,当然我指的是大数据量百万千万级了,不是几十条了,下面我们来看看解决查询慢的办法. MySQL查询优化:查询慢原因和解决方法 会经 ...

  5. mysql查询优化器为什么可能会选择错误的执行计划

    有可能导致mysql优化器选择错误的执行计划的原因如下: A:统计信息不准确,mysql依赖存储引擎为其提供的统计信息来评估成本,然而有的存储引擎提供的信息是准确的,有的引擎提供的可能就偏差很大,如: ...

  6. Mysql查询优化器

    Mysql查询优化器 本文的目的主要是通过告诉大家,查询优化器为我们做了那些工作,我们怎么做,才能使查询优化器对我们的sql进行优化,以及启示我们sql语句怎么写,才能更有效率.那么到底mysql到底 ...

  7. MySQL查询优化 (一)

    以下的文章主要讲述的是MySQL查询优化的5个十分好用方法,熟悉SQL语句的人都清楚,如果要对一个任务进行操作的话,SQL语句可以有很多种相关写法,但是不同的写法查询的性能可能会有天壤之别. 本文列举 ...

  8. MySQL查询优化:连接查询排序limit

    MySQL查询优化:连接查询排序limit(join.order by.limit语句) 2013-02-27      个评论       收藏    我要投稿   MySQL查询优化:连接查询排序 ...

  9. MySQL查询优化之explain

    在分析查询性能时,考虑EXPLAIN关键字同样很管用.EXPLAIN关键字一般放在SELECT查询语句的前面,用于描述MySQL如何执行查询操作.以及MySQL成功返回结果集需要执行的行数.expla ...

  10. Mysql查询优化器浅析

    --Mysql查询优化器浅析 -----------------------------2014/06/11 1 定义    Mysql查询优化器的工作是为查询语句选择合适的执行路径.查询优化器的代码 ...

随机推荐

  1. [翻译] ASP.NET WebAPI 中的异常处理

    原文链接:https://docs.microsoft.com/en-us/aspnet/web-api/overview/error-handling/exception-handling 本文介绍 ...

  2. openvSwitch tunnel

    ovs tunnel 实验拓扑 实验拓扑搭建基础脚本 #vbox虚拟机1 ip netns add left ip link add name veth1 type veth peer name sw ...

  3. 《PHP, MySQL, Javascript和CSS》读书随手记----php篇

    1. 基础 注释: // 或 /* */ $标示变量 语句末尾加分号 数组: $oxo = array(array('x','','o'), array('p','x',''),array('','x ...

  4. [leetcode.com]算法题目 - Triangle

    Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent n ...

  5. Mac下更改Mysql5.7的默认编码为utf8

    Mac上从官方安装完Mysql5.7后,有一部分的字符集默认为latin1,而非utf8,为避免乱码的产生,本文介绍将所有字符集设置为utf8 查看当前字符集编码 show variables lik ...

  6. POJ 2442(优先队列 k路归并 堆)

    Description Given m sequences, each contains n non-negative integer. Now we may select one number fr ...

  7. Java并发编程总结3——AQS、ReentrantLock、ReentrantReadWriteLock

    本文内容主要总结自<Java并发编程的艺术>第5章——Java中的锁. 一.AQS AbstractQueuedSynchronizer(简称AQS),队列同步器,是用来构建锁或者其他同步 ...

  8. 抓包和测试Api类工具

    1.PostMan  测试api 2.Fiddler4抓包工具使用教程一

  9. 九、将cs文件快速的转换成可执行文件和响应文件(配置编译开关的文件)

    1.将包含多个类型的源代码文件转换为可以部署的文件.有如下Program.cs的文件,代码如下: public sealed class Program { public static void Ma ...

  10. spring boot + mybatis + druid + redis

    接上篇,使用redis做缓存 新建spring boot 工程,添加pom引用 <dependency> <groupId>org.springframework.boot&l ...