SQL使用规范

作为一名工程狮, 不只要会写SQL, 还得会写性能优良的SQL. 以下是总结在开发过程中常用的方法.

  • 规则1 遵循单SQL最少功能原则
    • 不建议使用复杂的SQL查询数据, 如超过3个表的关联查询;
    • 建议使用简单的SQL查询数, 在业务代码中进行处理以达到最终想要的数据.

如查询某订单详情的例子:

#方法一:分多次简单查询, 然后在代码聚合数据(推荐)
select ... from om_order where order_id = 1;
select ... from om_order_item where order_id = 1;
select ... from om_order_item_ext where order_id = 1;

#方法二:通过关联查询,一次查出数据(亦可)
select ... from om_order t1,om_order_item t2,om_order_item_ext t2
where t1.order_id = t2.order_id and t1.order_id = t3.order_id and t1.order_id = 1;

  • 规则2 建议按需查询字段
    • 不建议查询全部字段(SELECT *
    • 尤其在查询一些字段很多的表或者多表关联查询的时候, 更应该避免查询全部字段

如下例子:

#就算查询全部字段,也不建议使用select *

select * from om_order where order_id = 1; //不合适
select field1, field2... where order_id = 2; //推荐
  • 规则3 避免嵌套子查询

  • 规则4 注意MySQL隐式转换规则, 否则SQL语句不会匹配到索引

  • 规则5 降低数据库交互次数

    • 规则1 推荐用多次简单查询获得数据, 权衡有如下好处:
      • 表分散在不同物理库不受影响
      • 业务实现逻辑条理清晰
      • 虽然数据库访问次数变多, 在访问次数控制3次左右, 能达到一个好的平衡. 但是如果单个业务逻辑数据库访问次数过多, 比如超过10次, 那么性能会急剧下降. 这个时候应当寻找更好的方式, 避免多次交互.

    以下为常见例子:

    1. 用批量插入代替单条插入,比如创建订单的时候需要写入20条订单项目,一定要避免循坏20次来进行插入操作
    2. 比如业务需要查询10个订单极其订单项目详情。那么可以用一次查询出10个订单主体信息,再用一次查询查询出这10个订单的订单项,最后在业务代码中将订单和对应的订单项目组合起来。一定不要在查询出订单主体信息以后,再循坏10次调用数据库连接查询对应的订单项信息
  • 规则6 在影响行数确定的时候使用limit

    • 在查找数据、更新数据、删除数据时,如影响行数确定需带上limit + 行数
    • 其一加快速度,其二在出错的情况下降低错误影响范围;
    • 有大量数据修改是,可使用limit来限制单次操作行数,减少操作响应时间
    ###以下为常见例子:
    select ... from um_user_info where uid = 1 limit 1; //推荐
    update um_user_info set age = 18 where uid = 1 limit 1; //推荐
    
  • 规则7 查询时禁止对索引字段使用函数或计算

    • SQL的查询条件,直接对某字段使用了函数或者进行运算,索引无效
    ### 以下为示例
    select ... from om_order where order_id - 1 = 99;//不会使用索引
    select ... from om_order where order_id = 99 + 1;//会使用索引,但是不推荐
    select ... from om_order where order_id = 100;//会使用索引, 推荐。(变量运算尽量在业务代码中完成)
    
  • 规则8 谨慎使用 NOT INNOT LIKE

    • NOT INNOT LIKE会造成全表扫描,避免使用,可用JOIN代替
  • 规则9 IN 语句一次查询集合不宜太大

    • 在in语句中, 附带的集合不宜超过500个, 如果查询的集合太大就算有索引, 效率也会受损, 此种情况可以考虑业务上优化.
  • 规则10 字符串模糊查询注意事项

    • 单向模糊匹配, 被查询的字段需要建立索引
    • 建立索引后, 需注意查询条件避免造成大范围检索, 比如搜索订单商品, 虽然barcode字段有索引, 但是如果查询条件是 LIKE “DI%”, 那么索引其实不会起到具体作用.
    • 禁止使用双向模糊匹配, 此类优化可以从需求层面解决或者通过全文搜索应用来解决. 如果一定要使用双向模糊匹配, 也一定要将搜索范围控制到非常窄的范围内进行模糊查询.
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
8.用执行计划分析SQL性能      EXPLAIN PLAN是一个很好的分析SQL语句的工具,它可以在不执行SQL的情况下分析语句      通过分析,我们就可以知道ORACLE是怎样连接表,使用什么方式扫描表(索引扫描或全表扫描),以及使用到的索引名称      按照从里到外,从上到下的次序解读分析的结果      EXPLAIN PLAN的分析结果是用缩进的格式排列的,最内部的操作将最先被解读,如果两个操作处于同一层中,带有最小操作号的将首先被执行      目前许多第三方的工具如PLSQL Developer和TOAD等都提供了极其方便的EXPLAIN PLAN工具      PG需要将自己添加的SQL文记入log,然后在EXPLAIN PLAN中进行分析,尽量减少全表扫描      ORACLE SQL性能优化系列      1.选择最有效率的表名顺序(只在基于规则的优化器中有效)      ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表driving table)将被最先处理      在FROM子句中包含多个表的情况下,必须选择记录条数最少的表作为基础表      当ORACLE处理多个表时,会运用排序及合并的方式连接它们      首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行排序;      然后扫描第二个表(FROM子句中最后第二个表);      最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并      例如:      表 TAB1 16,384 条记录      表 TAB2 5 条记录      选择TAB2作为基础表 (最好的方法)      select count(*) from tab1,tab2 执行时间0.96秒      选择TAB2作为基础表 (不佳的方法)      select count(*) from tab2,tab1 执行时间26.09秒      如果有3个以上的表连接询,那就需要选择交叉表(intersection table)作为基础表,交叉表是指那个被其他表所引用的表      例如:   EMP表描述了LOCATION表和CATEGORY表的交集   SELECT *   FROM LOCATION L,   CATEGORY C,   EMP E   WHERE E.EMP_NO BETWEEN 1000 AND 2000   AND E.CAT_NO = C.CAT_NO   AND E.LOCN = L.LOCN      将比下列SQL更有效率   SELECT *   FROM EMP E ,   LOCATION L ,   CATEGORY C   WHERE E.CAT_NO = C.CAT_NO   AND E.LOCN = L.LOCN   AND E.EMP_NO BETWEEN 1000 AND 2000      2.WHERE子句中的连接顺序      ORACLE采用自下而上的顺序解析WHERE子句      根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾      例如:   (低效,执行时间156.3秒)   SELECT *   FROM EMP E   WHERE SAL > 50000   AND JOB = 'MANAGER'   AND 25 < (SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO);      (高效,执行时间10.6秒)   SELECT *   FROM EMP E   WHERE 25 50000   AND JOB = 'MANAGER';      3.SELECT子句中避免使用'*'      当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用'*'是一个方便的方法,不幸的是,这是一个非常低效的方法      实际上,ORACLE在解析的过程中,会将'*'依次转换成所有的列名      这个工作是通过询数据字典完成的,这意味着将耗费更多的时间      4.减少访问数据库的次数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值