openGauss学习笔记-243 openGauss性能调优-SQL调优-典型SQL调优点-子查询调优

文章目录

    • openGauss学习笔记-243 openGauss性能调优-SQL调优-典型SQL调优点-子查询调优
      • 243.1 子查询调优
        • 243.1.1 子查询背景介绍
        • 243.1.2 openGauss对SubLink的优化
        • 243.1.3 更多优化示例

openGauss学习笔记-243 openGauss性能调优-SQL调优-典型SQL调优点-子查询调优

SQL调优是一个不断分析与尝试的过程:试跑Query,判断性能是否满足要求;如果不满足要求,则通过查看执行计划分析原因并进行针对性优化;然后重新试跑和优化,直到满足性能目标。

243.1 子查询调优

243.1.1 子查询背景介绍

应用程序通过SQL语句来操作数据库时会使用大量的子查询,这种写法比直接对两个表做连接操作在结构上和思路上更清晰,尤其是在一些比较复杂的查询语句中,子查询有更完整、更独立的语义,会使SQL对业务逻辑的表达更清晰更容易理解,因此得到了广泛的应用。

openGauss根据子查询在SQL语句中的位置把子查询分成了子查询、子链接两种形式。

  • 子查询SubQuery:对应于查询解析树中的范围表RangeTblEntry,更通俗一些指的是出现在FROM语句后面的独立的SELECT语句。

  • 子链接SubLink:对应于查询解析树中的表达式,更通俗一些指的是出现在where/on子句、targetlist里面的语句。

    综上,对于查询解析树而言,SubQuery的本质是范围表,而SubLink的本质是表达式。针对SubLink场景而言,由于SubLink可以出现在约束条件、表达式中,按照openGauss对SubLink的实现,SubLink可以分为以下几类:

    • exist_sublink:对应EXIST、NOT EXIST语句
    • any_sublink:对应op ALL(select…)语句,其中OP可以是IN、<、>、=操作符
    • all_sublink:对应op ALL(select…)语句,其中OP可以是IN、<、>、=操作符
    • rowcompare_sublink:对应record op (select …)语句
    • expr_sublink:对应(SELECT with single targetlist item …)语句
    • array_sublink:对应ARRAY(select…)语句
    • cte_sublink:对应with query(…)语句

    其中OLAP、HTAP场景中常用的sublink为exist_sublink、any_sublink,在openGauss的优化引擎中对其应用场景做了优化(子链接提升),由于SQL语句中子查询的使用的灵活性,会带来SQL子查询过于复杂造成性能问题。子查询从大类上来看,分为非相关子查询和相关子查询:

    • 非相关子查询None-Correlated SubQuery

      子查询的执行不依赖于外层父查询的任何属性值。这样子查询具有独立性,可独自求解,形成一个子查询计划先于外层的查询求解。

      例如:

      select t1.c1,t1.c2
      from t1
      where t1.c1 in (
          select c2
          from t2
          where t2.c2 IN (2,3,4)
      );
                                    QUERY PLAN
      ----------------------------------------------------------------
       Hash Join 
         Hash Cond: (t1.c1 = t2.c2)
         ->  Seq Scan on t1 
               Filter: (c1 = ANY ('{2,3,4}'::integer[]))
         ->  Hash 
               ->  HashAggregate 
                     Group By Key: t2.c2
                     ->  Seq Scan on t2  
                           Filter: (c2 = ANY ('{2,3,4}'::integer[]))
      (9 rows)
      
    • 相关子查询Correlated-SubQuery

      子查询的执行依赖于外层父查询的一些属性值(如下列示例t2.c1 = t1.c1条件中的t1.c1)作为内层查询的一个AND-ed条件。这样的子查询不具备独立性,需要和外层查询按分组进行求解。

      例如:

      select t1.c1,t1.c2
      from t1
      where t1.c1 in (
          select c2
          from t2
          where t2.c1 = t1.c1 AND t2.c2 in (2,3,4)
      );
                                     QUERY PLAN
      ------------------------------------------------------------------------
       Seq Scan on t1
         Filter: (SubPlan 1)
         SubPlan 1
           ->  Seq Scan on t2
                 Filter: ((c1 = t1.c1) AND (c2 = ANY ('{2,3,4}'::integer[])))
      (5 rows)
      
243.1.2 openGauss对SubLink的优化

针对SubLink的优化策略主要是让内层的子查询提升(pullup),能够和外表直接做关联查询,从而避免生成SubPlan+Broadcast內表的执行计划。判断子查询是否存在性能风险,可以通过explain查询语句查看Sublink的部分是否被转换成SubPlan的执行计划。

例如:

img

箭头右侧执行计划应替换成下面的执行计划:

QUERY PLAN
--------------------------------
Seq Scan on t1
Filter: (SubPlan 1)
SubPlan 1
->  Seq Scan on t2
Filter: (c1 = t1.c1)
(5 rows)
  • 目前openGauss支持的Sublink-Release场景

    • IN-Sublink无相关条件

      • 不能包含上一层查询的表中的列(可以包含更高层查询表中的列)。
      • 不能包含易变函数。

      img

      箭头右侧执行计划应替换成下面的执行计划:

      QUERY PLAN
      --------------------------------------
      Hash Join
      Hash Cond: (t1.c1 = t2.c2)
      ->  Seq Scan on t1
      ->  Hash
      ->  HashAggregate
      Group By Key: t2.c2
      ->  Seq Scan on t2
      Filter: (c1 = 1)
      (8 rows)
      
    • Exist-Sublink包含相关条件

      Where子句中必须包含上一层查询的表中的列,子查询的其它部分不能含有上层查询的表中的列。其它限制如下。

      • 子查询必须有from子句。
      • 子查询不能含有with子句。
      • 子查询不能含有聚集函数。
      • 子查询里不能包含集合操作、排序、limit、windowagg、having操作。
      • 不能包含易变函数。

      img

      箭头右侧执行计划应替换成下面的执行计划:

      QUERY PLAN


      Hash Join

      Hash Cond: (t1.c1 = t2.c1)

      -> Seq Scan on t1

      -> Hash

      -> HashAggregate

      Group By Key: t2.c1

      -> Seq Scan on t2

      (7 rows)

    • 包含聚集函数的等值相关子查询的提升

      子查询的where条件中必须含有来自上一层的列,而且此列必须和子查询本层涉及表中的列做相等判断,且这些条件必须用and连接。其它地方不能包含上层的列。其它限制条件如下。

      • 子查询中where条件包含的表达式(列名)必须是表中的列。

      • 子查询的Select关键字后,必须有且仅有一个输出列,此输出列必须是聚集函数(如max),并且聚集函数的参数(t2.c2)不能是来自外层表(t1)中的列。聚集函数不能是count。

        例如,下列示例可以提升。

        select * from t1 where c1 >(
               select max(t2.c1) from t2 where t2.c1=t1.c1
        );
        

        下列示例不能提升,因为子查询没有聚集函数。

        select * from t1 where c1 >(
               select  t2.c1 from t2 where t2.c1=t1.c1
        );
        

        下列示例不能提升,因为子查询有两个输出列。

        select * from t1 where (c1,c2) >(
               select  max(t2.c1),min(t2.c2) from t2 where t2.c1=t1.c1
        );
        
      • 子查询必须是from子句。

      • 子查询中不能有groupby、having、集合操作。

      • 子查询只能是inner join。

        例如:下列示例不能提升。

        select * from t1 where c1 >(
               select max(t2.c1) from t2 full join t3 on (t2.c2=t3.c2) where t2.c1=t1.c1
        );
        
      • 子查询的targetlist中不能包含返回set的函数。

      • 子查询的where条件中必须含有来自上一层的列,而且此列必须和子查询层涉及表中的列做相等判断,且这些条件必须用and连接。其它地方不能包含上层的上层中的列。例如:下列示例中的最内层子链接可以提升。

        select * from t3 where t3.c1=(
                select t1.c1
                from t1 where c1 >(
                        select max(t2.c1) from t2 where t2.c1=t1.c1 
        ));
        

        基于上面的示例,再加一个条件,则不能提升,因为最内侧子查询引用了上层中的列。示例如下:

        select * from t3 where t3.c1=(
                select t1.c1
                from t1 where c1 >(
                       select max(t2.c1) from t2 where t2.c1=t1.c1 and t3.c1>t2.c2
        
        ));
        
    • 提升OR子句中的SubLink

      当WHERE过滤条件中有OR连接的EXIST相关SubLink,

      例如:

      select a, c from t1
      where t1.a = (select avg(a) from t3 where t1.b = t3.b) or
      exists (select * from t4 where t1.c = t4.c);
      

      将OR-ed连接的EXIST相关子查询OR字句的提升过程:

      1. 提取where条件中,or子句中的opExpr。为:t1.a = (select avg(a) from t3 where t1.b = t3.b)

      2. 这个op操作中包含subquery,判断是否可以提升,如果可以提升,重写subquery为:select avg(a)、 t3.b from t3 group by t3.b,生成not null条件t3.b is not null,并将这个opexpr用这个not null条件替换。此时SQL变为:

        select a, c
        from t1 left join (select avg(a) avg, t3.b from t3 group by t3.b)  as t3 on (t1.a = avg and t1.b = t3.b)
        where t3.b is not null or exists (select * from t4 where t1.c = t4.c);
        
      3. 再次提取or子句中的exists sublink、exists (select * from t4 where t1.c = t4.c),判断是否可以提升,如果可以提升,转换subquery为:select t4.c from t4 group by t4.c生成NotNull条件t4.c is not null提升查询,SQL变为:

        select a, c
        from t1 left join (select avg(a) avg, t3.b from t3 group by t3.b)  as t3 on (t1.a = avg and t1.b = t3.b)
        left join (select t4.c from t4 group by t4.c) where t3.b is not null or t4.c is not null;
        
  • 目前openGauss不支持的Sublink-Release场景

    除了以上场景之外都不支持Sublink提升,因此关联子查询会被计划成SubPlan+Broadcast的执行计划,当inner表的数据量较大时则会产生性能风险。

    如果相关子查询中跟外层的两张表做join,那么无法提升该子查询,需要通过将父SQL创建成with子句,然后再跟子查询中的表做相关子查询查询。

    例如:

    select distinct t1.a, t2.a
    from t1 left join t2 on t1.a=t2.a and not exists (select a,b from test1 where test1.a=t1.a and test1.b=t2.a);
    

    改写为

    with temp as
    (
            select * from (select t1.a as a, t2.a as b from t1 left join t2 on t1.a=t2.a)
    
    )
    select distinct a,b
    from temp
    where not exists (select a,b from test1 where temp.a=test1.a and temp.b=test1.b);
    
    • 出现在targetlist里的相关子查询无法提升(不含count)

      例如:

      explain (costs off)
      select (select c2 from t2 where t1.c1 = t2.c1) ssq, t1.c2
      from t1
      where t1.c2 > 10;
      

      执行计划为:

      explain (costs off)
      select (select c2 from t2 where t1.c1 = t2.c1) ssq, t1.c2
      from t1
      where t1.c2 > 10;
                 QUERY PLAN
      --------------------------------
       Seq Scan on t1
         Filter: (c2 > 10)
         SubPlan 1
           ->  Seq Scan on t2
                 Filter: (t1.c1 = c1)
      (5 rows)
      

      由于相关子查询出现在targetlist(查询返回列表)里,对于t1.c1=t2.c1不匹配的场景仍然需要输出值,因此使用left-outerjoin关联T1&T2确保t1.c1=t2.c1在不匹配时,子SSQ能够返回不匹配的补空值。

      img 说明:

      SSQ和CSSQ的解释如下:

      • SSQ:ScalarSubQuery一般指返回1行1列scalar值的sublink,简称SSQ。
      • CSSQ:Correlated-ScalarSubQuery和SSQ相同不过是指包含相关条件的SSQ。

      上述SQL语句可以改写为:

      with ssq as
      (
          select t2.c2 from t2
      )
      select ssq.c2, t1.c2
      from t1 left join ssq on t1.c1 = ssq.c2
      where t1.c2 > 10;
      

      改写后的执行计划为:

                 QUERY PLAN
      ---------------------------------
       Hash Right Join
         Hash Cond: (ssq.c2 = t1.c1)
         CTE ssq
           ->  Seq Scan on t2
         ->  CTE Scan on ssq
         ->  Hash
               ->  Seq Scan on t1
                     Filter: (c2 > 10)
      (8 rows)
      

      可以看到出现在SSQ返回列表里的相关子查询SSQ,已经被提升成Right Join,从而避免当內表T2较大时出现SubPlan计划导致性能变差。

    • 出现在targetlist里的相关子查询无法提升(带count)

      例如:

      select (select count(*) from t2 where t2.c1=t1.c1) cnt, t1.c1, t3.c1
      from t1,t3
      where t1.c1=t3.c1 order by cnt, t1.c1;
      

      执行计划为

                       QUERY PLAN
      --------------------------------------------
       Sort
         Sort Key: ((SubPlan 1)), t1.c1
         ->  Hash Join
               Hash Cond: (t1.c1 = t3.c1)
               ->  Seq Scan on t1
               ->  Hash
                     ->  Seq Scan on t3
               SubPlan 1
                 ->  Aggregate
                       ->  Seq Scan on t2
                             Filter: (c1 = t1.c1)
      (11 rows)
      

      由于相关子查询出现在targetlist(查询返回列表)里,对于t1.c1=t2.c1不匹配的场景仍然需要输出值,因此使用left-outerjoin关联T1&T2确保t1.c1=t2.c1在不匹配时子SSQ能够返回不匹配的补空值,但是这里带了count语句及时在t1.c1=t2.t1不匹配时需要输出0,因此可以使用一个case-when NULL then 0 else count(*)来代替。

      上述SQL语句可以改写为:

      with ssq as
      (
          select count(*) cnt, c1 from t2 group by c1
      )
      select case when
                  ssq.cnt is null then 0
                  else ssq.cnt
             end cnt, t1.c1, t3.c1
      from t1 left join ssq on ssq.c1 = t1.c1,t3
      where t1.c1 = t3.c1
      order by ssq.cnt, t1.c1;
      

      改写后的执行计划为

                      QUERY PLAN
      -------------------------------------------
       Sort
         Sort Key: ssq.cnt, t1.c1
         CTE ssq
           ->  HashAggregate
                 Group By Key: t2.c1
                 ->  Seq Scan on t2
         ->  Hash Join
               Hash Cond: (t1.c1 = t3.c1)
               ->  Hash Left Join
                     Hash Cond: (t1.c1 = ssq.c1)
                     ->  Seq Scan on t1
                     ->  Hash
                           ->  CTE Scan on ssq
               ->  Hash
                     ->  Seq Scan on t3
      (15 rows)
      
    • 相关条件为不等值场景

      例如:

      select t1.c1, t1.c2
      from t1
      where t1.c1 = (select agg() from t2.c2 > t1.c2);
      

      对于非等值相关条件的SubLink目前无法提升,从语义上可以通过做2次join(一次CorrelationKey,一次rownum自关联)达到提升改写的目的。

      改写方案有两种。

      • 子查询改写方式

        select t1.c1, t1.c2
        from t1, (
            select t1.rowid, agg() aggref
            from t1,t2
            where t1.c2 > t2.c2 group by t1.rowid
        ) dt /* derived table */
        where t1.rowid = dt.rowid AND t1.c1 = dt.aggref;
        
      • CTE改写方式

        WITH dt as
        (
            select t1.rowid, agg() aggref
            from t1,t2
            where t1.c2 > t2.c2 group by t1.rowid
        )
        select t1.c1, t1.c2
        from t1, derived_table
        where t1.rowid = derived_table.rowid AND
        t1.c1 = derived_table.aggref;
        

    img 须知:

    • 对于AGG类型为count()时需要进行CASE-WHEN对没有match的场景补0处理,非COUNT()场景NULL处理。
    • CTE改写方式如果有sharescan支持性能上能够更优。
243.1.3 更多优化示例

**示例:**修改select语句,将子查询修改为和主表的join,或者修改为可以提升的subquery,但是在修改前后需要保证语义的正确性。

explain (costs off) select * from t1 where t1.c1 in (select t2.c1 from t2 where t1.c1 = t2.c2);
           QUERY PLAN
--------------------------------
 Seq Scan on t1
   Filter: (SubPlan 1)
   SubPlan 1
     ->  Seq Scan on t2
           Filter: (t1.c1 = c2)
(5 rows)

上面事例计划中存在一个subPlan,为了消除这个subPlan可以修改语句为:

explain (costs off) select * from t1 where exists (select t2.c1 from t2 where t1.c1 = t2.c2 and t1.c1 = t2.c1);
                QUERY PLAN
------------------------------------------
 Hash Join
   Hash Cond: (t1.c1 = t2.c2)
   ->  Seq Scan on t1
   ->  Hash
         ->  HashAggregate
               Group By Key: t2.c2, t2.c1
               ->  Seq Scan on t2
                     Filter: (c2 = c1)
(8 rows)

从计划可以看出,subPlan消除了,计划变成了两个表的hash join,这样会大大提高执行效率。

👍 点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向!

✏️ 评论,你的意见是我进步的财富!

图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/460427.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Scala--01--简介、环境搭建

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1. Scala简介1.1 Scala是什么&#xff1f;官网&#xff1a; [https://scala-lang.org/](https://scala-lang.org/)官方文档&#xff1a; [https://docs.scala-lang.…

WPF布局、控件与样式

视频来源&#xff1a;https://www.bilibili.com/video/BV1HC4y1b76v/ 布局 常用布局属性 HorizontalAlignment&#xff1a;用于设置元素的水平位置VerticalAlignment&#xff1a;用于设置元素的垂直位置Margin&#xff1a;指定元素与容器的边距Height&#xff1a;指定元素的…

音频提取:分享几个常用方法,简单好用

有时候我们会在视频中发现一首非常好听的歌曲&#xff0c;但是我们并不需要视频本身。 这时&#xff0c;我们可以提取视频中的音频&#xff0c;将其转化为音频文件&#xff0c;然后在任何时间、任何地点进行欣赏。 下面给大家分享几个提取视频中音频的几个方法&#xff0c;供…

[嵌入式AI从0开始到入土]16_ffmpeg_ascend编译安装及性能测试

[嵌入式AI从0开始到入土]嵌入式AI系列教程 注&#xff1a;等我摸完鱼再把链接补上 可以关注我的B站号工具人呵呵的个人空间&#xff0c;后期会考虑出视频教程&#xff0c;务必催更&#xff0c;以防我变身鸽王。 第1期 昇腾Altas 200 DK上手 第2期 下载昇腾案例并运行 第3期 官…

css 各种方位计算 - client系列 offset系列 scroll系列 x/y 系列

offset系列 HTMLElement.offsetTop - Web API 接口参考 | MDN 一文读懂offsetHeight/offsetLeft/offsetTop/offsetWidth/offsetParent_heightoffset-CSDN博客 client系列 搞清clientHeight、offsetHeight、scrollHeight、offsetTop、scrollTop-CSDN博客 scroll系列 秒懂scr…

RabbitMQ:1.概述及安装

概述 AMQP协议 MQ Message Queue&#xff08;消息队列&#xff09;是在消息的传输过程中保存消息的容器&#xff0c;多用于系统之间的异步通信 AMQP Advanced Message Queuing Protocol(高级消息队列协议)是一个网络协议&#xff0c;2006年AMQP规范发布【类比HTTP】 专门为消…

ubuntu安装zsh及环境配置

ubuntu安装zsh及环境配置 MacBook 安装 zsh 个人很喜欢使用zsh,它的终端显示很清晰,命令都很友好,使用git时,直接可以看到当前分支和修改状态 zsh安装 1.查看当前系统装了哪些shellcat /etc/shells 2.当前正在运行的是哪个版本的shellecho $SHELL 3.安装zshsudo apt-get -y …

【项目笔记】java微服务:黑马头条(day03)

文章目录 自媒体文章发布1)自媒体前后端搭建1.1)后台搭建1.2)前台搭建 2)自媒体素材管理2.1)素材上传2.2.1)需求分析2.2.2)素材管理-图片上传-表结构2.2.3)实现思路2.2.4)接口定义2.2.5)自媒体微服务集成heima-file-starter2.2.6)具体实现 2.2)素材列表查询2.2.1)接口定义2.2.2…

【Algorithm】动态规划和递归问题:动态规划和递归有什么区别?如何比较递归解决方案和它的迭代版本?

【Algorithm】动态规划和递归问题:动态规划和递归有什么区别?如何比较递归解决方案和它的迭代版本? 1. 动态规划(Dynamic Programming,DP)和递归定义及优缺点1.1 递归 (Recursion)定义及优缺点1.2 动态规划 (Dynamic Programming)定义及优缺点2. 动态规划(DP)和递归的特…

platform设备注册驱动模块的测试

一. 简介 上一篇文章编写了 platform设备注册代码&#xff0c;文章地址如下&#xff1a; 无设备树platform驱动实验&#xff1a;platform设备注册代码实现-CSDN博客 本文继续无设备树platform驱动实验&#xff0c;本文对编译好的 设备注册程序进行测试&#xff0c;测试所实…

Linux远程连接本地数据库(docker)

1. 安装docker 参考上一篇文章 CentOS安装Docker 2. Linux中安装Mysql 2.1 docker拉取mysql镜像 拉取镜像 docker pull mysql查看镜像列表 docker images2.2 运行mysql容器 运行一个名字为mysql的mysql容器&#xff0c;其连接端口号为3306&#xff0c;密码为123456 docker r…

运行gazebo机器人模型没有cmd_vel话题

运行赵虚左教程代码出现上诉问题 roslaunch urdf02_gazebo demo03_env.launch 原因&#xff1a;缺少某个包 在工作空间catkin_make编译发现报错 解决&#xff1a; sudo apt-get install ros-noetic-gazebo-ros-pkgs ros-noetic-gazebo-ros-control 下载后再次运行launch文件…

unity学习(59)——选择角色界面--MapHandler1

map内容需要结合客户端和服务器两部分的流程&#xff1a; 1.客户端第一次发出的command的4&#xff0c;选择请求&#xff1a; 2.服务器做出相应&#xff1a; select的内容&#xff0c;最后就是返回当前玩家的playerModel结构体。 3.去客户端里找type 2&#xff08;user2&#…

服务器数据恢复—服务器硬盘灯显示红色的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 一台服务器中有一组由多块硬盘组建的raid阵列&#xff0c;在运行过程中服务器突然崩溃&#xff0c;管理员检查服务器发现该服务器raid阵列中有两块硬盘的指示灯显示红色。于是&#xff0c;管理员重启服务器&#xff0c;服务器重启后&a…

maven私服搭建详细教程

1、为什么需要私服 如果在公司中多个项目模块中的的公共类用的都是一样的&#xff0c;那么不可能将这些一样的代码写两遍。所以将其中一个项目中的代码打包成私服&#xff0c;然后在另外一个模块中去进行引用。 除此之外&#xff0c;如果大公司中开发人员较多&#xff0c;大家同…

Dev C++和Visual Studio Code哪个好?

Dev C和Visual Studio Code哪个好&#xff1f; Dev C和Visual Studio Code都是常用的集成开发环境&#xff08;IDE&#xff09;&#xff0c;用于编写和调试代码。它们各自有不同的优点和适用场景。 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C的资…

对模型性能进行评估(Machine Learning 研习十五)

在上一篇我们已然训练了一个用于对数字图像识别的模型&#xff0c;但我们目前还不知道该模型在识别数字图像效率如何&#xff1f;所以&#xff0c;本文将对该模型进行评估。 使用交叉验证衡量准确性 评估模型的一个好方法是使用交叉验证&#xff0c;让我们使用cross_val_score…

Linux从0到1——Linux第一个小程序:进度条

Linux从0到1——Linux第一个小程序&#xff1a;进度条 1. 输出缓冲区2. 回车和换行的本质3. 实现进度条3.1 简单原理版本3.2 实际工程版本 1. 输出缓冲区 1. 小实验&#xff1a; 编写一个test.c文件&#xff0c;&#xff1a; #include <stdio.h> #include <unistd.h…

js【详解】ajax (含XMLHttpRequest、 同源策略、跨域、JSONP)

ajax 的核心API – XMLHttpRequest get 请求 // 新建 XMLHttpRequest 对象的实例 const xhr new XMLHttpRequest(); // 发起 get 请求&#xff0c;open 的三个参数为&#xff1a;请求类型&#xff0c;请求地址&#xff0c;是否异步请求&#xff08; true 为异步&#xff0c;f…

数据结构(二)顺序表和链表

1.线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使 用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续的一条直…