我的编程空间,编程开发者的网络收藏夹
学习永远不晚

PostgreSQL源码中NOT IN的作用是什么

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

PostgreSQL源码中NOT IN的作用是什么

本篇内容主要讲解“PostgreSQL源码中NOT IN的作用是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL源码中NOT IN的作用是什么”吧!

一、数据结构

SubPlanState
子计划运行期状态


typedef struct SubPlanState
{
    NodeTag        type;
    SubPlan    *subplan;        
    struct PlanState *planstate;    
    struct PlanState *parent;    
    ExprState  *testexpr;        
    List       *args;            
    HeapTuple    curTuple;        
    Datum        curArray;        
    
    TupleDesc    descRight;        
    ProjectionInfo *projLeft;    
    ProjectionInfo *projRight;    
    TupleHashTable hashtable;    
    TupleHashTable hashnulls;    
    bool        havehashrows;    
    bool        havenullrows;    
    MemoryContext hashtablecxt; 
    MemoryContext hashtempcxt;    
    ExprContext *innerecontext; 
    AttrNumber *keyColIdx;        
    Oid           *tab_eq_funcoids;    
    Oid           *tab_collations; 
    FmgrInfo   *tab_hash_funcs; 
    FmgrInfo   *tab_eq_funcs;    
    FmgrInfo   *lhs_hash_funcs; 
    FmgrInfo   *cur_eq_funcs;    
    ExprState  *cur_eq_comp;    
} SubPlanState;

SubPlan
子查询计划


typedef struct SubPlan
{
    Expr        xpr;//表达式
    
    //从SubLink中拷贝而来
    SubLinkType subLinkType;    
    
    //组合操作符,转换为可执行的表达式
    Node       *testexpr;        
    List       *paramIds;        
    
    //Plan tree标识
    int            plan_id;        
    
    //EXPLAIN和debug目的的SubPlan标识
    char       *plan_name;        
    
    //用于确定subplan输出类型的额外信息
    Oid            firstColType;    
    int32        firstColTypmod; 
    Oid            firstColCollation;    
    
    //执行阶段的相关信息
    bool        useHashTable;    
    bool        unknownEqFalse; 
    bool        parallel_safe;    
    
    
    //用于给子查询传入和传出参数的信息
    
    //setParam和parParam是整型链表(param IDs)
    List       *setParam;        
    List       *parParam;        
    List       *args;            
    
    //估算执行成本
    Cost        startup_cost;    
    Cost        per_call_cost;    
} SubPlan;

SubLinkType
SubLink类型


typedef enum SubLinkType
{
    EXISTS_SUBLINK,
    ALL_SUBLINK,
    ANY_SUBLINK,
    ROWCOMPARE_SUBLINK,
    EXPR_SUBLINK,
    MULTIEXPR_SUBLINK,
    ARRAY_SUBLINK,
    CTE_SUBLINK                    
} SubLinkType;

SubLink
SubLink结构体

typedef struct SubLink
{
    Expr        xpr;
    SubLinkType subLinkType;    
    int            subLinkId;        
    Node       *testexpr;        
    List       *operName;        
    Node       *subselect;        
    int            location;        
} SubLink;

二、源码解读

ExecScanSubPlan


static Datum
ExecScanSubPlan(SubPlanState *node,
                ExprContext *econtext,
                bool *isNull)
{
    SubPlan    *subplan = node->subplan;//子计划
    PlanState  *planstate = node->planstate;//计划运行期状态
    SubLinkType subLinkType = subplan->subLinkType;//子链接类型
    MemoryContext oldcontext;//原内存上下文
    TupleTableSlot *slot;//元组slot
    Datum        result;//结果指针
    bool        found = false;    
    ListCell   *pvar;//临时变量
    ListCell   *l;//临时变量
    ArrayBuildStateAny *astate = NULL;//
    
    if (subLinkType == MULTIEXPR_SUBLINK)
    {
        EState       *estate = node->parent->state;
        foreach(l, subplan->setParam)
        {
            int            paramid = lfirst_int(l);
            ParamExecData *prm = &(estate->es_param_exec_vals[paramid]);
            prm->execPlan = node;
        }
        *isNull = true;
        return (Datum) 0;
    }
    
    //数组
    if (subLinkType == ARRAY_SUBLINK)
        astate = initArrayResultAny(subplan->firstColType,
                                    CurrentMemoryContext, true);
    
    //切换上下文
    oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
    
    //通过父计划相关值中设置子计划参数
    Assert(list_length(subplan->parParam) == list_length(node->args));
    forboth(l, subplan->parParam, pvar, node->args)
    {
        int            paramid = lfirst_int(l);
        ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
        prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar),
                                               econtext,
                                               &(prm->isnull));
        planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
    }
    
    //执行ReScan
    //Reset a plan node so that its output can be re-scanned.
    ExecReScan(planstate);
    
    result = BoolGetDatum(subLinkType == ALL_SUBLINK);//ALL为T,否则为F
    *isNull = false;
    for (slot = ExecProcNode(planstate);
         !TupIsNull(slot);
         slot = ExecProcNode(planstate))//循环获取元组,直至没有元组为NULL(即已完成)
    {
        //元组描述符
        TupleDesc    tdesc = slot->tts_tupleDescriptor;
        Datum        rowresult;//结果
        bool        rownull;//是否为空?
        int            col;//列计数器
        ListCell   *plst;//临时变量
        if (subLinkType == EXISTS_SUBLINK)//EXISTS
        {
            found = true;
            result = BoolGetDatum(true);
            break;
        }
        if (subLinkType == EXPR_SUBLINK)//EXPR表达式
        {
            
            if (found)
                ereport(ERROR,
                        (errcode(ERRCODE_CARDINALITY_VIOLATION),
                         errmsg("more than one row returned by a subquery used as an expression")));
            found = true;
            
            if (node->curTuple)
                heap_freetuple(node->curTuple);
            node->curTuple = ExecCopySlotHeapTuple(slot);
            result = heap_getattr(node->curTuple, 1, tdesc, isNull);
            
            continue;
        }
        if (subLinkType == ARRAY_SUBLINK)//数组
        {
            Datum        dvalue;
            bool        disnull;
            found = true;
            
            Assert(subplan->firstColType == TupleDescAttr(tdesc, 0)->atttypid);
            dvalue = slot_getattr(slot, 1, &disnull);
            astate = accumArrayResultAny(astate, dvalue, disnull,
                                         subplan->firstColType, oldcontext);
            
            continue;
        }
        
        if (subLinkType == ROWCOMPARE_SUBLINK && found)//行比较
            ereport(ERROR,
                    (errcode(ERRCODE_CARDINALITY_VIOLATION),
                     errmsg("more than one row returned by a subquery used as an expression")));
        found = true;//初始为T
        
        col = 1;//列从1计数
        foreach(plst, subplan->paramIds)//循环遍历子查询参数
        {
            int            paramid = lfirst_int(plst);
            ParamExecData *prmdata;
            prmdata = &(econtext->ecxt_param_exec_vals[paramid]);
            Assert(prmdata->execPlan == NULL);
            //获取参数值
            prmdata->value = slot_getattr(slot, col, &(prmdata->isnull));
            //下一个列
            col++;
        }
        //解析表达式
        rowresult = ExecEvalExprSwitchContext(node->testexpr, econtext,
                                              &rownull);
        if (subLinkType == ANY_SUBLINK)
        {
            //ANY : 使用OR语义组合
            
            if (rownull)
                *isNull = true;
            else if (DatumGetBool(rowresult))
            {
                result = BoolGetDatum(true);
                *isNull = false;
                break;            
            }
        }
        else if (subLinkType == ALL_SUBLINK)
        {
            //ALL : 使用AND语义
            
            if (rownull)
                *isNull = true;
            else if (!DatumGetBool(rowresult))
            {
                result = BoolGetDatum(false);
                *isNull = false;
                break;            
            }
        }
        else
        {
            
            //这里一定是ROWCOMPARE
            result = rowresult;
            *isNull = rownull;
        }
    }
    MemoryContextSwitchTo(oldcontext);
    if (subLinkType == ARRAY_SUBLINK)
    {
        
        //在调用者上下文中返回结果
        result = makeArrayResultAny(astate, oldcontext, true);
    }
    else if (!found)
    {
        
        if (subLinkType == EXPR_SUBLINK ||
            subLinkType == ROWCOMPARE_SUBLINK)
        {
            result = (Datum) 0;
            *isNull = true;
        }
    }
    //返回结果
    return result;
}

ExecProcNode
执行输入参数node的ExecProcNode方法。


#ifndef FRONTEND
static inline TupleTableSlot *
ExecProcNode(PlanState *node)
{
    if (node->chgParam != NULL) 
        ExecReScan(node);        
    return node->ExecProcNode(node);
}
#endif

三、跟踪分析

执行SQL:

[pg12@localhost ~]$ psql -d testdb
Timing is on.
Expanded display is used automatically.
psql (12.0)
Type "help" for help.
[local]:5432 pg12@testdb=# 
[local]:5432 pg12@testdb=# select * from tbl;
 id | value 
----+-------
  1 |     2
(1 row)
Time: 2.678 ms
[local]:5432 pg12@testdb=# select count(*) from t_big_null;
  count   
----------
 10000001
(1 row)
Time: 679.972 ms
[local]:5432 pg12@testdb=# analyze tbl;
ANALYZE
Time: 64.442 ms
[local]:5432 pg12@testdb=# analyze t_big_null;
ANALYZE
Time: 434.702 ms
[local]:5432 pg12@testdb=# 
[local]:5432 pg12@testdb=# select pg_backend_pid();
 pg_backend_pid 
----------------
          18758
(1 row)
Time: 1.990 ms
[local]:5432 pg12@testdb=# select * from tbl a where a.id not in (select b.id from t_big_null b);

启动gdb跟踪

(gdb) b ExecScanSubPlan
Breakpoint 1 at 0x73014b: file nodeSubplan.c, line 228.
(gdb) c
Continuing.
Breakpoint 1, ExecScanSubPlan (node=0x1c89158, econtext=0x1c88990, isNull=0x1c88cad)
    at nodeSubplan.c:228
228        SubPlan    *subplan = node->subplan;
(gdb) 
(gdb) n
229        PlanState  *planstate = node->planstate;
(gdb) 
230        SubLinkType subLinkType = subplan->subLinkType;
(gdb) 
234        bool        found = false;    

subplan变量值(结构体SubPlan)
其中testexpr是测试表达式,操作符是整型的等值比较,
左操作符是Var,数据表的第一个列,类型为23-int4(select * from pg_type where oid=23;)
有操作符是Param,执行期设置,对应参数索引编号为0,类型为23-int4
paramIds是链表,第一项ID值为0(int_value = 0)
子查询结果的第一个列类型为23-int4

(gdb) p *subplan
$1 = {xpr = {type = T_SubPlan}, subLinkType = ANY_SUBLINK, testexpr = 0x1cb8790, 
  paramIds = 0x1cb8758, plan_id = 1, plan_name = 0x1cb8a80 "SubPlan 1", 
  firstColType = 23, firstColTypmod = -1, firstColCollation = 0, useHashTable = false, 
  unknownEqFalse = false, parallel_safe = true, setParam = 0x0, parParam = 0x0, 
  args = 0x0, startup_cost = 0, per_call_cost = 129155.31875000001}
(gdb) p *subplan->testexpr
$2 = {type = T_OpExpr}
(gdb) p *(OpExpr *)subplan->testexpr
$3 = {xpr = {type = T_OpExpr}, opno = 96, opfuncid = 65, opresulttype = 16, 
  opretset = false, opcollid = 0, inputcollid = 0, args = 0x1cb8868, location = 31}
(gdb) set $expr=(OpExpr *)subplan->testexpr
(gdb) p *$expr->args
$4 = {type = T_List, length = 2, head = 0x1cb8840, tail = 0x1cb88d8}
(gdb) p *$expr->args->head
$5 = {data = {ptr_value = 0x1cb87e8, int_value = 30115816, oid_value = 30115816}, 
  next = 0x1cb88d8}
(gdb) p *(Node *)$expr->args->head->data.ptr_value
$6 = {type = T_Var}
(gdb) p *(Var *)$expr->args->head->data.ptr_value
$7 = {xpr = {type = T_Var}, varno = 1, varattno = 1, vartype = 23, vartypmod = -1, 
  varcollid = 0, varlevelsup = 0, varnoold = 1, varoattno = 1, location = 26}
(gdb) p *(Var *)$expr->args->head->next->data.ptr_value
$8 = {xpr = {type = T_Param}, varno = 1, varattno = 0, vartype = 23, vartypmod = -1, 
  varcollid = 0, varlevelsup = 4294967295, varnoold = 2139062142, varoattno = 16, 
  location = 0}
(gdb) p *(Param *)$expr->args->head->next->data.ptr_value
$9 = {xpr = {type = T_Param}, paramkind = PARAM_EXEC, paramid = 0, paramtype = 23, 
  paramtypmod = -1, paramcollid = 0, location = -1}
(gdb) 
###
[local]:5432 pg12@testdb=# select * from pg_proc where oid = 65; --> opfuncid = 65,函数
-[ RECORD 1 ]---+-------
oid             | 65
proname         | int4eq
pronamespace    | 11
proowner        | 10
prolang         | 12
procost         | 1
prorows         | 0
provariadic     | 0
prosupport      | -
prokind         | f
prosecdef       | f
proleakproof    | t
proisstrict     | t
proretset       | f
provolatile     | i
proparallel     | s
pronargs        | 2
pronargdefaults | 0
prorettype      | 16
proargtypes     | 23 23
proallargtypes  | 
proargmodes     | 
proargnames     | 
proargdefaults  | 
protrftypes     | 
proclass="lazy" data-src          | int4eq
probin          | 
proconfig       | 
proacl          | 
Time: 6.253 ms
###
(gdb) p *subplan->paramIds
$11 = {type = T_IntList, length = 1, head = 0x1cb8730, tail = 0x1cb8730}
(gdb) p *subplan->paramIds->head
$12 = {data = {ptr_value = 0x7f7f7f7f00000000, int_value = 0, oid_value = 0}, next = 0x0}
(gdb)

planstate变量值,实际的执行节点是ExecMaterial

(gdb) p *planstate
$15 = {type = T_MaterialState, plan = 0x1cb8900, state = 0x1c87da8, 
  ExecProcNode = 0x6f802a <ExecProcNodeFirst>, 
  ExecProcNodeReal = 0x720ecf <ExecMaterial>, instrument = 0x0, worker_instrument = 0x0, 
  worker_jit_instrument = 0x0, qual = 0x0, lefttree = 0x1c88160, righttree = 0x0, 
  initPlan = 0x0, subPlan = 0x0, chgParam = 0x0, ps_ResultTupleDesc = 0x1c88580, 
  ps_ResultTupleSlot = 0x1c88698, ps_ExprContext = 0x0, ps_ProjInfo = 0x0, 
  scandesc = 0x1c88468, scanops = 0xc3e720 <TTSOpsMinimalTuple>, outerops = 0x0, 
  innerops = 0x0, resultops = 0xc3e720 <TTSOpsMinimalTuple>, scanopsfixed = true, 
  outeropsfixed = false, inneropsfixed = false, resultopsfixed = true, scanopsset = true, 
  outeropsset = false, inneropsset = false, resultopsset = true}
(gdb)

subLinkType变量,类型为ANY_SUBLINK,把NOT IN转为ANY_SUBLINK

(gdb) p subLinkType
$16 = ANY_SUBLINK

设置变量,执行相关检查等

(gdb) n
237        ArrayBuildStateAny *astate = NULL;
(gdb) 
250        if (subLinkType == MULTIEXPR_SUBLINK)
(gdb) 
266        if (subLinkType == ARRAY_SUBLINK)
(gdb) 
275        oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
(gdb) 
282        Assert(list_length(subplan->parParam) == list_length(node->args));
(gdb) 
284        forboth(l, subplan->parParam, pvar, node->args)
(gdb) p subplan->parParam
$17 = (List *) 0x0

执行ExecReScan,planstate->ExecProcNode实际为ExecMaterial

(gdb) n
298        ExecReScan(planstate);
(gdb) p *planstate
$20 = {type = T_MaterialState, plan = 0x1cb8900, state = 0x1c87da8, 
  ExecProcNode = 0x720ecf <ExecMaterial>, ExecProcNodeReal = 0x720ecf <ExecMaterial>, 
  instrument = 0x0, worker_instrument = 0x0, worker_jit_instrument = 0x0, qual = 0x0, 
  lefttree = 0x1c88160, righttree = 0x0, initPlan = 0x0, subPlan = 0x0, chgParam = 0x0, 
  ps_ResultTupleDesc = 0x1c88580, ps_ResultTupleSlot = 0x1c88698, ps_ExprContext = 0x0, 
  ps_ProjInfo = 0x0, scandesc = 0x1c88468, scanops = 0xc3e720 <TTSOpsMinimalTuple>, 
  outerops = 0x0, innerops = 0x0, resultops = 0xc3e720 <TTSOpsMinimalTuple>, 
  scanopsfixed = true, outeropsfixed = false, inneropsfixed = false, 
  resultopsfixed = true, scanopsset = true, outeropsset = false, inneropsset = false, 
  resultopsset = true}
(gdb)

初始化result&isNull变量

(gdb) n
321        result = BoolGetDatum(subLinkType == ALL_SUBLINK);
(gdb) 
322        *isNull = false;
(gdb) p result
$18 = 0

执行循环,slot从planstate->ExecProcNode(即ExecMaterial)中获取

(gdb) n
324        for (slot = ExecProcNode(planstate);
(gdb) 
325             !TupIsNull(slot);
(gdb) 
(gdb) p *slot
$22 = {type = T_TupleTableSlot, tts_flags = 20, tts_nvalid = 0, 
  tts_ops = 0xc3e720 <TTSOpsMinimalTuple>, tts_tupleDescriptor = 0x1c88580, 
  tts_values = 0x1c88708, tts_isnull = 0x1c88710, tts_mcxt = 0x1c87c90, tts_tid = {
    ip_blkid = {bi_hi = 65535, bi_lo = 65535}, ip_posid = 0}, tts_tableOid = 0}
(gdb) p slot->tts_values[0]
$23 = 0
(gdb)

获取slot的描述符

(gdb) 
328            TupleDesc    tdesc = slot->tts_tupleDescriptor;
(gdb) p tdesc
$21 = (TupleDesc) 0x206e6f6900000000

判断subLink类型执行相关逻辑,循环paramIds,填充参数值

(gdb) n
334            if (subLinkType == EXISTS_SUBLINK)
(gdb) 
341            if (subLinkType == EXPR_SUBLINK)
(gdb) 
367            if (subLinkType == ARRAY_SUBLINK)
(gdb) 
383            if (subLinkType == ROWCOMPARE_SUBLINK && found)
(gdb) 
388            found = true;
(gdb) 
395            col = 1;
(gdb) 
396            foreach(plst, subplan->paramIds)
(gdb) p *slot
$22 = {type = T_TupleTableSlot, tts_flags = 20, tts_nvalid = 0, 
  tts_ops = 0xc3e720 <TTSOpsMinimalTuple>, tts_tupleDescriptor = 0x1c88580, 
  tts_values = 0x1c88708, tts_isnull = 0x1c88710, tts_mcxt = 0x1c87c90, tts_tid = {
    ip_blkid = {bi_hi = 65535, bi_lo = 65535}, ip_posid = 0}, tts_tableOid = 0}
(gdb) p *slot->tts_values[0]
Cannot access memory at address 0x0
(gdb) p slot->tts_values[0]
$23 = 0
(gdb) n
398                int            paramid = lfirst_int(plst);
(gdb) 
401                prmdata = &(econtext->ecxt_param_exec_vals[paramid]);
(gdb) p paramid
$24 = 0
(gdb) n
402                Assert(prmdata->execPlan == NULL);
(gdb) p *prmdata
$25 = {execPlan = 0x0, value = 0, isnull = false}
(gdb) n
403                prmdata->value = slot_getattr(slot, col, &(prmdata->isnull));
(gdb) n
404                col++;
(gdb) p *prmdata
$26 = {execPlan = 0x0, value = 2, isnull = false}
(gdb) n
396            foreach(plst, subplan->paramIds)
(gdb)

解析表达式,亦即解析表达式tbl.id = 2,获取结果

(gdb) 
407            rowresult = ExecEvalExprSwitchContext(node->testexpr, econtext,
(gdb) p *(Var *)$expr->args->head->data.ptr_value
$28 = {xpr = {type = T_Var}, varno = 1, varattno = 1, vartype = 23, vartypmod = -1, 
  varcollid = 0, varlevelsup = 0, varnoold = 1, varoattno = 1, location = 26}
(gdb)  p *(Param *)$expr->args->head->next->data.ptr_value
$29 = {xpr = {type = T_Param}, paramkind = PARAM_EXEC, paramid = 0, paramtype = 23, 
  paramtypmod = -1, paramcollid = 0, location = -1}
(gdb)  p econtext->ecxt_param_exec_vals[0]
$30 = {execPlan = 0x0, value = 2, isnull = false}

由于tbl.id = 1,因此表达式解析结果为F

(gdb) n
410            if (subLinkType == ANY_SUBLINK)
(gdb) p rowresult
$31 = 0
(gdb)

判断subLink类型,如为ANY则进入相应逻辑

(gdb) n
410            if (subLinkType == ANY_SUBLINK)
(gdb) p rowresult
$31 = 0
(gdb) n
413                if (rownull)
(gdb) p rownull
$32 = false
(gdb) n
415                else if (DatumGetBool(rowresult))
(gdb)

结果不为T,因此再次循环执行,获取slot,这次的值应为3,因为3 <> 1,因此再次循环直至t_big_null中出现值1或完成扫描

326             slot = ExecProcNode(planstate))
(gdb) 
...
(gdb) 
403                prmdata->value = slot_getattr(slot, col, &(prmdata->isnull));
(gdb) 
404                col++;
(gdb) p prmdata->value
$36 = 3
(gdb) p slot->tts_values[0]
$37 = 3
(gdb) 
...

完成执行

(gdb) c
Continuing.
###
[local]:5432 pg12@testdb=# select * from tbl a where a.id not in (select b.id from t_big_null b);
 id | value 
----+-------
(0 rows)
Time: 3089703.031 ms (51:29.703)
[local]:5432 pg12@testdb=# 
[local]:5432 pg12@testdb=# 
###

调用栈

Breakpoint 1, ExecScanSubPlan (node=0x1c89158, econtext=0x1c88990, isNull=0x1c88cad)
    at nodeSubplan.c:228
228        SubPlan    *subplan = node->subplan;
(gdb) bt
#0  ExecScanSubPlan (node=0x1c89158, econtext=0x1c88990, isNull=0x1c88cad)
    at nodeSubplan.c:228
#1  0x000000000072fe5e in ExecSubPlan (node=0x1c89158, econtext=0x1c88990, 
    isNull=0x1c88cad) at nodeSubplan.c:90
#2  0x00000000006e90a8 in ExecEvalSubPlan (state=0x1c88ca8, op=0x1c88d80, 
    econtext=0x1c88990) at execExprInterp.c:3783
#3  0x00000000006e48b2 in ExecInterpExpr (state=0x1c88ca8, econtext=0x1c88990, 
    isnull=0x7fff7b9514f7) at execExprInterp.c:1484
#4  0x00000000006e50b8 in ExecInterpExprStillValid (state=0x1c88ca8, econtext=0x1c88990, 
    isNull=0x7fff7b9514f7) at execExprInterp.c:1769
#5  0x00000000006f9ec0 in ExecEvalExprSwitchContext (state=0x1c88ca8, econtext=0x1c88990, 
    isNull=0x7fff7b9514f7) at ../../../class="lazy" data-src/include/executor/executor.h:307
#6  0x00000000006f9fb8 in ExecQual (state=0x1c88ca8, econtext=0x1c88990)
    at ../../../class="lazy" data-src/include/executor/executor.h:376
#7  0x00000000006fa37d in ExecScan (node=0x1c88878, accessMtd=0x72b84c <SeqNext>, 
    recheckMtd=0x72b8f1 <SeqRecheck>) at execScan.c:228
#8  0x000000000072b93b in ExecSeqScan (pstate=0x1c88878) at nodeSeqscan.c:112
#9  0x00000000006f8077 in ExecProcNodeFirst (node=0x1c88878) at execProcnode.c:445
#10 0x00000000006ed3cd in ExecProcNode (node=0x1c88878)
    at ../../../class="lazy" data-src/include/executor/executor.h:239
#11 0x00000000006efbb3 in ExecutePlan (estate=0x1c87da8, planstate=0x1c88878, 
    use_parallel_mode=false, operation=CMD_SELECT, sendTuples=true, numberTuples=0, 
    direction=ForwardScanDirection, dest=0x1cbc7c0, execute_once=true) at execMain.c:1646
#12 0x00000000006ed9df in standard_ExecutorRun (queryDesc=0x1be78b8, 
    direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:364
#13 0x00000000006ed815 in ExecutorRun (queryDesc=0x1be78b8, 
    direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:308
#14 0x00000000008f1010 in PortalRunSelect (portal=0x1c27d78, forward=true, count=0, 
    dest=0x1cbc7c0) at pquery.c:929
#15 0x00000000008f0cae in PortalRun (portal=0x1c27d78, count=9223372036854775807, 
    isTopLevel=true, run_once=true, dest=0x1cbc7c0, altdest=0x1cbc7c0, 
    completionTag=0x7fff7b951890 "") at pquery.c:770
#16 0x00000000008ead35 in exec_simple_query (
    query_string=0x1bc1d88 "select * from tbl a where a.id not in (select b.id from t_big_null b);") at postgres.c:1215
#17 0x00000000008eefa5 in PostgresMain (argc=1, argv=0x1bedf18, 
    dbname=0x1bedd60 "testdb", username=0x1bbeaa8 "pg12") at postgres.c:4236
#18 0x0000000000845915 in BackendRun (port=0x1be3d30) at postmaster.c:4431
#19 0x00000000008450f3 in BackendStartup (port=0x1be3d30) at postmaster.c:4122
#20 0x000000000084132f in ServerLoop () at postmaster.c:1704
#21 0x0000000000840be5 in PostmasterMain (argc=1, argv=0x1bbca60) at postmaster.c:1377
#22 0x0000000000761469 in main (argc=1, argv=0x1bbca60) at main.c:228
(gdb)

到此,相信大家对“PostgreSQL源码中NOT IN的作用是什么”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

PostgreSQL源码中NOT IN的作用是什么

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

postgresql中timestamp的作用是什么

在postgresql中,timestamp是一种数据类型,用于存储日期和时间信息。它可以存储从公元前4713年到公元后294276年之间的日期和时间。timestamp数据类型非常有用,可以用来记录事件发生的时间戳,比如数据库中的数据插入
postgresql中timestamp的作用是什么
2024-03-02

postgresql中explain的作用是什么

在PostgreSQL中,EXPLAIN语句用于分析查询语句的执行计划,帮助开发人员和数据库管理员了解系统如何执行特定查询,并且可以帮助优化查询性能。当你执行一个查询时,可以在该查询之前加上EXPLAIN关键字,以获取 PostgreSQ
postgresql中explain的作用是什么
2024-03-06

postgresql中concat的作用是什么

在 PostgreSQL 中,concat 函数的作用是将两个或多个字符串连接起来,形成一个新的字符串。concat 函数接受任意数量的参数,每个参数都是一个字符串。例如:SELECT concat('hello ',
postgresql中concat的作用是什么
2024-04-09

postgresql中group_concat的作用是什么

在 PostgreSQL 中,没有内置的 GROUP_CONCAT 函数,但可以使用 STRING_AGG 函数来实现类似的功能。STRING_AGG 函数用于将一列值连接为一个字符串,并以指定的分隔符分隔这些值。这在对查询结果进行聚合操作
postgresql中group_concat的作用是什么
2024-04-09

sql中not的作用是什么

在SQL中,NOT是一个逻辑运算符,用于对条件进行取反,即反转条件的结果。当NOT与其他逻辑运算符(比如AND、OR)一起使用时,可以用来构建更复杂的条件表达式。例如,可以使用NOT来表示"不等于"、“不包含”、"不是"等含义。通过使用NO
sql中not的作用是什么
2024-04-09

JavaScript中for-in语句的作用是什么

这篇文章将为大家详细讲解有关JavaScript中for-in语句的作用是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。说明1、for-in语句是一种严格的迭代语句,用于对象中的非符号键
2023-06-20

postgresql数据库中间件的作用是什么

在PostgreSQL数据库中,中间件的作用是在数据库服务器和客户端之间提供一些额外的功能和服务,以提高数据库的性能、可靠性和可扩展性。一些常见的中间件功能包括连接池管理、负载均衡、故障转移、缓存管理、数据复制和分区等。通过使用中间件,可以
postgresql数据库中间件的作用是什么
2024-04-08

python中in操作符指的是什么

这篇文章主要介绍python中in操作符指的是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、说明字典in操作符用于判断指定键是否存在于字典中,如果键在字典中返回 True,否则返回 False。2、语法key
2023-06-15

postgresql中explain的用法是什么

在 PostgreSQL 中,EXPLAIN 是一个用于查询执行计划的命令。通过在查询语句前加上 EXPLAIN 关键字,可以让 PostgreSQL 返回查询的执行计划,而不执行实际的查询操作。使用 EXPLAIN 命令可以帮助我们分析
postgresql中explain的用法是什么
2024-03-06

postgresql中case的用法是什么

在PostgreSQL中,CASE表达式用于根据条件返回不同的值。它的一般语法如下:CASEWHEN condition1 THEN result1WHEN condition2 THEN result2...ELSE default_r
postgresql中case的用法是什么
2024-03-06

编程热搜

目录