nqkk58 发表于 2024-8-4 15:54:25

52条SQL语句性能优化策略,意见保藏


    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">阅读本文大概<span style="color: black;">必须</span> 12.5 分钟。</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">来自:<span style="color: black;">cnblogs.com/SimpleWu/p/9929043.html</span></span></p><span style="color: black;">本文会<span style="color: black;">说到</span> 52 条 SQL 语句性能优化策略。</span><span style="color: black;">1、对<span style="color: black;">查找</span>进行优化,应<span style="color: black;">尽可能</span>避免全表扫描,<span style="color: black;">首要</span>应<span style="color: black;">思虑</span>在 WHERE 及 ORDER BY <span style="color: black;">触及</span>的列上<span style="color: black;">创立</span>索引。</span><span style="color: black;">2、应<span style="color: black;">尽可能</span>避免在 WHERE 子句中对字段进行 NULL 值判断,创建表时 NULL 是默认值,但大<span style="color: black;">都数</span>时候应该<span style="color: black;">运用</span> NOT NULL,<span style="color: black;">或</span><span style="color: black;">运用</span>一个特殊的值,如 0,-1 <span style="color: black;">做为</span>默认值。</span><span style="color: black;">3、应<span style="color: black;">尽可能</span>避免在 WHERE 子句中<span style="color: black;">运用</span> !=&nbsp;或 &lt;&gt; 操作符。MySQL <span style="color: black;">仅有</span>对以下操作符才<span style="color: black;">运用</span>索引:&lt;,&lt;=,=,&gt;,&gt;=,BETWEEN,IN,以及某些时候的 LIKE。</span><span style="color: black;">4、应<span style="color: black;">尽可能</span>避免在 WHERE 子句中<span style="color: black;">运用</span> OR 来连接<span style="color: black;">要求</span>,否则将<span style="color: black;">引起</span>引擎放弃<span style="color: black;">运用</span>索引而进行全表扫描,<span style="color: black;">能够</span><span style="color: black;">运用</span> UNION 合并<span style="color: black;">查找</span>:</span><span style="color: black;">select id from t where num=10 union all select id from t where num=20</span><span style="color: black;">。</span><span style="color: black;">5、IN 和 NOT IN <span style="color: black;">亦</span>要慎用,否则会<span style="color: black;">引起</span>全表扫描。<span style="color: black;">针对</span>连续的数值,能用 BETWEEN 就不要用 IN:</span><span style="color: black;">select id from t where num between 1 and 3</span><span style="color: black;">。</span><span style="color: black;">6、下面的<span style="color: black;">查找</span><span style="color: black;">亦</span>将<span style="color: black;">引起</span>全表扫描:</span><span style="color: black;">select id from t where name like‘%abc%’</span><span style="color: black;"><span style="color: black;">或</span>select id from t where name like‘%abc’若要提<span style="color: black;">有效</span>率,<span style="color: black;">能够</span><span style="color: black;">思虑</span>全文检索。而select id from t where name like‘abc%’才用到索引。</span><span style="color: black;">7、<span style="color: black;">倘若</span>在 WHERE 子句中<span style="color: black;">运用</span>参数,<span style="color: black;">亦</span>会<span style="color: black;">引起</span>全表扫描。</span><span style="color: black;">8、应<span style="color: black;">尽可能</span>避免在 WHERE 子句中对字段进行表达式操作,应<span style="color: black;">尽可能</span>避免在 WHERE 子句中对字段进行函数操作。</span><span style="color: black;">9、<span style="color: black;">非常多</span>时候用 EXISTS 代替 IN 是一个好的<span style="color: black;">选取</span>:</span><span style="color: black;">select num from a where num in(select num from b)</span><span style="color: black;">。用下面的语句替换:</span><span style="color: black;">select num from a where exists(select 1 from b where num=a.num)</span><span style="color: black;">。</span><span style="color: black;"><span style="color: black;">十、</span>索引固然<span style="color: black;">能够</span><span style="color: black;">加强</span>相应的 SELECT 的效率,但<span style="color: black;">同期</span><span style="color: black;">亦</span>降低了 INSERT 及 UPDATE 的效。<span style="color: black;">由于</span> INSERT 或 UPDATE 时有可能会重建索引,<span style="color: black;">因此</span><span style="color: black;">怎么样</span>建索引<span style="color: black;">必须</span><span style="color: black;">谨慎</span><span style="color: black;">思虑</span>,视<span style="color: black;">详细</span><span style="color: black;">状况</span>而定。一个表的索引数最好不要超过 6 个,若太多则应<span style="color: black;">思虑</span><span style="color: black;">有些</span>不常<span style="color: black;">运用</span>到的列上建的索引<span style="color: black;">是不是</span>有必要。</span><span style="color: black;">11、应尽可能的避免更新 clustered 索引数据列, <span style="color: black;">由于</span> clustered 索引数据列的<span style="color: black;">次序</span><span style="color: black;">便是</span>表记录的<span style="color: black;">理学</span>存储<span style="color: black;">次序</span>,一旦该列值改变将<span style="color: black;">引起</span><span style="color: black;">全部</span>表记录的<span style="color: black;">次序</span>的<span style="color: black;">调节</span>,会耗费相当大的资源。若应用系统<span style="color: black;">必须</span>频繁更新 clustered 索引数据列,<span style="color: black;">那样</span><span style="color: black;">必须</span><span style="color: black;">思虑</span><span style="color: black;">是不是</span>应将该索引建为 clustered 索引。</span><span style="color: black;">12、<span style="color: black;">尽可能</span><span style="color: black;">运用</span>数字型字段,若只含数值信息的字段<span style="color: black;">尽可能</span>不要设计为字符型,这会降低<span style="color: black;">查找</span>和连接的性能,并会<span style="color: black;">增多</span>存储开销。</span><span style="color: black;">13、尽可能的<span style="color: black;">运用</span> varchar, nvarchar 代替 char, nchar。<span style="color: black;">由于</span><span style="color: black;">首要</span>变长字段存储空间小,<span style="color: black;">能够</span>节省存储空间,其次<span style="color: black;">针对</span><span style="color: black;">查找</span><span style="color: black;">来讲</span>,在一个相对较小的字段内搜索效率显然要高些。</span><span style="color: black;">14、最好不要<span style="color: black;">运用</span>返回所有:</span><span style="color: black;">select from t&nbsp;</span><span style="color: black;">,用<span style="color: black;">详细</span>的字段列表代替 “*”,不要返回用不到的任何字段。</span><span style="color: black;">15、<span style="color: black;">尽可能</span>避免向客户端返回大数据量,若数据量过大,应该<span style="color: black;">思虑</span>相应需求<span style="color: black;">是不是</span><span style="color: black;">恰当</span>。</span><span style="color: black;">16、<span style="color: black;">运用</span>表的别名(Alias):当在 SQL 语句中连接多个表时,请<span style="color: black;">运用</span>表的别名并把别名前缀于<span style="color: black;">每一个</span> Column 上。<span style="color: black;">这般</span>一来,就<span style="color: black;">能够</span>减少解析的时间并减少<span style="color: black;">哪些</span>由 Column 歧义<span style="color: black;">导致</span>的语法错误。</span><span style="color: black;">17、<span style="color: black;">运用</span>“临时表”暂存中间结果 :</span><span style="color: black;">简化 SQL 语句的重要<span style="color: black;">办法</span><span style="color: black;">便是</span>采用临时表暂存中间结果。<span style="color: black;">然则</span>临时表的好处远远不止这些,将临时结果暂存在临时表,后面的<span style="color: black;">查找</span>就在 tempdb 中了,这<span style="color: black;">能够</span>避免程序中多次扫描主表,<span style="color: black;">亦</span>大大减少了程序执行中“共享锁”阻塞“更新锁”,减少了阻塞,<span style="color: black;">加强</span>了并发性能。</span><span style="color: black;">18、<span style="color: black;">有些</span> SQL <span style="color: black;">查找</span>语句应加上 nolock,读、写是会相互阻塞的,为了<span style="color: black;">加强</span>并发性能。<span style="color: black;">针对</span><span style="color: black;">有些</span><span style="color: black;">查找</span>,<span style="color: black;">能够</span>加上 nolock,<span style="color: black;">这般</span>读的时候<span style="color: black;">能够</span><span style="color: black;">准许</span>写,但缺点是可能读到未提交的脏数据。</span><span style="color: black;"><span style="color: black;">运用</span> nolock 有3条原则:</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">查找</span>的结果用于“插、删、改”的<span style="color: black;">不可</span>加 nolock;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">查找</span>的表属于频繁<span style="color: black;">出现</span>页分裂的,慎用 nolock ;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">运用</span>临时表<span style="color: black;">同样</span><span style="color: black;">能够</span><span style="color: black;">保留</span>“数据前影”,起到类似 Oracle 的 undo 表空间的功能,能采用临时表<span style="color: black;">加强</span>并发性能的,不要用 nolock。</span></p><span style="color: black;">19、<span style="color: black;">平常</span>的简化规则如下:</span><span style="color: black;">不要有超过 5 个以上的表连接(JOIN),<span style="color: black;">思虑</span><span style="color: black;">运用</span>临时表或表变量存放中间结果。少用子<span style="color: black;">查找</span>,视图嵌套不要过深,<span style="color: black;">通常</span>视图嵌套不要超过 2 个为宜。</span><span style="color: black;">20、将<span style="color: black;">必须</span><span style="color: black;">查找</span>的结果预先计算好放在表中,<span style="color: black;">查找</span>的时候再Select。这在SQL7.0以前是最重要的手段,例如医院的住院费计算。</span><span style="color: black;">21、用 OR 的字句<span style="color: black;">能够</span>分解成多个<span style="color: black;">查找</span>,并且<span style="color: black;">经过</span> UNION 连接多个<span style="color: black;">查找</span>。<span style="color: black;">她们</span>的速度只同<span style="color: black;">是不是</span><span style="color: black;">运用</span>索引<span style="color: black;">相关</span>,<span style="color: black;">倘若</span><span style="color: black;">查找</span><span style="color: black;">必须</span>用到联合索引,用 UNION all 执行的效率更高。多个 OR 的字句<span style="color: black;">无</span>用到索引,改写成 UNION 的形式再试图与索引匹配。一个关键的问题<span style="color: black;">是不是</span>用到索引。</span><span style="color: black;">22、在IN后面值的列表中,将<span style="color: black;">显现</span>最频繁的值放在最前面,<span style="color: black;">显现</span>得最少的放在最后面,减少判断的次数。</span><span style="color: black;">23、<span style="color: black;">尽可能</span>将数据的处理工作放在服务器上,减少网络的开销,如<span style="color: black;">运用</span>存储过程。</span><span style="color: black;">存储过程是编译好、优化过、并且被组织到一个执行规划里、且存储在数据库中的 SQL 语句,是<span style="color: black;">掌控</span>流语言的集合,速度当然快。反复执行的动态 SQL,<span style="color: black;">能够</span><span style="color: black;">运用</span>临时存储过程,该过程(临时表)被放在 Tempdb 中。</span><span style="color: black;">24、当服务器的内存够多时,配制</span><span style="color: black;"><strong style="color: blue;"><span style="color: black;">线程数量 = 最大连接数+5</span></strong></span><span style="color: black;">,<span style="color: black;">这般</span>能发挥最大的效率;否则<span style="color: black;">运用</span><strong style="color: blue;">配制线程数量&lt; 最大连接数</strong>,启用 SQL SERVER 的线程池来<span style="color: black;">处理</span>,<span style="color: black;">倘若</span>还是<strong style="color: blue;">数量 = 最大连接数+5</strong>,严重的损害服务器的性能。</span><span style="color: black;">
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">25、<span style="color: black;">查找</span>的<span style="color: black;">相关</span>同写的<span style="color: black;">次序</span> :</p>
    </span><span style="color: black;"><span style="color: black;">select</span> a.personMemberID, * <span style="color: black;">from</span> chineseresume a,personmember b <span style="color: black;">where</span> personMemberID = b.referenceid <span style="color: black;">and</span> a.personMemberID = <span style="color: black;">JCNPRH39681</span>(A = B, B =<span style="color: black;">号码</span>) </span><span style="color: black;"><span style="color: black;">select</span> a.personMemberID, * <span style="color: black;">from</span> chineseresume a,personmember b <span style="color: black;">where</span> a.personMemberID = b.referenceid <span style="color: black;">and</span> a.personMemberID = <span style="color: black;">JCNPRH39681</span> <span style="color: black;">and</span>b.referenceid =<span style="color: black;">JCNPRH39681</span> (A = B, B = <span style="color: black;">号码</span>, A = <span style="color: black;">号码</span>) </span><span style="color: black;"><span style="color: black;">select</span> a.personMemberID, * <span style="color: black;">from</span> chineseresume a,personmember b <span style="color: black;">where</span> b.referenceid = <span style="color: black;">JCNPRH39681</span> <span style="color: black;">and</span> a.personMemberID = <span style="color: black;">JCNPRH39681</span> (B = <span style="color: black;">号码</span>, A = <span style="color: black;">号码</span>)</span><span style="color: black;">26、<span style="color: black;">尽可能</span><span style="color: black;">运用</span> EXISTS 代替&nbsp;</span><span style="color: black;">select count(1)</span><span style="color: black;">&nbsp;来判断<span style="color: black;">是不是</span>存在记录。count 函数<span style="color: black;">仅有</span>在统计表中所有行数时<span style="color: black;">运用</span>,<span style="color: black;">况且</span> count(1) 比 count(*) 更有效率。</span><span style="color: black;">27、<span style="color: black;">尽可能</span><span style="color: black;">运用</span> “&gt;=”,不要<span style="color: black;">运用</span> “&gt;”。</span><span style="color: black;">28、索引的<span style="color: black;">运用</span>规范:</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">索引的创建要与应用结合<span style="color: black;">思虑</span>,<span style="color: black;">意见</span>大的 OLTP 表不要超过 6 个索引;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">尽可能的<span style="color: black;">运用</span>索引字段<span style="color: black;">做为</span><span style="color: black;">查找</span><span style="color: black;">要求</span>,尤其是聚簇索引,必要时<span style="color: black;">能够</span><span style="color: black;">经过</span> index index_name 来强制指定索引;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">避免对大表<span style="color: black;">查找</span>时进行 table scan,必要时<span style="color: black;">思虑</span>新建索引;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">在<span style="color: black;">运用</span>索引字段<span style="color: black;">做为</span><span style="color: black;">要求</span>时,<span style="color: black;">倘若</span>该索引是联合索引,<span style="color: black;">那样</span><span style="color: black;">必要</span><span style="color: black;">运用</span>到该索引中的<span style="color: black;">第1</span>个字段<span style="color: black;">做为</span><span style="color: black;">要求</span>时<span style="color: black;">才可</span><span style="color: black;">保准</span>系统<span style="color: black;">运用</span>该索引,否则该索引将不会被<span style="color: black;">运用</span>;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">要<span style="color: black;">重视</span>索引的<span style="color: black;">守护</span>,周期性重建索引,重新编译存储过程。  </span></p><span style="color: black;">
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">29、下列 SQL <span style="color: black;">要求</span>语句中的列都建有恰当的索引,但执行速度却非常慢:</p>
    </span><span style="color: black;"><span style="color: black;">SELECT</span> * <span style="color: black;">FROM</span> <span style="color: black;">record</span> <span style="color: black;">WHERE</span> <span style="color: black;">substrINg</span>(card_no, <span style="color: black;">1</span>, <span style="color: black;">4</span>) = <span style="color: black;">5378</span> <span style="color: black;">--13秒 </span></span><span style="color: black;"><span style="color: black;">SELECT</span> * <span style="color: black;">FROM</span> <span style="color: black;">record</span> <span style="color: black;">WHERE</span> amount/<span style="color: black;">30</span> &lt; <span style="color: black;">1000</span> <span style="color: black;">--11秒 </span></span><span style="color: black;"><span style="color: black;">SELECT</span> * <span style="color: black;">FROM</span> <span style="color: black;">record</span> <span style="color: black;">WHERE</span> <span style="color: black;">convert</span>(<span style="color: black;">char</span>(<span style="color: black;">10</span>), <span style="color: black;">date</span>, <span style="color: black;">112</span>) = <span style="color: black;">19991201</span> <span style="color: black;">--10秒</span></span><span style="color: black;">分析:&nbsp;</span><span style="color: black;">WHERE 子句中对列的任何操作结果都是在 SQL 运行时逐列计算得到的,<span style="color: black;">因此呢</span>它不得不进行表搜索,而<span style="color: black;">无</span><span style="color: black;">运用</span>该列上面的索引。</span><span style="color: black;">
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">倘若</span>这些结果在<span style="color: black;">查找</span>编译时就能得到,<span style="color: black;">那样</span>就<span style="color: black;">能够</span>被 SQL 优化器优化,<span style="color: black;">运用</span>索引,避免表搜索,<span style="color: black;">因此呢</span>将 SQL 重写成下面<span style="color: black;">这般</span>:</p>
    </span><span style="color: black;"><span style="color: black;">SELECT</span> * <span style="color: black;">FROM</span> <span style="color: black;">record</span> <span style="color: black;">WHERE</span> card_no <span style="color: black;">like</span> <span style="color: black;">5378%</span> <span style="color: black;">-- &lt; 1秒 </span></span><span style="color: black;"><span style="color: black;">SELECT</span> * <span style="color: black;">FROM</span> <span style="color: black;">record</span> <span style="color: black;">WHERE</span> amount &lt; <span style="color: black;">1000</span>*<span style="color: black;">30</span> <span style="color: black;">-- &lt; 1秒 </span></span><span style="color: black;"><span style="color: black;">SELECT</span> * <span style="color: black;">FROM</span> <span style="color: black;">record</span> <span style="color: black;">WHERE</span> <span style="color: black;">date</span> = <span style="color: black;">1999/12/01</span> <span style="color: black;">-- &lt; 1秒</span></span><span style="color: black;">30、当有一批处理的<span style="color: black;">插进</span>或更新时,用批量<span style="color: black;">插进</span>或批量更新,绝不会一条条记录的去更新。</span><span style="color: black;">
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">31、在所有的存储过程中,能够用 SQL 语句的,我绝不会用循环去实现。</p>
    </span><span style="color: black;">例如:列出上个月的每一天,我会用 connect by 去递归<span style="color: black;">查找</span>一下,绝不会去用循环从上个月<span style="color: black;">第1</span>天到最后一天。</span><span style="color: black;">32、<span style="color: black;">选取</span>最有效率的表名<span style="color: black;">次序</span>(<span style="color: black;">仅在</span>基于规则的优化器中有效):&nbsp;</span><span style="color: black;">Oracle 的解析器<span style="color: black;">根据</span>从右到左的<span style="color: black;">次序</span>处理 FROM 子句中的表名,FROM 子句中写在最后的表(<span style="color: black;">基本</span>表 driving table)将被最先处理,在 FROM 子句中<span style="color: black;">包括</span>多个表的<span style="color: black;">状况</span>下,你<span style="color: black;">必要</span><span style="color: black;">选取</span>记录条数最少的表<span style="color: black;">做为</span><span style="color: black;">基本</span>表。</span><span style="color: black;"><span style="color: black;">倘若</span>有 3 个以上的表连接<span style="color: black;">查找</span>,那就<span style="color: black;">必须</span><span style="color: black;">选取</span>交叉表(intersection table)<span style="color: black;">做为</span><span style="color: black;">基本</span>表,交叉表<span style="color: black;">指的是</span>那个被其他表所引用的表。</span><span style="color: black;">33、<span style="color: black;">加强</span> GROUP BY 语句的效率,<span style="color: black;">能够</span><span style="color: black;">经过</span>将不<span style="color: black;">必须</span>的记录在 GROUP BY 之前过滤掉。下面两个<span style="color: black;">查找</span>返回相同结果,但第二个<span style="color: black;">显著</span>就快了许多。</span><span style="color: black;">低效:</span><span style="color: black;"><span style="color: black;">SELECT</span> JOB, <span style="color: black;">AVG</span>(SAL) </span><span style="color: black;"><span style="color: black;">FROM</span> EMP </span><span style="color: black;"><span style="color: black;">GROUP</span> <span style="color: black;">BY</span> JOB </span><span style="color: black;"><span style="color: black;">HAVING</span> JOB = <span style="color: black;">PRESIDENT</span> </span><span style="color: black;"><span style="color: black;">OR</span> JOB = <span style="color: black;">MANAGER</span> </span><span style="color: black;"><span style="color: black;">有效</span>:</span><span style="color: black;"><span style="color: black;">SELECT</span> JOB, <span style="color: black;">AVG</span>(SAL) </span><span style="color: black;"><span style="color: black;">FROM</span> EMP</span><span style="color: black;"><span style="color: black;">WHERE</span> JOB = <span style="color: black;">PRESIDENT</span> </span><span style="color: black;"><span style="color: black;">OR</span> JOB = <span style="color: black;">MANAGER</span> </span><span style="color: black;"><span style="color: black;">GROUP</span> <span style="color: black;">BY</span> JOB</span><span style="color: black;">34、SQL 语句用大写,<span style="color: black;">由于</span> Oracle 总是先解析 SQL 语句,把小写的字母转换成大写的再执行。</span><span style="color: black;">35、别名的<span style="color: black;">运用</span>,别名是大型数据库的应用技巧,<span style="color: black;">便是</span>表名、列名在<span style="color: black;">查找</span>中以一个字母为别名,<span style="color: black;">查找</span>速度要比建连接表快 1.5 倍。</span><span style="color: black;">36、避免死锁,在你的存储过程和触发器中<span style="color: black;">拜访</span>同一个表时总是以相同的<span style="color: black;">次序</span>;事务应经可能地缩短,在一个事务中应尽可能减少<span style="color: black;">触及</span>到的数据量;永远不要在事务中等待用户输入。</span><span style="color: black;">37、避免<span style="color: black;">运用</span>临时表,除非却有<span style="color: black;">必须</span>,否则应<span style="color: black;">尽可能</span>避免<span style="color: black;">运用</span>临时表,相反,<span style="color: black;">能够</span><span style="color: black;">运用</span>表变量代替。大<span style="color: black;">都数</span>时候(99%),表变量驻扎在内存中,<span style="color: black;">因此呢</span>速度比临时表更快,临时表驻扎在 TempDb 数据库中,<span style="color: black;">因此呢</span>临时表上的操作<span style="color: black;">必须</span>跨数据库通信,速度自然慢。</span><span style="color: black;">38、最好不要<span style="color: black;">运用</span>触发器:</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">触发一个触发器,执行一个触发器事件本身<span style="color: black;">便是</span>一个耗费资源的过程;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">倘若</span>能够<span style="color: black;">运用</span>约束实现的,<span style="color: black;">尽可能</span>不要<span style="color: black;">运用</span>触发器;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">不要为<span style="color: black;">区别</span>的触发事件(Insert、Update 和 Delete)<span style="color: black;">运用</span>相同的触发器;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">不要在触发器中<span style="color: black;">运用</span>事务型代码。</span></p><span style="color: black;">39、索引创建规则:&nbsp;</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">表的主键、外键<span style="color: black;">必要</span>有索引;&nbsp;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">数据量超过 300 的表应该有索引;&nbsp;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">经常与其他表进行连接的表,在连接字段上应该<span style="color: black;">创立</span>索引;&nbsp;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">经常出<span style="color: black;">此刻</span> WHERE 子句中的字段,<span style="color: black;">尤其</span>是大表的字段,应该<span style="color: black;">创立</span>索引;&nbsp;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">索引应该建在<span style="color: black;">选取</span>性高的字段上;&nbsp;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">索引应该建在小字段上,<span style="color: black;">针对</span>大的文本字段<span style="color: black;">乃至</span>超长字段,不要建索引;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">复合索引的<span style="color: black;">创立</span><span style="color: black;">必须</span>进行仔细分析,<span style="color: black;">尽可能</span><span style="color: black;">思虑</span>用单字段索引代替;&nbsp;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">正确<span style="color: black;">选取</span>复合索引中的主列字段,<span style="color: black;">通常</span>是<span style="color: black;">选取</span>性较好的字段;&nbsp;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">复合索引的几个字段<span style="color: black;">是不是</span>经常<span style="color: black;">同期</span>以 AND 方式出<span style="color: black;">此刻</span> WHERE 子句中?单字段<span style="color: black;">查找</span><span style="color: black;">是不是</span>极少<span style="color: black;">乃至</span><span style="color: black;">无</span>?<span style="color: black;">倘若</span>是,则<span style="color: black;">能够</span><span style="color: black;">创立</span>复合索引;否则<span style="color: black;">思虑</span>单字段索引;&nbsp;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">如果复合索引中<span style="color: black;">包括</span>的字段经常单独出<span style="color: black;">此刻</span> WHERE 子句中,则分解为多个单字段索引;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">倘若</span>复合索引所<span style="color: black;">包括</span>的字段超过 3 个,<span style="color: black;">那样</span>仔细<span style="color: black;">思虑</span>其必要性,<span style="color: black;">思虑</span>减少复合的字段;&nbsp;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">倘若</span>既有单字段索引,又有这几个字段上的复合索引,<span style="color: black;">通常</span><span style="color: black;">能够</span>删除复合索引;&nbsp;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">频繁进行数据操作的表,不要<span style="color: black;">创立</span>太多的索引;&nbsp;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">删除无用的索引,避免对执行计划<span style="color: black;">导致</span><span style="color: black;">消极</span>影响;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">表上<span style="color: black;">创立</span>的<span style="color: black;">每一个</span>索引都会<span style="color: black;">增多</span>存储开销,索引<span style="color: black;">针对</span><span style="color: black;">插进</span>、删除、更新操作<span style="color: black;">亦</span>会<span style="color: black;">增多</span>处理上的开销。<span style="color: black;">另一</span>,<span style="color: black;">太多</span>的复合索引,在有单字段索引的<span style="color: black;">状况</span>下,<span style="color: black;">通常</span>都是<span style="color: black;">无</span>存在价值的;相反,还会降低数据<span style="color: black;">增多</span>删除时的性能,<span style="color: black;">尤其</span>是对频繁更新的表<span style="color: black;">来讲</span>,<span style="color: black;">消极</span>影响更大。&nbsp;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">尽可能</span>不要对数据库中某个含有<span style="color: black;">海量</span>重复的值的字段<span style="color: black;">创立</span>索引。</span></p><span style="color: black;">40、MySQL <span style="color: black;">查找</span>优化总结:</span><span style="color: black;"><span style="color: black;">运用</span>慢<span style="color: black;">查找</span>日志去<span style="color: black;">发掘</span>慢<span style="color: black;">查找</span>,<span style="color: black;">运用</span>执行计划去判断<span style="color: black;">查找</span><span style="color: black;">是不是</span>正常运行,总是去测试你的<span style="color: black;">查找</span><span style="color: black;">瞧瞧</span><span style="color: black;">是不是</span><span style="color: black;">她们</span>运行在最佳状态下。</span><span style="color: black;">久而久之性能总会变化,避免在<span style="color: black;">全部</span>表上<span style="color: black;">运用</span> count(*),它可能锁住整张表,使<span style="color: black;">查找</span>保持一致以便后续<span style="color: black;">类似</span>的<span style="color: black;">查找</span><span style="color: black;">能够</span><span style="color: black;">运用</span><span style="color: black;">查找</span>缓存,在适当的情形下<span style="color: black;">运用</span> GROUP BY 而不是 DISTINCT,在 WHERE、GROUP BY 和 ORDER BY 子句中<span style="color: black;">运用</span>有索引的列,保持索引简单,不在多个索引中<span style="color: black;">包括</span>同一个列。</span><span style="color: black;">有时候 MySQL 会<span style="color: black;">运用</span>错误的索引,<span style="color: black;">针对</span>这种<span style="color: black;">状况</span><span style="color: black;">运用</span> USE INDEX,<span style="color: black;">检测</span><span style="color: black;">运用</span> SQL_MODE=STRICT 的问题,<span style="color: black;">针对</span>记录数<span style="color: black;">少于</span>5的索引字段,在 UNION 的时候<span style="color: black;">运用</span>LIMIT不是是用OR。</span><span style="color: black;">为了避免在更新前 SELECT,<span style="color: black;">运用</span> INSERT ON DUPLICATE KEY <span style="color: black;">或</span> INSERT IGNORE;不要用 UPDATE 去实现,不要<span style="color: black;">运用</span> MAX;<span style="color: black;">运用</span>索引字段和 ORDER BY子句 LIMIT M,N <span style="color: black;">实质</span>上<span style="color: black;">能够</span>减缓<span style="color: black;">查找</span>在某些<span style="color: black;">状况</span>下,有节制地<span style="color: black;">运用</span>,在 WHERE 子句中<span style="color: black;">运用</span> UNION 代替子<span style="color: black;">查找</span>,在重新<span style="color: black;">起步</span>的 MySQL,记得来温暖你的数据库,以<span style="color: black;">保证</span>数据在内存和<span style="color: black;">查找</span>速度快,<span style="color: black;">思虑</span>持久连接,而不是多个连接,以减少开销。</span><span style="color: black;">基准<span style="color: black;">查找</span>,<span style="color: black;">包含</span><span style="color: black;">运用</span>服务器上的负载,有时一个简单的<span style="color: black;">查找</span><span style="color: black;">能够</span>影响其他<span style="color: black;">查找</span>,当负载<span style="color: black;">增多</span>在服务器上,<span style="color: black;">运用</span> SHOW PROCESSLIST 查看慢的和有问题的<span style="color: black;">查找</span>,在<span style="color: black;">研发</span>环境中产生的镜像数据中测试的所有可疑的<span style="color: black;">查找</span>。</span><span style="color: black;">41、MySQL 备份过程:</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">从二级复制服务器上进行备份;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">在进行备份<span style="color: black;">时期</span>停止复制,以避免在数据依赖和外键约束上<span style="color: black;">显现</span>不一致;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">彻底停止 MySQL,从数据库文件进行备份;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">倘若</span><span style="color: black;">运用</span> MySQL dump 进行备份,请<span style="color: black;">同期</span>备份二进制日志文件 – <span style="color: black;">保证</span>复制<span style="color: black;">无</span>中断;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">不要信任 LVM 快照,这很可能产生数据不一致,将来会给你带来麻烦;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">为了<span style="color: black;">更易</span>进行单表恢复,以表为单位导出数据——<span style="color: black;">倘若</span>数据是与其他表隔离的。&nbsp;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">当<span style="color: black;">运用</span> mysqldump 时请<span style="color: black;">运用</span> –opt;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">在备份之前<span style="color: black;">检测</span>和优化表;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">为了更快的进行导入,在导入时临时禁用外键约束。;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">为了更快的进行导入,在导入时临时禁用<span style="color: black;">独一</span>性检测;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">在每一次备份后计算数据库,表以及索引的尺寸,以便更够监控数据尺寸的增长;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">经过</span>自动调度脚本监控复制实例的错误和延迟;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">定时</span>执行备份。</span></p><span style="color: black;">42、<span style="color: black;">查找</span>缓冲并不自动处理空格,<span style="color: black;">因此呢</span>,在写 SQL 语句时,应<span style="color: black;">尽可能</span>减少空格的<span style="color: black;">运用</span>,尤其是在 SQL 首和尾的空格(<span style="color: black;">由于</span><span style="color: black;">查找</span>缓冲并不自动截取首尾空格)。</span><span style="color: black;">43、member 用 mid 做标准进行分表方便<span style="color: black;">查找</span>么?<span style="color: black;">通常</span>的业务需求中基本上都是以 username 为<span style="color: black;">查找</span>依据,正常应当是 username 做 hash 取模来分表。</span><span style="color: black;">而分表的话 MySQL 的 partition 功能<span style="color: black;">便是</span>干这个的,对代码是透明的;</span><span style="color: black;">在代码层面去实现貌似是不<span style="color: black;">恰当</span>的。</span><span style="color: black;">44、<span style="color: black;">咱们</span>应该为数据库里的每张表都设置一个 ID 做为其主键,<span style="color: black;">况且</span>最好的是一个 INT 型的(<span style="color: black;">举荐</span><span style="color: black;">运用</span> UNSIGNED),并设置上自动<span style="color: black;">增多</span>的 AUTO_INCREMENT 标志。</span><span style="color: black;">45、在所有的存储过程和触发器的<span style="color: black;">起始</span>处设置 SET NOCOUNT ON,在结束时设置 SET NOCOUNT OFF。</span><span style="color: black;">无需在执行存储过程和触发器的<span style="color: black;">每一个</span>语句后向客户端发送 DONE_IN_PROC <span style="color: black;">信息</span>。</span><span style="color: black;">46、MySQL <span style="color: black;">查找</span><span style="color: black;">能够</span>启用高速<span style="color: black;">查找</span>缓存。这是<span style="color: black;">加强</span>数据库性能的有效MySQL优化<span style="color: black;">办法</span>之一。当同一个<span style="color: black;">查找</span>被执行多次时,从缓存中提取数据和直接从数据库中返回数据快<span style="color: black;">非常多</span>。</span><span style="color: black;">47、EXPLAIN SELECT <span style="color: black;">查找</span>用来跟踪查看效果:</span><span style="color: black;"><span style="color: black;">运用</span> EXPLAIN 关键字<span style="color: black;">能够</span>让你<span style="color: black;">晓得</span> MySQL 是<span style="color: black;">怎样</span>处理你的 SQL 语句的。这<span style="color: black;">能够</span>帮你分析你的<span style="color: black;">查找</span>语句或是表结构的性能瓶颈。</span><span style="color: black;">EXPLAIN 的<span style="color: black;">查找</span>结果还会告诉你你的索引主键被<span style="color: black;">怎样</span>利用的,你的数据表是<span style="color: black;">怎样</span>被搜索和排序的。</span><span style="color: black;">48、当只要一行数据时<span style="color: black;">运用</span> LIMIT 1 :</span><span style="color: black;">当你<span style="color: black;">查找</span>表的有些时候,你<span style="color: black;">已然</span><span style="color: black;">晓得</span>结果只会有一条结果,但<span style="color: black;">由于</span>你可能<span style="color: black;">必须</span>去fetch游标,或是你<span style="color: black;">亦</span>许会去<span style="color: black;">检测</span>返回的记录数。</span><span style="color: black;">在这种<span style="color: black;">状况</span>下,加上 LIMIT 1 <span style="color: black;">能够</span><span style="color: black;">增多</span>性能。</span><span style="color: black;"><span style="color: black;">这般</span>一来,MySQL 数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合记录的数据。</span><span style="color: black;">49、选择表合适存储引擎:</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">myisam:</span></strong><span style="color: black;">应用时以读和<span style="color: black;">插进</span>操<span style="color: black;">做为</span>主,<span style="color: black;">仅有</span>少量的更新和删除,并且对事务的完整性,并发性<span style="color: black;">需求</span>不是很高的。&nbsp;</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">InnoDB:</span></strong><span style="color: black;">事务处理,以及并发<span style="color: black;">要求</span>下<span style="color: black;">需求</span>数据的一致性。除了<span style="color: black;">插进</span>和<span style="color: black;">查找</span>外,<span style="color: black;">包含</span><span style="color: black;">非常多</span>的更新和删除。(InnoDB 有效地降低删除和更新<span style="color: black;">引起</span>的锁定)。</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">针对</span>支持事务的 InnoDB类 型的表<span style="color: black;">来讲</span>,影响速度的<span style="color: black;">重点</span><span style="color: black;">原由</span>是 AUTOCOMMIT 默认设置是打开的,<span style="color: black;">况且</span>程序<span style="color: black;">无</span>显式调用 BEGIN <span style="color: black;">起始</span>事务,<span style="color: black;">引起</span>每<span style="color: black;">插进</span>一条都自动提交,严重影响了速度。<span style="color: black;">能够</span>在执行 SQL 前调用 begin,多条 SQL 形成一个事物(即使 autocommit 打开<span style="color: black;">亦</span><span style="color: black;">能够</span>),将大大<span style="color: black;">加强</span>性能。</span></p><span style="color: black;">50、优化表的数据类型,<span style="color: black;">选取</span>合适的数据类型:</span><strong style="color: blue;"><span style="color: black;">原则:</span></strong><span style="color: black;">更小<span style="color: black;">一般</span>更好,简单就好,所有字段都得有默认值,<span style="color: black;">尽可能</span>避免 NULL。&nbsp;</span><span style="color: black;">例如:数据库表设计时候更小的占磁盘空间尽可能<span style="color: black;">运用</span>更小的整数类型。(mediumint 就比 int 更合适)&nbsp;</span><span style="color: black;"><span style="color: black;">例如</span>时间字段:datetime 和 timestamp。datetime 占用8个字节,timestamp 占用4个字节,只用了一半。而 timestamp <span style="color: black;">暗示</span>的范围是 1970—2037 适合做更新时间。</span><span style="color: black;">MySQL<span style="color: black;">能够</span>很好的支持大数据量的存取,<span style="color: black;">然则</span><span style="color: black;">通常</span>说来,数据库中的表越小,在它上面执行的<span style="color: black;">查找</span><span style="color: black;">亦</span>就会越快。&nbsp;</span><span style="color: black;"><span style="color: black;">因此呢</span>,在创建表的时候,为了<span style="color: black;">得到</span>更好的性能,<span style="color: black;">咱们</span><span style="color: black;">能够</span>将表中字段的宽度设得尽可能小。</span><span style="color: black;">例如:</span><span style="color: black;">在定义邮政编码这个字段时,<span style="color: black;">倘若</span>将其设置为 CHAR(255),显然给数据库<span style="color: black;">增多</span>了不必要的空间。</span><span style="color: black;"><span style="color: black;">乃至</span><span style="color: black;">运用</span>VARCHAR 这种类型<span style="color: black;">亦</span>是多余的,<span style="color: black;">由于</span> CHAR(6) 就<span style="color: black;">能够</span>很好的完成任务了。</span><span style="color: black;"><span style="color: black;">一样</span>的,<span style="color: black;">倘若</span><span style="color: black;">能够</span>的话,<span style="color: black;">咱们</span>应该<span style="color: black;">运用</span> MEDIUMINT 而不是 BIGIN 来定义整型字段,应该<span style="color: black;">尽可能</span>把字段设置为 NOT NULL,<span style="color: black;">这般</span>在将来执行<span style="color: black;">查找</span>的时候,数据库<span style="color: black;">不消</span>去比较 NULL 值。</span><span style="color: black;"><span style="color: black;">针对</span>某些文本字段,例如“省份”<span style="color: black;">或</span>“性别”,<span style="color: black;">咱们</span><span style="color: black;">能够</span>将它们定义为 ENUM 类型。<span style="color: black;">由于</span>在 MySQL 中,ENUM 类型被当作数值型数据来处理,</span><span style="color: black;">而数值型数据被处理起来的速度要比文本类型快得多。<span style="color: black;">这般</span>,<span style="color: black;">咱们</span>又<span style="color: black;">能够</span><span style="color: black;">加强</span>数据库的性能。</span><span style="color: black;">51、字符串数据类型:char, varchar, text <span style="color: black;">选取</span>区别。</span><span style="color: black;">52、任何对列的操作都将<span style="color: black;">引起</span>表扫描,它<span style="color: black;">包含</span>数据库函数、计算表达式等等,<span style="color: black;">查找</span>时要尽可能将操作移至等号右边。</span><span style="color: black;">&lt;END&gt;</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">举荐</span>阅读:</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;"><a style="color: black;">完全整理 | 365篇高质技术<span style="color: black;">文案</span>目录整理</a></strong></span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><a style="color: black;">算法之美 : 栈和队列</a></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><a style="color: black;">主宰这个世界的10大算法</a></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><a style="color: black;">彻底理解c</a>ookie、session、token</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><a style="color: black;">浅谈什么是递归算法</a></span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;"><span style="color: black;">专注服务器后台技术栈知识总结分享</span></strong></span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;"><span style="color: black;">欢迎关注交流<span style="color: black;">一起</span>进步</span></strong></span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;"></p>




zrd123 发表于 2024-8-27 14:39:51

对于这个问题,我有不同的看法...

流星的美 发表于 2024-9-1 07:50:15

期待与你深入交流,共探知识的无穷魅力。
页: [1]
查看完整版本: 52条SQL语句性能优化策略,意见保藏