数据库相关

参考链接:
http://www.nowamagic.net/academy/detail/32061020
http://www.cnblogs.com/hi-bazinga/archive/2012/06/05/2536806.html
http://www.cnblogs.com/ybwang/archive/2010/06/04/1751279.html
http://www.cnblogs.com/phoenixbai/p/mysql_best_practices.html
http://ariyue.iteye.com/blog/553541

基本知识


** 四大范式**
第一范式:每个属性不可再分,属性原子性(高效查询提高性能)
第二范式:非主属性完全依赖于主属性,即消除非主属性对主属性的部分函数依赖关系(完全但不是直接,少冗余)
第三范式:确保每列都和主键列直接相关,而不是间接相关。非主属性对主属性不存在传递函数依赖关系(完全且直接)
BCNF:非主键字段必须依赖于整个主键字

事务隔离级别
读未提交:实际很少用。
读已提交:大多数数据库的默认级别。解决脏读问题。
可重读:mysql默认。解决了脏读和不可重复读问题。但有幻读问题。
可串行化:最高的级别,强制事务排序使之不会相互冲突,解决幻读问题。但会有性能问题。

脏读(rollback):A已更新一份数据,B在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
不可重复读(update):事务两次查询之中数据的内容不一致 ,别的事务更新所致。
幻读(insert):事务两次查询之中数据的条数不一致 ,别的事务新增所致。
=====================
四个方面:数据库设计、SQL语句优化、数据库参数配置、恰当的硬件资源和操作系统。

一、数据库设计
  1. 适度的反范式,根据业务场景做适度的冗余可以大大提高性能。
  2. 适当建立索引,以及复合索引。Cardinality越大,Selectivity越高的字段,越是理想的建索引的对象
  3. 表的水平划分和垂直划分
  4. 主键不要设得太大 (InnoDB),因为它是以B+树形式存储数据文件的。
  5. 文件,图片等大文件用文件系统存储,数据库只存储路径。
  6. 避免频繁读写,尽量集中批量操作。
  7. 静态表会更快(固定长度的表,无VARCHAR, TEXT, BLOB可变长度的string类型的字段的表为静态表。否则,为动态表)。
二、SQL语句优化

慢日志

参数文件里配置:
   slow_query_log=d:/slow.txt
   long_query_time = 2
通过mysql自带的工具(mysqldumpslow.pl)来分析慢日志。

2.Explain查看mysql执行计划

QUERY最佳实践:

  1. 不要用 “SELECT *”,否则,会读多,传输多,且增加可避免的表扫描

  2. 不要 like ‘%item%’ but ‘item%’
    前面有%,这索引就没办法利用了。所以,若想用索引加快查询速度,那前面别加%.

  3. Cardinaltiy (基数) & Selectivity (选择比)
    Cardinality: 不同值的个数。如表t中其有100条记录, 字段owner也有100条值,但其中10个不相同的值。这10就是这字段的Cardinality.
    Selectivity: 10/100 = 10%就是这字段的selectivity.
    这概念主要用来判断此字段是否适合建索引。Cardinality越大,Selectivity越高的字段,越是理想的建索引的对象。有时数据库会根据这个值来决定,是利用索引还是扫表。所以说,不是你建了索引,人家就会用的。而且,索引不可太多,多了反而会拖慢更新速度。

  4. ORDER BY created DESC的优化
    时间排序是应用中比较常见的需求。细想,这时间不是自增长的嘛?那跟ID自增长不是一回事儿嘛? 所以说,在ORDER BY 时,用自增长的主键ID,会比用created,省一个FILE SORT操作。快很多的。

  5. Count(1), count(), count(owner)的区别
    count(1)等同于count(
    ),等同于count(任何一个NOT NULL的字段)
    count(owner):若owner是可NULL的,则数出来的数跟上面的三种情况会少的。少的正好是那些owner is null的个数。

  6. Don`t JOIN ON 不同数据类型
    A表user_id作为B表的外键,这种很常见。此时,需注意user_id字段的类型,在两张表里都要保持一致。这样节省不必要的开支,比如,数据库替你做类型转换等。

  7. 不要用全文索引(full-text index)
    当前只有MyISAM才支持全文索引。而且,不太好用,可自定义性比较差,所以完全无视它即可。若真需要做全文索引,还是考虑用Lucene, Solr, ElasticSearch, Sphinx, Groonga, Xapian等吧。个个都是行家里手,功能齐全,可定义性强,随你搞。

  8. Limit n,m 慢,慎用
    大部分人翻页,可能都是靠这个的。数据量大时,这显然会很慢。网上有人推荐说,第一次查出来后,记住当前页的最后一个ID,然后,在查询下一页时,把这个ID做为限制条件加进去,然后取limit pagesize。
    诸如此类,若细想,应该是能想出点儿可行之策的我觉的。其实,当数据量很大时,你可以换个角度想,如继续在limit n,m上做文章能还是直接换个查询方式,如用搜索引擎等。

百万级数据量时,limit优化

小小的索引+一点点的改动就使mysql 可以支持百万甚至千万级的高效分页

  1. 建立复合索引
  2. 通用优化索引,找出id,再拼成 ”292,2492,38,12000“这样的字符串
  3. 再次用 where id in 语句查询出结果

100万的数据,160万数据,15G表,190M索引
如果对于有where 条件,又想走索引用limit的,必须设计一个索引,将where 放第一位,limit用到的主键放第2位,而且只能select 主键!

三、数据库参数配置

nnodb_additional_mem_pool_size = 64M
innodb_buffer_pool_size = 5G

四、合理的硬件资源和操作系统

读写分离 binlog

主库master用来写入,slave1—slave3都用来做select,每个数据库分担的压力小了很多。工具:mysql-proxy(官方),amobe for mysql(新浪)

====================
导致引擎放弃使用索引而进行全表扫描常见情况:

  1. 在 where 子句中对字段进行 null 值判断
  2. 在 where 子句中使用!=或<>操作符
  3. 在 where 子句中使用 or 来连接条件,可以用 union all 来改写。
  4. in 和 not in 也要慎用,因为IN会使系统无法使用索引,而只能直接搜索表中的数据,对于连续的数值,能用 between 就不要用 in .
  5. 在 where 子句中对字段进行表达式操作
  6. 在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算
  7. 能用DISTINCT的就不用GROUP BY
  8. 尽量不要用SELECT INTO语句。 SELECT INOT 语句会导致表锁定,阻止其他用户访问该表。
  9. 避免在索引列上使用计算,not,in和<>等操作
  10. 当只需要一行数据的时候使用limit 1

你可能感兴趣的:(数据库相关)