Daily Archive for September 8th, 2010

MySQL性能优化21 – 使用随机函数产生采样

RAND() 函数是 MySQL 提供的产生随机数的函数。没有指定参数时,每次执行会返回 0-1 的浮点数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mysql> select rand();

+------------------+
| rand() |
+------------------+
| 0.56110724207117 |
+------------------+

1 row in set (0.02 sec)

mysql> select rand();

+-----------------+
| rand() |
+-----------------+
| 0.3343874880433 |
+-----------------+

1 row in set (0.00 sec)

Continue reading ‘MySQL性能优化21 – 使用随机函数产生采样’

Share

MySQL性能优化20 – ORDER BY 操作的优化

在某些情况中, MySQL 可以使用一个索引来满足 ORDER BY 子句,而不需要额外的排序。 where 条件和 order by 使用相同的索引,并且 order by 的顺序和索引顺序相同,并且 order by 的字段都是升序或者都是降序。

例如:下列 sql 可以使用索引。

1
2
3
4
5
SELECT * FROM t1 ORDER BY key_part1,key_part2,... ;

SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC, key_part2 DESC;

SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 DESC;

但是以下情况不使用索引:

1
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC

–order by 的字段混合 ASC 和 DESC

1
SELECT * FROM t1 WHERE key2=constant ORDER BY key1 ;

– 用于查询行的关键字与 ORDER BY 中所使用的不相同

1
SELECT * FROM t1 ORDER BY key1, key2 ;

– 对不同的关键字使用 ORDER BY 。

Share

MySQL性能优化19 – GROUP BY 操作的优化

默认情况下, MySQL 在执行 GROUP BY col1 , col2.... 操作的时候,会按照 GROUP BY 字段的顺序进行排序。如果显式包括一个包含相同的列的 ORDER BY 子句,则对 MySQL 的实际执行性能没有什么额外的影响。

如果查询包括 GROUP BY 操作, 但是不需要对结果进行排序,或者对默认的排序结果不满意,希望获得结果后再由程序进一步处理的时候,可以指定 ORDER BY NULL 禁止排序,从而避免排序结果的消耗。 Continue reading ‘MySQL性能优化19 – GROUP BY 操作的优化’

Share

MySQL性能优化18 – 使用 GROUP BY WITH ROLLUP 改善统计性能

使用 GROUP BY 的 WITH ROLLUP 字句可以检索出更多的分组聚合信息,它不仅仅能像一般的 GROUP BY 语句那样检索出各组的聚合信息,还能检索出本组类的整体聚合信息。 Continue reading ‘MySQL性能优化18 – 使用 GROUP BY WITH ROLLUP 改善统计性能’

Share

MySQL性能优化17 – INSERT操作的优化

执行 INSERT 操作的时候,可以考虑使用以下的方式优化 SQL 的执行效率:

  • 如果你同时从同一客户插入很多行,使用多个值表的 INSERT 语句。这比使用分开 INSERT 语句快。
    1
    Insert into test values(1,2),(1,3),(1,4)
  • 如果你从不同客户插入很多行,能通过使用 INSERT DELAYED 语句得到更高的速度。 Delayed的含义是让 INSERT 语句马上执行,其实数据都被放在内存的队列中,并没有真正写入磁盘;这比每条语句分别插入要快的多; LOW_PRIORITY 刚好相反,在所有其他用户对表的读写完后才进行插入;
  • 将索引文件和数据文件分在不同的磁盘上存放;
  • 如果进行批量插入,可以增加 bulk_insert_buffer_size 变量值的方法来提高速度,但是,这只能对 MyISAM 表使用;
  • 当从一个文本文件装载一个表时,使用 LOAD DATA INFILE。这通常比使用很多 INSERT 语句快 20 倍;
  • 根据应用情况使用 REPLACE 语句代替 INSERT ;
  • 根据应用情况使用 IGNORE 关键字忽略重复记录。
Share

MySQL性能优化16 – InnoDB 存储引擎

对于 InnoDB 类型的表,这种方式并不能提高导入数据的效率。对于 InnoDB 类型的表,我们有以下几种方式可以提高导入的效率:

因为 InnoDB 类型的表是按照主键的顺序保存的,所以将导入的数据按照主键的顺序排列,可以有效的提高导入数据的效率。如果 InnoDB 表没有主键,那么系统会默认创建一个内部列作为主键,所以如果可以给表创建一个主键,将可以利用这个优势提高导入数据的效率。

在导入数据前执行 SET UNIQUE_CHECKS=0 ,关闭唯一性校验,在导入结束后执行 SET UNIQUE_CHECKS=1 ,恢复唯一性校验,可以提高导入的效率。

如果应用使用自动提交的方式,建议在导入前执行 SET AUTOCOMMIT=0 ,关闭自动提交,导入结束后再执行 SET AUTOCOMMIT=1,打开自动提交,也可以提高导入的效率。

Share

MySQL性能优化15 – MyISAM 存储引擎

对于 MyISAM 类型的表,可以通过以下方式快速的导入大量的数据。

loading the data

这两个命令用来打开或者关闭 MyISAM 表非唯一索引的更新。在导入大量的数据到一个非空的 MyISAM 表时,通过设置这两个命令,可以提高导入的效率。对于导入大量数据到一个空的 MyISAM 表,默认就是先导入数据然后才创建索引的,所以不用进行设置。

Share

MySQL性能优化14 – HIGH_PRIORITY/LOW_PRIORITY/INSERT DELAYED

MySQL 还允许改变语句调度的优先级,它可以使来自多个客户端的查询更好地协作,这样单个客户端就不会由于锁定而等待很长时间。改变优先级还可以确保特定类型的查询被处理得更快。

我们首先应该确定应用的类型,判断应用是以查询为主还是以更新为主的,是确保查询效率还是确保更新的效率,决定是查询优先还是更新优先。

下面我们提到的改变调度策略的方法主要是针对 MyISAM 存储引擎的,对于 InnoDB 存储引擎,语句的执行是由获得行锁的顺序决定的。

MySQL 的默认的调度策略可用总结如下:

  • 写入操作优先于读取操作。
  • 对某张数据表的写入操作某一时刻只能发生一次,写入请求按照它们到达的次序来处理。
  • 对某张数据表的多个读取操作可以同时地进行。

MySQL 提供了几个语句调节符,允许你修改它的调度策略:

如果写入操作是一个 LOW_PRIORITY(低优先级)请求,那么系统就不会认为它的优先级高于读取操作。在这种情况下,如果写入者在等待的时候,第二个读取者到达了,那么就允许第二个读取者插到写入者之前。只有在没有其它的读取者的时候,才允许写入者开始操作。这种调度修改可能存在 LOW_PRIORITY 写入操作永远被阻塞的情况。

SELECT 查询的 HIGH_PRIORITY (高优先级)关键字也类似。它允许 SELECT插入正在等待的写入操作之前,即使在正常情况下写入操作的优先级更高。另外一种影响是,高优先级的 SELECT 在正常的 SELECT语句之前执行,因为这些语句会被写入操作阻塞。

如果你希望所有支持 LOW_PRIORITY选项的语句都默认地按照低优先级来处理,那么请使用 --low-priority-updates 选项来启动服务器。通过使用 INSERT HIGH_PRIORITY 来把 INSERT[/cci] 语句提高到正常的写入优先级,可以消除该选项对单个 INSERT 语句的影响。

Share

MySQL性能优化13 – SQL_NO_CACHE/SQL_CACHE

可以在 SELECT 语句中指定查询缓存的选项,对于那些肯定要实时的从表中获取数据的查询,或者对于那些一天只执行一次的查询,我们都可以指定不进行查询缓存,使用 SQL_NO_CACHE 选项。

对于那些变化不频繁的表,查询操作很固定,我们可以将该查询操作缓存起来,这样每次执行的时候不实际访问表和执行查询,只是从缓存获得结果,可以有效地改善查询的性能,使用 SQL_CACHE 选项。

下面是使用 SQL_NO_CACHESQL_CACHE 的例子:

1
2
mysql> select sql_no_cache id,name from test3 where id < 2;
mysql> select sql_cache id,name from test3 where id < 2;

注意:查询缓存的使用还需要配合相应得服务器参数的设置,相关情况请参考服务器优化的章节。

Share

MySQL性能优化12 – FORCE INDEX/IGNORE INDEX

FORCE INDEX 通常用来对查询强制使用一个或者多个索引。 MySQL 通常会根据统计信息选择正确的索引,但是当查询优化器选择了错误的索引或者根本没有使用索引的时候,这个提示将非常有用。

IGNORE INDEX 提示会禁止查询优化器使用指定的索引。在具有多个索引的查询时,可以用来指定不需要优化器使用的那个索引,还可以在删除不必要的索引之前在查询中禁止使用该索引。 Continue reading ‘MySQL性能优化12 – FORCE INDEX/IGNORE INDEX’

Share