书写高质量SQL的建议
<p><img title="书写高质量SQL的建议" alt="书写高质量SQL的建议" border="0" height="auto" src="https://zhuji.jb51.net/uploads/img/202305/27a6211a8225b51da65b6d1e9213b700.jpg" width="auto"></p>
<h3>
1、避免混乱的逻辑</h3>
<p>
反例:(统计用户数量)</p>
<ol class="dp-sql">
<li class="alt">
<span><span>List<</span><span class="func">User</span><span>> users = userMapper.selectAll(); </span></span>
</li>
<li>
<span><span class="keyword">return</span><span> users.</span><span class="keyword">size</span><span>(); </span></span>
</li>
</ol>
<p>
正例:</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">int</span><span> </span><span class="func">count</span><span> = userMapper.countUser(</span><span class="string">"select count(*) from user"</span><span>); </span></span>
</li>
<li>
<span><span class="keyword">return</span><span> </span><span class="func">count</span><span>; </span></span>
</li>
</ol>
<h3>
2、select one 如果已知结果只有一条, 使用limit 1</h3>
<p>
反例:(查找nickname = 报之琼瑶 的用户)</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span> id, nickname </span><span class="keyword">from</span><span> t </span><span class="keyword">where</span><span> nickname = </span><span class="string">'报之琼瑶'</span><span> </span></span>
</li>
</ol>
<p>
正例:</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span> id, nickname </span><span class="keyword">from</span><span> t </span><span class="keyword">where</span><span> nickname = </span><span class="string">'报之琼瑶'</span><span> limit 1 </span></span>
</li>
</ol>
<p>
理由:</p>
<ol>
<li>
加上limit1,只要找到了对应的一条记录, 就不会继续向下扫描了,效率会大大提高。limit1适用于查询结果为1条(也可能为0)会导致全表扫描的的SQL语句。</li>
<li>
如果条件列上有索引就不用limit 1,如主键查询 id = 1</li>
</ol>
<h3>
3、尽量避免在where子句中使用or来连接条件</h3>
<p>
反例:(查找name = 张三 或者 法外狂徒 的用户)</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span> id,</span><span class="keyword">name</span><span> </span><span class="keyword">from</span><span> t </span><span class="keyword">where</span><span> </span><span class="keyword">name</span><span> = </span><span class="string">'张三'</span><span> </span><span class="op">or</span><span> </span><span class="keyword">name</span><span> = </span><span class="string">'法外狂徒'</span><span> </span></span>
</li>
</ol>
<p>
正例:</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span> id,</span><span class="keyword">name</span><span> </span><span class="keyword">from</span><span> t </span><span class="keyword">where</span><span> </span><span class="keyword">name</span><span> = </span><span class="string">'张三'</span><span> </span></span>
</li>
<li>
<span><span class="keyword">union</span><span> </span><span class="op">all</span><span> </span></span>
</li>
<li class="alt">
<span><span class="keyword">select</span><span> id,</span><span class="keyword">name</span><span> </span><span class="keyword">from</span><span> t </span><span class="keyword">where</span><span> </span><span class="keyword">name</span><span> = </span><span class="string">'法外狂徒'</span><span> </span></span>
</li>
</ol>
<p>
理由:</p>
<p>
使用or将导致引擎放弃使用索引而进行全表扫描</p>
<h3>
4、优化like关键字</h3>
<p>
like常用于模糊查询, 不恰当的编码会导致索引失效</p>
<p>
反例:</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span> userId,</span><span class="keyword">name</span><span> </span><span class="keyword">from</span><span> </span><span class="func">user</span><span> </span><span class="keyword">where</span><span> userId </span><span class="op">like</span><span> </span><span class="string">'%123'</span><span> </span></span>
</li>
</ol>
<p>
正例:</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span> userId,</span><span class="keyword">name</span><span> </span><span class="keyword">from</span><span> </span><span class="func">user</span><span> </span><span class="keyword">where</span><span> userId </span><span class="op">like</span><span> </span><span class="string">'123%'</span><span> </span></span>
</li>
</ol>
<center>
<img title="书写高质量SQL的建议" alt="书写高质量SQL的建议" src="https://zhuji.jb51.net/uploads/img/202305/d975a74437bc1d399e1c7635869ee571.jpg">
</center>
<p>
%123, 百分号在前不走索引</p>
<center>
<img title="书写高质量SQL的建议" alt="书写高质量SQL的建议" src="https://zhuji.jb51.net/uploads/img/202305/acd1562cb47e6e06966ddb0c575a5795.jpg">
</center>
<p>
123%,百分号在后走索引</p>
<p>
但是也会存在百分号在后不走索引的情况,mysql的innodb存储引擎最终执行哪种方法都是基于成本计算的, 通过比较全表扫描和二级索引比较再回表查询</p>
<p>
可以通过</p>
<p>
INFORMATION_SCHEMA.OPTIMIZER_TRACE来分析查询过程</p>
<center>
<img title="书写高质量SQL的建议" alt="书写高质量SQL的建议" src="https://zhuji.jb51.net/uploads/img/202305/8487b89390b4a345320d784cd8f18db2.jpg">
</center>
<p>
trace字段json复制出来即可分析</p>
<h3>
5、查询SQL尽量不要使用select *,而是select具体字段, 不要返回用不到的任何字段。</h3>
<p>
反例:(统计用户数量)</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span> * </span><span class="keyword">from</span><span> t </span></span>
</li>
</ol>
<p>
正例:</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span> id, </span><span class="keyword">name</span><span>, tel </span><span class="keyword">from</span><span> t </span></span>
</li>
</ol>
<p>
理由:</p>
<ol>
<li>
妨碍优化器选择更优的执行计划,比如说索引扫描</li>
<li>
增删字段可能导致代码崩溃</li>
</ol>
<p>
6、尽量避免在索引列上使用mysql的内置函数</p>
<p>
反例:</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span> * </span><span class="keyword">from</span><span> </span><span class="func">user</span><span> </span><span class="keyword">where</span><span> date_add(create_time,Interval 5 </span><span class="func">day</span><span>) >=now() </span></span>
</li>
</ol>
<p>
正例:</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span> * </span><span class="keyword">from</span><span> </span><span class="func">user</span><span> </span><span class="keyword">where</span><span> create_time >= date_add(now(), interval - 5 </span><span class="func">day</span><span>) </span></span>
</li>
</ol>
<center>
<img title="书写高质量SQL的建议" alt="书写高质量SQL的建议" src="https://zhuji.jb51.net/uploads/img/202305/84301c689b1556bbc1d1190b4dc9fe6b.jpg">
</center>
<p>
不走索引</p>
<center>
<img title="书写高质量SQL的建议" alt="书写高质量SQL的建议" src="https://zhuji.jb51.net/uploads/img/202305/555839d485185b5581d84b600f93dd24.jpg">
</center>
<p>
走索引</p>
<h3>
7、应尽量避免在 where 子句中对字段进行表达式操作,这将导致系统放弃使用索引而进行全表扫</h3>
<p>
反例: (对字段user_age进行运算操作, 不走索引)</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span> * </span><span class="keyword">from</span><span> </span><span class="func">user</span><span> </span><span class="keyword">where</span><span> user_age - 1 = 2 </span></span>
</li>
</ol>
<p>
正例: (走索引)</p>
<ol class="dp-sql">
<li class="alt">
<span><span class="keyword">select</span><span> * </span><span class="keyword">from</span><span> </span><span class="func">user</span><span> </span><span class="keyword">where</span><span> user_age = 3 </span></span>
</li>
</ol>
<p>
原文链接:https://www.toutiao.com/a6992763976006271496/</p>
頁:
[1]