db

db

Posted by nomadli on August 20, 2020

sql serer

SELECT 优化

  • select语法顺序
      SELECT 
      DISTINCT <select_list>
      FROM <left_table>
      <join_type> JOIN <right_table>
      ON <join_condition>
      WHERE <where_condition>
      GROUP BY <group_by_list>
      HAVING <having_condition>
      ORDER BY <order_by_condition>
      LIMIT <limit_number>
    
  • select执行顺序 ```SQL FROM <表名> # 选取表,将多个表数据通过笛卡尔积变成一个表。 ON <筛选条件> # 对笛卡尔积的虚表进行筛选 JOIN <join, left join, right join...>
# 指定join,用于添加数据到on之后的虚表中,例如left join会将左表的剩余数据添加到虚表中 WHERE # 对上述虚表进行筛选 GROUP BY <分组条件> # 分组 <SUM()等聚合函数> # 用于having子句进行判断,在书写上这类聚合函数是写在having判断里面的 HAVING <分组筛选> # 对分组后的结果进行聚合筛选 SELECT <返回数据列表> # 返回的单列必须在group by子句中,聚合函数除外 DISTINCT # 数据除重 ORDER BY <排序条件> # 排序 LIMIT <行数限制> ``` - 最大化利用索引、尽可能避免全表扫描、减少无效数据的查询 - 避免在字段开头模糊查询(LIKE 用INSTR函数代替)、范围查询 > <,尽量放在后面. - in 和 not in 会全表扫描, 连续值可以使用between 1 and 100。 - 子查询 select xx from a where a.id in (select ..) 使用 select xx from a exists (select .. a.id = b.id) - or查询 select * from a where id=1 or id=2 使用 select * from a where id=1 UNION select * from a where id=2 - 避免null判断,使用0做为值 - 避免条件左侧运算 select * from a where id*10=100 使用 id=100/10 - sql拼装为了不判断where添加where 1=1 导致不走索引 - 使用!= 或 <> 不等于判断 - 联合索引需要最左匹配原则,一旦左侧有不匹配后续索引不再使用,索引(a,b) where b=1 and a=2 - 条件涉及类型隐式转换导致不走索引 - order by、group by 、union 、distinc 需要与where一致, select * from a order by a 使用 where a >=0 order by a - select * from a USE INDEX(id,age) 指定使用的索引,防止执行器选择非最优索引 - select * from a IGNORE INDEX(age,..) 忽略某个索引 - select * from a FORCE INDEX(id,...) 强制使用某索引 - 避免使用select * 导致内存网络无用数据、导致执行优化器无法完成索引覆盖率优化,影响执行计划选择 - 避免使用now()、rand()、sysdate()、current_user()函数,无法利用query cache,主从复制不一致 - 关联查询小表先行,mysql从左到右,oracle相反,第一张表必然全表扫描 - 链接多个表时,使用别名,列使用表名前缀,减少解析及歧义 - 避免使用having用where代替,having是对结果集的筛选,having可以使用聚合函数,where不行 - where条件以过滤比高的在左,组合索引也要这样才能配合 - GROUP BY会导致排序,显示的指定ORDER BY NULL来阻止排序,如: GROUP BY age ORDER BY NULL - where 嵌套的子查询可以使用join来代替,可以避免建立临时表 - union会在临时表上做DISTINCT操作,如果不需要去重,使用union all - 清表用truncate不记录undo日志、且自增字段归零 - limit做子select使用索引分页 ## 增删改 DML 语句优化 - 使用单条语句插入多行数据 insert inot a values(1,1),(2,2),(3,3) - 大量数据的事物分多个事物,commit可以释放undo数据块、redo log、锁等。 - MyISAM 、MEMROY、MERGE,只有表锁, Innodb有行锁,使用LOW_PRIORITY(DELETE、INSERT、LOAD DATA、REPLACE、UPDATE) HIGH_PRIORITY(SELECT、INSERT) DELAYED(INSERT、REPLACE)调整优先级。 - --low-priority-updates启动服务,所有支持LOW_PRIORITY的语句都会按低优先级处理