15. 分区表基础 官方文档: http://dev.mysql.com/doc/refman/5.1/zh/partitioning.html 分区类型: RANGE 分区 :基于属于一个给定连续区间的列值,把多行分配给分区。 LIST 分区 :类似于按 RANGE 分区,区别在于 LIST 分区是基于列值匹配一个离散值集合中的某个值来进行选择。 HASH 分区 :基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含 MySQL 中有效的、产生非负整数值的任何表达式。 KEY 分区 :类似于按 HASH 分区,区别在于 KEY 分区只支持计算一列或多列,且 MySQL 服务器提供其自身的哈希函数。必须有一列或多列包含整数值。 子分区 :子分区是分区表中每个分区的再次分割。
16. 分区表基础— Range 分区 每个分区包含那些分区表达式的值位于一个给定的连续区间内的行。这些区间要连续且不能相互重叠,使用 VALUES LESS THAN 操作符来进行定义。 CREATE TABLE employees ( id INT NOT NULL, store_id INT NOT NULL ) PARTITION BY RANGE (store_id) ( PARTITION p0 VALUES LESS THAN (6), //1~5 PARTITION p1 VALUES LESS THAN (11), //6~10 PARTITION p2 VALUES LESS THAN (16), //11~15 PARTITION p3 VALUES LESS THAN MAXVALUE // 16~MAX ) ;
17. 分区表基础— List 分区 LIST 分区中每个分区的定义和选择是基于某列的值从属于一个值列表集中的一个值。 LIST 分区通过” VALUES IN (value_list)” 的方式来定义每个分区,其中” value_list” 是一个通过逗号分隔的整数列表。 CREATE TABLE employees ( id INT NOT NULL, store_id INT ) PARTITION BY LIST(store_id) PARTITION p1 VALUES IN (3,5,6,9,17), PARTITION p2 VALUES IN (1,2,10,11,19,20), PARTITION p3 VALUES IN (4,12,13,14,18), PARTITION p4 VALUES IN (7,8,15,16) ) ;
18. 分区表基础— Hash 分区 在 HASH 分区中, MySQL 自动完成分区值,你所要做的只是基于将要被哈希的列值指定一个列值或表达式,以及指定被分区的表将要被分割成的分区数量。 CREATE TABLE employees ( id INT NOT NULL, store_id INT ) PARTITION BY HASH(store_id) PARTITIONS 4 ;
19. 分区表基础—子分区 子分区是分区表中每个分区的再次分割,子分区既可以使用 HASH 希分区,也可以使用 KEY 分区, 每个分区必须有相同数量的子分区。 CREATE TABLE ts (id INT, purchased DATE) PARTITION BY RANGE(YEAR(purchased)) SUBPARTITION BY HASH(TO_DAYS(purchased)) ( PARTITION p0 VALUES LESS THAN (1990) ( SUBPARTITION s0, SUBPARTITION s1 ), PARTITION p1 VALUES LESS THAN (2000) ( SUBPARTITION s2, SUBPARTITION s3 ));
22. 优化器差异 MySQL 对子查询会处理为临时表,所以一般 JOIN 效率比做子查询高。 MySQL 在 JOIN 中对 ORDER BY 、 GROUP BY 优化较弱, JOIN 中的排序分组几乎都会使用 Fille Sort 和临时表 MySQL 只有 RBO ,没有 CBO ,所以总是选择类型上最优的执行计划,而不一定是开销最小的。 MySQL 对于 OR ,很多时候并不会优化成两次索引访问或合并索引,所以 OR 最好写成两条 SQL ,做 UNION ALL 。 IN 中存在 NULL 条件,可能会让优化器走成全表扫描。
23. SQL 方言差异 选择部分行 : Oracle 使用 Rownum , MySQL 使用 LIMIT start,end; 执行函数 : Oracle 需要 SELECT f() FROM dual; MySQL 可以直接 SELECT f(); 复制数据 : Oracle 必须有 as , CREATE TABLE t AS SELECT * FROM table; MySQL 的 as 是可选, CREATE TABLE t SELECT * FROM table;
24. 常用功能差异 锁差异 : Oracle 锁加在数据块上, InnoDB 锁加在主键索因上,所以 InnoDB 总是有主键索引。 导入导出数据 : Oracle 采用 EXP/IMP 导入导出。 MySQL 采用 mysqldump 导出,导入可以采用管道或 source 。 mysqldump –u 用户 – p 密码 DB [table1 table2…] > db.sql 提交方式 : MySQL 默认自动提交, Oracle 默认手动提交, MySQL 大批量操作最好改变为手动提交, SET AUTOCOMMIT=0 SQL 缓存 : MySQL 只能缓存结果集,不能缓存 SQL 解析结果 数据库对象 : Oracle 将数据库对象编译存储,直接执行二进制码, MySQL 只存储代码,临时解析执行,所以 MySQL 触发器、存储过程等对象创建时仅检查语法,并不检查逻辑
26. 索引优化基础 MySQL 只在认为走索引可以筛去 85% 以上数据的时候,才使用索引,如果达不到这个标准,索引是无意义的。 前缀索引 : MySQL 可以利用索引的前向部分,但不可以利用后向部分,不支持反向索引。 例如: SELECT col2 FROM table WHERE col1=1; 可以使用索引 (col1,col2) ,但不可以使用 (col2,col1). 不等比较的优化 :如果索引的前向部分在 WHERE 中是等于,那么可以使用索引,如果索引的前向部分再 WHERE 中是不等比较,那么不可以为后面的等于比较使用索引 例如: SELECT col1 FROM table WHERE col2=1 AND col3 >10; 可以完全使用索引 (col2,col3) ,但只可以使用 (col3,col2) 的前缀, 排序的优化 :可以在条件是等于的时候继续使用索引排序,或者条件中的不等于字段就是排序字段。 例如: SELECT col1 FROM table WHERE col2=1 AND col3>0 ORDER BY col3 ,可以完全使用索引 (col2,col3) 避免排序。但条件是 col2<1 AND col3=0 ORDER BY col3 时则只能使用 col2 排除记录,不可以用来排序。 GROUP BY/DISTINCT 也是以排序为基础,优化同上。
28. SQL 书写优化 尽量将子查询转化为链接查询,除非子查询只返回极少的记录。 不要在条件里写不必要的条件。 没有必要排序的分组采用 ORDER BY null 指定不排序。 OR 条件若不能正确的走索引,则拆分为两条 SQL 。 不在乎重复的情况下, UNION ALL 可以避免 UNION 要做的排序。 没必要的时候不要做外连接,内连接效率比外连接高。