通过提示字来影响MySQL

  许多关系型数据库都具备一些提示字(Hint)的概念-一种为底层的SQL引擎和查询优化器提供额外信息的简单语法。某些时候你会因为要解决一个BUG或者提升性能而用到这些鱼贩。我们浏览几个能够影响MySQL的查询处理的提示字。像你在查询缓存那个章节所看到的,MySQL中的提示字经常出现的SELECT关键字的后面。

  SELECT SQL_CACHE * FROM mytable ...

  不过稍后你也会看到,并非所有的提示字都是这样。

  如果你因为你的SQL代码需要在MySQL之外的其他数据服务器中运行,而因此担心代码可移植性的问题,你可以将Hint放在注释中,这一来就会被其他的数据服务器所忽略-MySQL的比较老的版本也会忽略。

  SELECT /*! SQL_CACHE */ * FROM mytable ...

  连接顺序(Join Order)

  MySQL一般情况下不会在意你查询中列出表名称的前后顺序。它会检查各种可能、进而确定先读哪一张表,然后再读哪一张,依此类推。偶尔你也可能会发现MySQl处理多表连接不是非常理想。在查看过查询的EXPLAIN输出之后,你意识到这是由于没有使用最优的顺序存取表而导致的。

  如果你确信你能够比MySQL更为优化的确定表连接的顺序,你可以使用STRAIGHT_JOIN作为提示字,用原来在逗号或者JOIN关键字所在的地方:

  SELECT * FROM table1 STRAIGHT_JOIN table2 WHERE ...

  这样一来就强制MySQL按照你在查询中指定顺序来连接表,而不再自行去确定连接的顺序。

  索引的使用

  MySQL提供了若干索引相关的提示字,来满足你对其所使用的索引进行更多的控制的需要。

  在你查询语句中表名的后面,添加USE INDEX 来提供你希望MySQ去参考的索引列表,就可以让MySQL不再考虑其他可用的索引:

  SELECT * FROM mytable USE INDEX (mod_time, name) ...

  如果你只是单纯的想让MySQL忽略一个或者多个索引,可以使用IGNORE INDEX作为Hint:

  SELECT * FROM mytale IGNORE INDEX (priority) ...

  为强制MySQL使用一个特定的索引,可在查询中使用FORCE INDEX作为Hint:

  SELECT * FROM mytable FORCE INDEX (mod_time) ...

  这样一来,你可以告诉MySQL忽略其他的决策,尽管那些决策在常规情形下是被看作是确定查找所需数据的最优途径。只有在你所指定的索引对于该查询根本用不上时,它才会继续采用常规的决策方式以寻找最优的查询方式。

  结果集的大小

  还有一组提示字时用来告诉MySQL,需要以一种不同的方式来处理结果集。像绝大多数其他的提示字一样,你务必你确信知道它的确能够带来助益的情况下再去采用它。滥用迟早会引发性能上的问题。

  当处理一个会让客户端耗费点时间才能处理的大结果集时,可以考虑使用SQL_BUFFER_RESULT 提示字。这样可以告诉MySQL将结果集保存在一个临时表中,这样可以尽早的释放各种锁。

  SQL_BUFFER_RESULT Hint告诉MySQL当前的查询会返回非常多的记录行。当MySQL看到这个提示字,它就会使用做出一个主动决策-在用基于磁盘临时表。为了对结果集进行排序而在这个临时表上建立一个索引不是那么合适。

  查询缓存

  正如我们在本章的开始所提到的,查询缓存在内存中保存着经常被执行的SELECT的查询结果以加速查找。MySQL提供了用于控制查询结果是否应该被缓存的控制开关提示字。

  通过使用SQL_CACHE,你要求MySQL将本次查询的结果缓存起来,如果query_cache_type被设置为1,这个Hint就没有什么效果,因为所有的SELECT查询都已经缺省被缓存起来。然而,如果query_cache_type设置为2,那么只有在明确指定的情况下查询结果才会被缓存起来,此时就是SQL_CACHE的用武之地了。

  与此相反,使用SQL_NO_CACHE Hint可以要求MySQL不要缓存本次查询的结果集。因为这是个反向请求标记,所以适用于query_cache_type为1和2的两种情况。