搜索
首页数据库SQL记录 慢SQL优化实战

记录 慢SQL优化实战

Dec 25, 2020 pm 05:23 PM
mysqlsql

sql教程介绍sql慢查询的优化

记录 慢SQL优化实战

推荐(免费):sql教程

一、存在问题

经过sql慢查询的优化,我们系统中发现了以下几种类型的问题:

1.未建索引:整张表没有建索引;2.索引未命中:有索引,但是部分查询条件下索引未命中;3.搜索了额外的非必要字段,导致回表;4.排序,聚合导致慢查询;5.相同内容多次查询数据库;6.未消限制搜索范围或者限制的搜索范围在预期之外,导致全部扫描;

二、解决方案

1.优化索引,增加或者修改当前的索引;         

2.重写sql;3.利用redis缓存,减少查询次数;4.增加条件,避免非必要查询;5.增加条件,减少查询范围;

三、案例分析

(一)药材搜索接口

完整sql语句在附录,为方便阅读和脱敏,部分常用字段采用中文。

这儿主要讲一下我们拿到Sql语句后的整个分析过程,思考逻辑,然后进行调整的过程和最后解决的办法。

给大家提供一些借鉴,也希望大家能够提出更好的建议。

这个sql语句要求是根据医生搜索的拼音或者中文,进行模糊查询,找到药材,然后根据医生选择的药库,查找下面的供应商,然后根据供应商,进行药材匹配,排除掉供应商没有的药材,然后根据真名在前,别名在后,完全匹配在前,部分匹配在后,附加医生最近半年的使用习惯,把药材排序出来。最后把不同名称的同一味药聚合起来,以真名(另名)的形式展现。

1.分析sql

  • (1)14-8

第14排,id为8的explain结果分析:

①Explain
8,DERIVED,ssof,range,"ix_district,ix_供应商id",ix_district,8,NULL,18,Using where; Using index; Using temporary
②Sql
SELECT DISTINCT (ssof.供应商id) AS 供应商id FROM  药库供应商关系表 AS ssof  WHERE ssof.药库id IN (  1, 2, 8, 9, 10, 11, 12, 13, 14, 15, 17, 22, 24, 25, 26, 27, 31, 33)  AND ssof.药方剂型id IN (1)
③索引
PRIMARY KEY (`id`),    UNIQUE KEY `ix_district` (        `药库id`, `药方剂型id`, `供应商id`    ) USING BTREE,KEY `ix_供应商id` (`供应商id`) USING BTREE
④分析

使用了索引,建立了临时表,这个地方索引已经完全覆盖了,但是还有回表操作。

原因是用in,这个导致了回表。如果in可以被mysql 自动优化为等于,就不会回表。如果无法优化,就回表。

临时表是因为有distinct,所以无法避免。

同时使用in需要注意,如果里面的值数量比较多,有几万个。即使区分度高,就会导致索引失效,这种情况需要多次分批查询。

2. 12-7

  • (1)Explain
7,DERIVED,<derived8>,ALL,NULL,NULL,NULL,NULL,18,Using temporary; Using filesort
  • (2)Sql
INNER JOIN (上面14-8临时表) tp ON tp.供应商id= ms.供应商id
  • (3)索引

  • (4)分析

对临时表操作,无索引,用了文件排序。

这一部分是对临时表和药材表进行关联操作的一部分,有文件排序是因为需要对药材表id进行group by 导致的。

1、默认情况下,mysql在使用group by之后,会产生临时表,而后进行排序(此处排序默认是快排),这会消耗的性能。

2、group by本质是先分组后排序【而不是先排序后分组】。

3、group by column 默认会按照column分组, 然后根据column升序排列;  group by column order by null 则默认按照column分组,然后根据标的主键ID升序排列。

3. 13-7

  • (1)Explain
7,DERIVED,ms,ref,"ix_title,idx_audit,idx_mutiy",idx_mutiy,5,"tp.供应商id,const",172,NULL
  • (2)Sql
SELECT ms.药材表id, max(ms.audit) AS audit, max(ms.price) AS price, max(ms.market_price) AS market_price,max(ms.is_granule) AS is_granule,max(ms.is_decoct) AS is_decoct, max(ms.is_slice) AS is_slice,max(ms.is_cream) AS is_cream, max(ms.is_extract) AS is_extract,max(ms.is_cream_granule) AS is_cream_granule, max(ms.is_extract_granule) AS is_extract_granule,max(ms.is_drychip) AS is_drychip,            max(ms.is_pill) AS is_pill,max(ms.is_powder) AS is_powder, max(ms.is_bolus) AS is_bolus FROM 供应商药材表 AS ms INNER JOIN (                SELECT                    DISTINCT (ssof.供应商id) AS 供应商id                FROM                    药库供应商关系表 AS ssof WHERE  ssof.药库id IN (  1, 2, 8, 9, 10, 11, 12, 13, 14, 15, 17, 22, 24, 25, 26, 27, 31, 33 ) AND ssof.药方剂型id IN (1) ) tp ON tp.供应商id= ms.供应商id WHERE  ms.audit = 1  GROUP BY  ms.药材表id
  • (3)索引
   KEY `idx_mutiy` (`供应商id`, `audit`, `药材表id`)
  • (4)分析

命中了索引,表间连接使用了供应商id,建立索引的顺序是供应商id,where条件中audit,Group by 条件药材表id。

这部分暂时不需要更改。

4.10-6

  • (1)Explain
6,DERIVED,r,range,"PRIMARY,id,idx_timeline,idx_did_timeline,idx_did_isdel_statuspay_timecreate_payorderid,idx_did_statuspay_ischecked_isdel",idx_did_timeline,8,NULL,546,Using where; Using index; Using temporary; Using filesort
  • (2)Sql
SELECT 
       count(*) AS total, 
       rc.i AS m药材表id 
     FROM 
        处方药材表 AS rc 
        INNER JOIN 药方表AS r ON r.id = rc.药方表_id 
     WHERE 
         r.did = 40 
         AND r.timeline > 1576115196 
         AND rc.type_id in (1, 3) 
         GROUP BY 
    rc.i
  • (3)索引
KEY `idx_did_timeline` (`did`, `timeline`),
  • (4)分析

驱动表与被驱动表,小表驱动大表。

先了解在join连接时哪个表是驱动表,哪个表是被驱动表:

1.当使用left join时,左表是驱动表,右表是被驱动表;

2.当使用right join时,右表时驱动表,左表是驱动表;

3.当使用join时,mysql会选择数据量比较小的表作为驱动表,大表作为被驱动表;

4. in后面跟的是驱动表, exists前面的是驱动表;

5. 11-6

  • (1)Explain
6,DERIVED,rc,ref,"orderid_药材表,药方表_id",药方表_id,5,r.id,3,Using where
  • (2)Sql

同上

  • (3)索引
  KEY `idx_药方表_id` (`药方表_id`, `type_id`) USING BTREE,
  • (4)分析

索引的顺序没有问题,仍旧是in 导致了回表。

6.8-5

  • (1)Explain
5,UNION,malias,ALL,id_tid,NULL,NULL,NULL,4978,Using where
  • (2)Sql
 SELECT 
      mb.id, 
      mb.sort_id, 
      mb.title, 
      mb.py, 
      mb.unit, 
      mb.weight, 
      mb.tid, 
      mb.amount_max, 
      mb.poisonous, 
      mb.is_auxiliary, 
      mb.is_auxiliary_free, 
      mb.is_difficult_powder, 
      mb.brief, 
      mb.is_fixed_recipe, 
      ASE WHEN malias.py = 'GC' THEN malias.title ELSE CASE WHEN malias.title = 'GC' THEN malias.title ELSE '' END END AS atitle, 
      alias.py AS apy, 
      CASE WHEN malias.py = 'GC' THEN 2 ELSE CASE WHEN malias.title = 'GC' THEN 2 ELSE 1 END END AS ttid 
 FROM 
      药材表 AS mb 
      LEFT JOIN 药材表 AS malias ON malias.tid = mb.id 
WHERE 
      alias.title LIKE '%GC%' 
      OR malias.py LIKE '%GC%'
  • (3)索引
KEY `id_tid` (`tid`) USING BTREE,
  • (4)分析

因为like是左右like,无法建立索引,所以只能建tid。Type是all,遍历全表以找到匹配的行,左右表大小一样,估算的找到所需的记录所需要读取的行数有4978。这个因为是like的缘故,无法优化,这个语句并没有走索引,药材表 AS mb FORCE INDEX (id_tid) 改为强制索引,读取的行数减少了700行。

7.9-5

  • (1)Explain
5,UNION,mb,eq_ref,"PRIMARY,ix_id",PRIMARY,4,malias.tid,1,NULL
  • (2)Sql

同上

  • (3)索引
PRIMARY KEY (`id`) USING BTREE,
  • (4)分析

走了主键索引,行数也少,通过。

8.7-4

  • (1)Explain
4,DERIVED,mb,ALL,id_tid,NULL,NULL,NULL,4978,Using where
  • (2)Sql

    SELECT 
       mb.id, 
       mb.sort_id, 
       mb.title, 
       mb.py, 
       mb.unit, 
       mb.weight, 
       mb.tid, 
       mb.amount_max, 
       mb.poisonous, 
       mb.is_auxiliary, 
       mb.is_auxiliary_free, 
       mb.is_difficult_powder, 
       mb.brief, 
       mb.is_fixed_recipe, 
       '' AS atitle, 
       '' AS apy, 
       CASE WHEN mb.py = 'GC' THEN 3 ELSE CASE WHEN mb.title = 'GC' THEN 3 ELSE 1 END END AS ttid 
    FROM 
       药材表 AS mb 
      WHERE 
       mb.tid = 0 
       AND (
           mb.title LIKE '%GC%' 
           OR mb.py LIKE '%GC%'
                                )
  • (3)索引

KEY `id_tid` (`tid`) USING BTREE,
  • (4)分析

    tid int(11) NOT NULL DEFAULT ‘0’ COMMENT ‘真名药品的id’,

他也是like,这个没法优化。

9.6-3

  • (1)Explain
3,DERIVED,<derived4>,ALL,NULL,NULL,NULL,NULL,9154,Using filesort
  • (2)Sql

    UNION ALL

  • (3)索引

  • (4)分析

就是把真名搜索结果和别人搜索结果合并。避免用or连接,加快速度 形成一个munion的表,初步完成药材搜索,接下去就是排序。

这一个进行了2次查询,然后用union连接,可以考虑合并为一次查询。用case when进行区分,计算出权重。

这边是一个优化点。

10.4-2

  • (1)Explain
2,DERIVED,<derived3>,ALL,NULL,NULL,NULL,NULL,9154,NULL
  • (2)Sql

    SELECT 
       munion.id, 
       munion.sort_id, 
       case when length(
         trim(
              group_concat(munion.atitle SEPARATOR ' ')
                        )
                    )> 0 then concat(
                        munion.title, 
                        '(', 
                        trim(
                            group_concat(munion.atitle SEPARATOR ' ')
                        ), 
                        ')'
                    ) else munion.title end as title, 
          munion.py, 
          munion.unit, 
          munion.weight, 
          munion.tid, 
          munion.amount_max, 
          munion.poisonous, 
          munion.is_auxiliary, 
          munion.is_auxiliary_free, 
          munion.is_difficult_powder, 
          munion.brief, 
          munion.is_fixed_recipe, 
          --  trim( group_concat( munion.atitle SEPARATOR ' ' ) ) AS atitle,
                    ##  --  
           trim(
                 group_concat(munion.apy SEPARATOR ' ')
                 ) AS apy, 
             ##   
               max(ttid) * 100000 + id AS ttid 
         FROM 
                munion <derived4>
             GROUP BY 
                id -- 全部实名药材 结束##
  • (3)索引

  • (4)分析

这里全部在临时表中搜索了。

11.5-2

  • (1)Explain
2,DERIVED,<derived6>,ref,<auto_key0>,<auto_key0>,5,m.id,10,NULL
  • (2)Sql
Select fields from 全部实名药材表 as m  LEFT JOIN ( 个人使用药材统计表 ) p ON m.id = p.m药材表id
  • (3)索引

  • (4)分析

2张虚拟表left join

使用了优化器为派生表生成的索引

这边比较浪费性能,每次查询,都要对医生历史开方记录进行统计,并且统计还是几张大表计算后的结果。但是如果只是sql优化,这边暂时无法优化。

12.2-1

  • (1)Explain
1,PRIMARY,<derived7>,ALL,NULL,NULL,NULL,NULL,3096,Using where; Using temporary; Using filesort
  • (2)Sql

  • (3)索引

  • (4)分析

临时表操作

13.3-1

  • (1)Explain
1,PRIMARY,<derived2>,ref,<auto_key0>,<auto_key0>,4,msu.药材表id,29,NULL
  • (2)Sql

  • (3)索引

  • (4)分析

临时表操作

14.null

  • (1)Explain
NULL,UNION RESULT,"<union4,5>",ALL,NULL,NULL,NULL,NULL,NULL,Using temporary
  • (2)Sql

  • (3)索引

  • (4)分析

临时表

(二)优化sql

上面我们只做索引的优化,遵循的原则是:

1.最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。2.=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。3.尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条记录。4.索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’)。5.尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。

查询优化神器 - explain命令

关于explain命令相信大家并不陌生,具体用法和字段含义可以参考官网explain-output,这里需要强调rows是核心指标,绝大部分rows小的语句执行一定很快(有例外,下面会讲到)。所以优化语句基本上都是在优化rows。

化基本步骤:

0.先运行看看是否真的很慢,注意设置SQL_NO_CACHE1.where条件单表查,锁定最小返回记录表。这句话的意思是把查询语句的where都应用到表中返回的记录数最小的表开始查起,单表每个字段分别查询,看哪个字段的区分度最高;2.explain查看执行计划,是否与1预期一致(从锁定记录较少的表开始查询);3.order by limit 形式的sql语句让排序的表优先查;4.了解业务方使用场景;5.加索引时参照建索引的几大原则;6.观察结果,不符合预期继续从0分析;

上面已经详细的分析了每一个步骤,根据上面的sql,去除union操作, 增加索引。可以看出,优化后虽然有所改善。但是距离我们的希望还有很大距离,但是光做sql优化,感觉也没有多少改进空间,所以决定从其他方面解决。

(三)拆分sql

由于速度还是不领人满意,尤其是个人用药情况统计,其实没必要每次都全部统计一次,再要优化,只靠修改索引应该是不行的了,所以考虑使用缓存。

接下来是修改php代码,把全部sql语句拆分,然后再组装。

  • (1)搜索真名,别名(缓存)
SELECT  mb.id,  mb.sort_id,  mb.title,  mb.py,  mb.unit,  mb.weight,  mb.tid,  mb.amount_max,  mb.poisonous,  mb.is_auxiliary,  mb.is_auxiliary_free,  mb.is_difficult_powder,  mb.brief,  mb.is_fixed_recipe,  IFNULL(group_concat(malias.title),'') atitle,  IFNULL(group_concat(malias.py),'') apy  FROM  药材表 AS mb  LEFT JOIN 药材表 AS malias ON malias.tid = mb.id  WHERE  mb.tid = 0  AND (  malias.title LIKE '%GC%'  OR malias.py LIKE '%GC%'  or mb.title LIKE '%GC%'  OR mb.py LIKE '%GC%'  )  group by  mb.id

  • (2)如果命中有药材
①排序

真名在前,别名在后,完全匹配在前,部分匹配在后

//对搜索结果进行处理,增加权重
②对供应商药材搜索
SELECT ms.药材表id, max( ms.audit ) AS audit, max( ms.price ) AS price, max( ms.market_price ) AS market_price, max( ms.is_granule ) AS is_granule, max( ms.is_decoct ) AS is_decoct, max( ms.is_slice ) AS is_slice, max( ms.is_cream ) AS is_cream, max( ms.is_extract ) AS is_extract, max( ms.is_cream_granule) AS is_cream_granule, max( ms.is_extract_granule) AS is_extract_granule, max( ms.is_drychip ) AS is_drychip, max( ms.is_pill ) AS is_pill, max( ms.is_powder ) AS is_powder, max( ms.is_bolus ) AS is_bolus  FROM 供应商药材表 AS ms WHERE ms.audit = 1 AND ms.供应商idin (  SELECT DISTINCT  ( ssof.供应商id) AS 供应商id FROM  药库供应商关系表 AS ssof  WHERE  ssof.药库id IN ( 1,2,8,9,10,11,12,13,14,15,17,22,24,25,26,27,31,33 )  AND ssof.药方剂型id IN (1) ) AND ms.药材表id IN ( 78,205,206,207,208,209,334,356,397,416,584,652,988,3001,3200,3248,3521,3522,3599,3610,3624,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,4405,4406,4407,4408,5704,5705,5706,5739,5740,5741,5742,5743,6265,6266,6267,6268,6514,6515,6516,6517,6518,6742,6743 ) AND ms.is_slice = 1  GROUP BY ms.药材表id

③拿医生历史开方药材用量数据(缓存)
SELECT  count( * ) AS total,  rc.i AS 药材表id FROM  处方药材表 AS rc  INNER JOIN 药方表AS r ON r.id = rc.药方表_id WHERE  r.did = 40  AND r.timeline > 1576116927  AND rc.type_id in (1,3) GROUP BY  rc.i

④  装配及排序微调

  • (3)小结

运行速度,对于开方量不是特别多的医生来说,两者速度都是0.1秒左右.但是如果碰到开方量大的医生,优化后的sql速度比较稳定,能始终维持在0.1秒左右,优化前的sql速度会超过0.2秒.速度提升约一倍以上。

最后对搜索结果和未优化前的搜索结果进行比对,结果数量和顺序完全一致.本次优化结束。

四、附录:

SELECT sql_no_cache 
    *FROM
    (
        -- mbu start##        SELECT
            m.*,
            ifnull(p.total, 0) AS total        FROM
            (
                --全部实名药材
开始
##SELECT
       munion.id,
       munion.sort_id,
       case when length(
        trim(
              group_concat(munion.atitle SEPARATOR ' ')
                 )
             )> 0 then concat(
           munion.title,
          '(',
      trim(
             group_concat(munion.atitle SEPARATOR ' ')
              ),
                ')'
             ) else munion.title end as title,
        munion.py,
        munion.unit,
        munion.weight,
        munion.tid,
        munion.amount_max,
        munion.poisonous,
        munion.is_auxiliary,
        munion.is_auxiliary_free,
        munion.is_difficult_powder,
        munion.brief,
        munion.is_fixed_recipe,
        --  trim( group_concat( munion.atitle SEPARATOR ' ' ) ) AS atitle,##        --  trim( group_concat( munion.apy SEPARATOR  ' ' ) ) AS apy,##              max(ttid) * 100000 + id AS ttid           FROM
              (
                -- #union start
联合查找,得到全部药材
##  (
       SELECT
              mb.id,
              mb.sort_id,
              mb.title,
              mb.py,
              mb.unit,
              mb.weight,
              mb.tid,
              mb.amount_max,
              mb.poisonous,
              mb.is_auxiliary,
              mb.is_auxiliary_free,
              mb.is_difficult_powder,
              mb.brief,
              mb.is_fixed_recipe,
              '' AS atitle,
              '' AS apy,
              CASE WHEN mb.py = 'GC' THEN 3 ELSE CASE WHEN mb.title = 'GC' THEN 3 ELSE 1 END END AS ttid               FROM
                 药材表 AS mb                     WHERE
                         mb.tid = 0
                       AND (
                              mb.title LIKE '%GC%'
                              OR mb.py LIKE '%GC%'
                                )
                        ) --真名药材

结束
## UNION ALL
    (
      SELECT
            mb.id,
            mb.sort_id,
            mb.title,
            mb.py,
            mb.unit,
            mb.weight,
            mb.tid,
            mb.amount_max,
            mb.poisonous,
            mb.is_auxiliary,
            mb.is_auxiliary_free,
            mb.is_difficult_powder,
            mb.brief,
            mb.is_fixed_recipe,
            CASE WHEN malias.py = 'GC' THEN malias.title ELSE CASE WHEN malias.title = 'GC' THEN malias.title ELSE '' END END AS atitle,
            malias.py AS apy,
            CASE WHEN malias.py = 'GC' THEN 2 ELSE CASE WHEN malias.title = 'GC' THEN 2 ELSE 1 END END AS ttid          FROM
                药材表 AS mb                LEFT JOIN 药材表 AS malias ON malias.tid = mb.id          WHERE
                malias.title LIKE '%GC%'
                OR malias.py LIKE '%GC%'
                      ) --其他药材结束
##                 -- #union end##                ) munion                GROUP BY
                    id --全部实名药材

结束
##                    ) m            LEFT JOIN (
                --个人使用药材统计

开始
##    SELECT
          count(*) AS total,
          rc.i AS m药材表id     FROM
           处方药材表 AS rc           INNER JOIN 药方表AS r ON r.id = rc.药方表_id      WHERE
           r.did = 40
            AND r.timeline > 1576115196
            AND rc.type_id in (1, 3)
       GROUP BY
              rc.i --个人使用药材统计

结束
##           ) p ON m.id = p.m药材表id -- mbu end ##            ) mbu    INNER JOIN (
        -- msu start
供应商药材筛选
##        SELECT
            ms.药材表id,
            max(ms.audit) AS audit,
            max(ms.price) AS price,
            max(ms.market_price) AS market_price,
            max(ms.is_granule) AS is_granule,
            max(ms.is_decoct) AS is_decoct,
            max(ms.is_slice) AS is_slice,
            max(ms.is_cream) AS is_cream,
            max(ms.is_extract) AS is_extract,
            max(ms.is_cream_granule) AS is_cream_granule,
            max(ms.is_extract_granule) AS is_extract_granule,
            max(ms.is_drychip) AS is_drychip,
            max(ms.is_pill) AS is_pill,
            max(ms.is_powder) AS is_powder,
            max(ms.is_bolus) AS is_bolus        FROM
            供应商药材表 AS ms            INNER JOIN (
                SELECT
                    DISTINCT (ssof.供应商id) AS 供应商id                FROM
                    药库供应商关系表 AS ssof                WHERE
                    ssof.药库id IN (
                        1, 2, 8, 9, 10, 11, 12, 13, 14, 15, 17, 22,
                        24, 25, 26, 27, 31, 33
                    )
                    AND ssof.药方剂型id IN (1)
            ) tp ON tp.供应商id= ms.供应商id        WHERE
            ms.audit = 1
        GROUP BY
            ms.药材表id -- msu end ##            ) msu ON mbu.id = msu.药材表idWHERE
    msu.药材表id > 0
    AND msu.is_slice = 1order by
    total desc,
    ttid desc

相关免费学习推荐:mysql视频教程

以上是记录 慢SQL优化实战的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:learnku。如有侵权,请联系admin@php.cn删除
SQL和MySQL:了解核心差异SQL和MySQL:了解核心差异Apr 17, 2025 am 12:03 AM

SQL是一种用于管理关系数据库的标准语言,而MySQL是一个具体的数据库管理系统。SQL提供统一语法,适用于多种数据库;MySQL轻量、开源,性能稳定但在大数据处理上有瓶颈。

SQL:初学者的学习曲线SQL:初学者的学习曲线Apr 16, 2025 am 12:11 AM

SQL学习曲线陡峭,但通过实践和理解核心概念可掌握。1.基础操作包括SELECT、INSERT、UPDATE、DELETE。2.查询执行分为解析、优化、执行三步。3.基本用法如查询雇员信息,高级用法如使用JOIN连接表。4.常见错误包括未使用别名和SQL注入,需使用参数化查询防范。5.性能优化通过选择必要列和保持代码可读性实现。

SQL:命令,mysql:引擎SQL:命令,mysql:引擎Apr 15, 2025 am 12:04 AM

SQL命令在MySQL中分为DQL、DDL、DML、DCL和TCL五类,用于定义、操作和控制数据库数据。MySQL通过词法分析、语法分析、优化和执行等阶段处理SQL命令,并利用索引和查询优化器提升性能。使用示例包括SELECT用于数据查询,JOIN用于多表操作。常见错误有语法、逻辑和性能问题,优化策略包括使用索引、优化查询和选择合适的存储引擎。

用于数据分析的SQL:商业智能的高级技术用于数据分析的SQL:商业智能的高级技术Apr 14, 2025 am 12:02 AM

SQL的高级查询技巧包括子查询、窗口函数、CTE和复杂JOIN,能够处理复杂数据分析需求。1)子查询用于找出每个部门工资最高的员工。2)窗口函数和CTE用于分析员工的薪资增长趋势。3)性能优化策略包括索引优化、查询重写和使用分区表。

MySQL:SQL的特定实现MySQL:SQL的特定实现Apr 13, 2025 am 12:02 AM

MySQL是开源的关系型数据库管理系统,提供了标准SQL功能和扩展。1)MySQL支持标准SQL操作如CREATE、INSERT、UPDATE、DELETE,并扩展了LIMIT子句。2)它使用InnoDB和MyISAM等存储引擎,适用于不同场景。3)用户可以通过创建表、插入数据和使用存储过程等高级功能高效使用MySQL。

SQL:使所有人都可以访问数据管理SQL:使所有人都可以访问数据管理Apr 12, 2025 am 12:14 AM

sqlmakesdatamanagectAccessibletoAllbyProvidingAsimpleyetpoperfultoolSetSetForQuerquereingAndManagingDatabases.1)ItworkswithrelationalDatabases,允许inserstospecefifywhattheywanttododowithththedata.2)

SQL索引策略:通过数量级提高查询性能SQL索引策略:通过数量级提高查询性能Apr 11, 2025 am 12:04 AM

SQL索引可以通过巧妙的设计显着提升查询性能。 1.选择合适的索引类型,如B-tree、哈希或全文索引。 2.使用复合索引优化多字段查询。 3.避免过度索引以减少数据维护开销。 4.定期维护索引,包括重建和移除不必要的索引。

sql怎么删除约束sql怎么删除约束Apr 10, 2025 pm 12:21 PM

在 SQL 中删除约束,请执行以下步骤:识别要删除的约束名称;使用 ALTER TABLE 语句:ALTER TABLE 表名 DROP CONSTRAINT 约束名;确认删除。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中