mysql查询语句的效率
几篇文章的摘录。
为什么MySQL不推荐使用子查询和join(开发程序)
1子查询,效率差。原因:执行子查询时,会创建临时表,查询完毕后再删除它,所以子查询的速度会收到影响。
2JOIN。小表驱动大表,通过索引字段进行关联,只适用较少的数据量。
3从开发程序看,数据库只作为储存数据的工具来用,业务逻辑放到应用控制层上去实现。
推荐,大数据下,为了保证效率,推荐根据索引单表取得数据,然后在程序里面做join, merge数据。??只开发时,在控制层实现业务逻辑??。
MySQL大表优化方案
单表优化:
一般以整型值为主的表在千万级
以下,字符串为主的表在五百万
以下的表进行单表优化。
除非单表数据未来会一直不断上涨,否则不要一开始就考虑拆分,拆分会带来逻辑、部署、运维的各种复杂度。
字段:
- 适用tinyint, smallint, medium_int代替int, 非负加上unsigned
- varchar的长度要根据实际需求设定
- 用enum或int,代替varchar
- 尽量使用
TIMESTAMP
而非DATETIME 为什么?(一篇博客)
- datetime类型适合记录数据的原始的创建时间。
- 可以为空值。实际储存格式由创表者设定。
- 和时区无关。
- 用now()来插入系统的当前时间。
- timestamp类型适合记录数据的最后修改时间,因为可以设定当其他字段的值变更后,timestamp自动更新。
- 可以为空值,但不能自定义值。
- 有时区,可以时区转化。
- 值的范围是:1970或晚于2037。
- 值以UTC格式保存。
- 默认值: current_timestamp()
- 默认情况下以后任何时间修改表中的记录时,对应记录的timestamp值会自动被更新为当前的系统时间。
- datetime类型适合记录数据的原始的创建时间。
- 单表设计,字段数量要控制,最好20个以内。
- 避免用null字段, 很难查询优化且占用额外索引空间
索引:
- 索引根据实际需要来设置,不是越多越好,索引本身是占用内存空间的。
- 在where和order by上会用到的columns, 是否建立索引,可以使用explain查看是用了索引还是全表扫描
- 应尽量避免在where上对字段进行null值的判断,否则导致引擎放弃使用索引,而改用全表扫描。
- 如性别列这种只有男,女,中性三种值的字段/列,无需建立索引。
- 尽量不用foreign key,用应用程序来保证约束。
- 尽量不用unique, 用应用程序来保证约束。
- 使用多列索引时主意顺序和查询条件保持一致,同时删除不必要的单列索引
- 字符字段只建前缀索引, 字符字段最好不要做主键.
查询:
- 不做列运算:
SELECT id WHERE age + 1 = 10
,任何对列的操作都将导致全表扫描,它包括数据库教程函数、计算表达式等等,查询时要尽可能将操作移至等号右边。 - sql语句尽量简单,大语句拆成小语句,减少锁时间;一条大语句可以堵死整个库。
- 不用select *
- OR改成IN。用OR的时间复杂度是N,用in的时间复杂度是logN。in的个数在200以内。
- 不用函数和触发器,在应用程序中实现!!
- 避免模糊查询 like "%xxxx"。会导致索引字典失效。
- 少用JOIN,更要减少使用子查询。
- 使用同类型比较: “123”和“123”比较, 123和123比较。
- 尽量避免在where子句中使用 !=和<>操作符,因为会导致全表扫描,而不是使用索引。
- 对于连续数值,使用between, 不要用in。SELECT id FROM t WHERE num BETWEEN 1 AND 5
- 列表数据不要取全表数据,用limit分页查询,每页也不要太大。
其他优化方案:
- 引擎的选择
- 系统调优参数
- 升级硬件
- 缓存
- 表分区
- 对表进行垂直拆分
- 水平拆分(非常复杂)