iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >怎么使用PostgreSQL的tuplesort_performsort函数
  • 395
分享到

怎么使用PostgreSQL的tuplesort_performsort函数

2024-04-02 19:04:59 395人浏览 安东尼
摘要

本篇内容主要讲解“怎么使用postgresql的tuplesort_perfORMsort函数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Postgr

本篇内容主要讲解“怎么使用postgresql的tuplesort_perfORMsort函数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Postgresql的tuplesort_performsort函数”吧!

TupleTableSlot
执行器在”tuple table”中存储元组,这个表是各自独立的TupleTableSlots链表.


typedef struct TupleTableSlot
{
    nodeTag     type;//Node标记
    //如slot为空,则为T
    bool        tts_isempty;    
    //是否需要pfree tts_tuple?
    bool        tts_shouldFree; 
    //是否需要pfree tts_mintuple?
    bool        tts_shouldFreeMin;  
#define FIELDNO_TUPLETABLESLOT_SLOW 4
    //为slot_deform_tuple存储状态?
    bool        tts_slow;       
#define FIELDNO_TUPLETABLESLOT_TUPLE 5
    //物理元组,如为虚拟元组则为NULL
    HeapTuple   tts_tuple;      
#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 6
    //slot中的元组描述符
    TupleDesc   tts_tupleDescriptor;    
    //slot所在的上下文
    MemoryContext tts_mcxt;     
    //元组缓存,如无则为InvalidBuffer
    Buffer      tts_buffer;     
#define FIELDNO_TUPLETABLESLOT_NVALID 9
    //tts_values中的有效值
    int         tts_nvalid;     
#define FIELDNO_TUPLETABLESLOT_VALUES 10
    //当前每个属性的值
    Datum      *tts_values;     
#define FIELDNO_TUPLETABLESLOT_ISNULL 11
    //isnull数组
    bool       *tts_isnull;     
    //minimal元组,如无则为NULL
    MinimalTuple tts_mintuple;  
    //在minimal情况下的工作空间
    HeapTupleData tts_minhdr;   
#define FIELDNO_TUPLETABLESLOT_OFF 14
    //slot_deform_tuple的存储状态
    uint32      tts_off;        
    //不能被变更的描述符(固定描述符)
    bool        tts_fixedTupleDescriptor;   
} TupleTableSlot;

typedef struct TupleTableSlot
{
    NodeTag     type;//Node标记
#define FIELDNO_TUPLETABLESLOT_FLAGS 1
    uint16      tts_flags;      
#define FIELDNO_TUPLETABLESLOT_NVALID 2
    AttrNumber  tts_nvalid;     
    const TupleTableSlotOps *const tts_ops; 
#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 4
    TupleDesc   tts_tupleDescriptor;    
#define FIELDNO_TUPLETABLESLOT_VALUES 5
    Datum      *tts_values;     
#define FIELDNO_TUPLETABLESLOT_ISNULL 6
    bool       *tts_isnull;     
    MemoryContext tts_mcxt;     
} TupleTableSlot;

//TupleTableSlot的"小程序"
struct TupleTableSlotOps
{
    
    //slot的最小化大小
    size_t          base_slot_size;
    
    //初始化方法
    void (*init)(TupleTableSlot *slot);
    
    //析构方法
    void (*release)(TupleTableSlot *slot);
    
    void (*clear)(TupleTableSlot *slot);
    
    void (*getsomeattrs)(TupleTableSlot *slot, int natts);
    
    Datum (*getsysattr)(TupleTableSlot *slot, int attnum, bool *isnull);
    
    void (*materialize)(TupleTableSlot *slot);
    
    void (*copyslot) (TupleTableSlot *dstslot, TupleTableSlot *srcslot);
    
    HeapTuple (*get_heap_tuple)(TupleTableSlot *slot);
    
    MinimalTuple (*get_minimal_tuple)(TupleTableSlot *slot);
    
    HeapTuple (*copy_heap_tuple)(TupleTableSlot *slot);
    
    MinimalTuple (*copy_minimal_tuple)(TupleTableSlot *slot);
};
typedef struct tupleDesc
{
    int         natts;          
    Oid         tdtypeid;       
    int32       tdtypmod;       
    int         tdrefcount;     
    TupleConstr *constr;        
    
    //attrs[N]是第N+1个属性的描述符
    FormData_pg_attribute attrs[FLEXIBLE_ARRAY_MEMBER];
}  *TupleDesc;

SortState
排序运行期状态信息


typedef struct SortState
{
    //基类
    ScanState    ss;                
    //是否需要随机访问排序输出?
    bool        randoMaccess;    
    //结果集是否存在边界?
    bool        bounded;        
    //如存在边界,需要多少个元组?
    int64        bound;            
    //是否已完成排序?
    bool        sort_Done;        
    //是否使用有界值?
    bool        bounded_Done;    
    //使用的有界值?
    int64        bound_Done;        
    //tuplesort.c的私有状态
    void       *tuplesortstate; 
    //是否worker?
    bool        am_worker;        
    //每个worker对应一个条目
    SharedSortInfo *shared_info;    
} SortState;

typedef struct SharedSortInfo
{
    //worker个数?
    int            num_workers;
    //排序机制
    TuplesortInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER];
} SharedSortInfo;

TuplesortInstrumentation
报告排序统计的数据结构.


typedef enum
{
    SORT_TYPE_STILL_IN_PROGRESS = 0,//仍然在排序中
    SORT_TYPE_TOP_N_HEAPSORT,//TOP N 堆排序
    SORT_TYPE_QUICKSORT,//快速排序
    SORT_TYPE_EXTERNAL_SORT,//外部排序
    SORT_TYPE_EXTERNAL_MERGE//外部排序后的合并
} TuplesortMethod;//排序方法
typedef enum
{
    SORT_SPACE_TYPE_DISK,//需要用上磁盘
    SORT_SPACE_TYPE_MEMORY//使用内存
} TuplesortSpaceType;
typedef struct TuplesortInstrumentation
{
    //使用的排序算法
    TuplesortMethod sortMethod; 
    //排序使用空间类型
    TuplesortSpaceType spaceType;    
    //空间消耗(以K为单位)
    long        spaceUsed;        
} TuplesortInstrumentation;

二、源码解读

tuplesort_performsort是排序的实现.


void
tuplesort_performsort(Tuplesortstate *state)
{
    MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
#ifdef TRACE_SORT
    if (trace_sort)
        elog(LOG, "performsort of worker %d starting: %s",
             state->worker, pg_rusage_show(&state->ru_start));
#endif
    //根据状态执行不同的逻辑
    switch (state->status)
    {
        case TSS_INITIAL:
            
            if (SERIAL(state))
            {
                
                //快速排序
                tuplesort_sort_memtuples(state);
                state->status = TSS_SORTEDINMEM;
            }
            else if (WORKER(state))
            {
                
                inittapes(state, false);
                dumptuples(state, true);
                worker_nomergeruns(state);
                state->status = TSS_SORTEDONTAPE;
            }
            else
            {
                
                leader_takeover_tapes(state);
                mergeruns(state);
            }
            state->current = 0;
            state->eof_reached = false;
            state->markpos_block = 0L;
            state->markpos_offset = 0;
            state->markpos_eof = false;
            break;
        case TSS_BOUNDED://堆排序
            
            sort_bounded_heap(state);
            state->current = 0;
            state->eof_reached = false;
            state->markpos_offset = 0;
            state->markpos_eof = false;
            state->status = TSS_SORTEDINMEM;
            break;
        case TSS_BUILDRUNS:
            
            //全部刷到磁盘上
            dumptuples(state, true);
            //合并执行
            mergeruns(state);
            state->eof_reached = false;
            state->markpos_block = 0L;
            state->markpos_offset = 0;
            state->markpos_eof = false;
            break;
        default:
            elog(ERROR, "invalid tuplesort state");
            break;
    }
#ifdef TRACE_SORT
    if (trace_sort)
    {
        if (state->status == TSS_FINALMERGE)
            elog(LOG, "performsort of worker %d done (except %d-way final merge): %s",
                 state->worker, state->activeTapes,
                 pg_rusage_show(&state->ru_start));
        else
            elog(LOG, "performsort of worker %d done: %s",
                 state->worker, pg_rusage_show(&state->ru_start));
    }
#endif
    MemoryContextSwitchTo(oldcontext);
}

三、跟踪分析

测试脚本

select * from t_sort order by c1,c2;

跟踪分析

(gdb) b tuplesort_begin_heap
Breakpoint 1 at 0xa6ffa1: file tuplesort.c, line 812.
(gdb) b tuplesort_puttupleslot
Breakpoint 2 at 0xa7119d: file tuplesort.c, line 1436.
(gdb) b tuplesort_performsort
Breakpoint 3 at 0xa71f45: file tuplesort.c, line 1792.
(gdb) c
Continuing.
Breakpoint 1, tuplesort_begin_heap (tupDesc=0x208fa40, nkeys=2, attNums=0x2081858, sortOperators=0x2081878, 
    sortCollations=0x2081898, nullsFirstFlags=0x20818b8, workMem=4096, coordinate=0x0, randomAccess=false)
    at tuplesort.c:812
812        Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
(gdb)

tuplesort_begin_heap
输入参数

(gdb) p *tupDesc
$1 = {natts = 7, tdtypeid = 2249, tdtypmod = -1, tdhasoid = false, tdrefcount = -1, constr = 0x0, attrs = 0x208fa60}
(gdb) p *tupDesc->attrs
$2 = {attrelid = 0, attname = {data = '\000' <repeats 63 times>}, atttypid = 1043, attstattarget = -1, attlen = -1, 
  attnum = 1, attndims = 0, attcacheoff = -1, atttypmod = 24, attbyval = false, attstorage = 120 'x', attalign = 105 'i', 
  attnotnull = false, atthasdef = false, atthasmissing = false, attidentity = 0 '\000', attisdropped = false, 
  attislocal = true, attinhcount = 0, attcollation = 100}
(gdb) p *attNums
$3 = 2
(gdb) p *sortOperators
$4 = 97
(gdb) p *sortCollations
$5 = 0
(gdb) p nullsFirstFlags
$6 = (_Bool *) 0x20818b8
(gdb) p *nullsFirstFlags
$7 = false
(gdb)

获取排序状态,status = TSS_INITIAL

(gdb) p *state
$8 = {status = TSS_INITIAL, nKeys = 0, randomAccess = false, bounded = false, boundUsed = false, bound = 0, tuples = true, 
  availMem = 4169704, allowedMem = 4194304, maxTapes = 0, tapeRange = 0, sortcontext = 0x2093290, tuplecontext = 0x20992c0, 
  tapeset = 0x0, comparetup = 0x0, copytup = 0x0, writetup = 0x0, readtup = 0x0, memtuples = 0x209b310, memtupcount = 0, 
  memtupsize = 1024, growmemtuples = true, slabAllocatorUsed = false, slabMemoryBegin = 0x0, slabMemoryEnd = 0x0, 
  slabFreeHead = 0x0, read_buffer_size = 0, lastReturnedTuple = 0x0, currentRun = 0, mergeactive = 0x0, Level = 0, 
  destTape = 0, tp_fib = 0x0, tp_runs = 0x0, tp_dummy = 0x0, tp_tapenum = 0x0, activeTapes = 0, result_tape = -1, 
  current = 0, eof_reached = false, markpos_block = 0, markpos_offset = 0, markpos_eof = false, worker = -1, shared = 0x0, 
  nParticipants = -1, tupDesc = 0x0, sorTKEys = 0x0, onlyKey = 0x0, abbrevNext = 0, indexInfo = 0x0, estate = 0x0, 
  heapRel = 0x0, indexRel = 0x0, enforceUnique = false, high_mask = 0, low_mask = 0, max_buckets = 0, datumType = 0, 
  datumTypeLen = 0, ru_start = {tv = {tv_sec = 0, tv_usec = 0}, ru = {ru_utime = {tv_sec = 0, tv_usec = 0}, ru_stime = {
        tv_sec = 0, tv_usec = 0}, {ru_maxrss = 0, __ru_maxrss_Word = 0}, {ru_ixrss = 0, __ru_ixrss_word = 0}, {
        ru_idrss = 0, __ru_idrss_word = 0}, {ru_isrss = 0, __ru_isrss_word = 0}, {ru_minflt = 0, __ru_minflt_word = 0}, {
        ru_majflt = 0, __ru_majflt_word = 0}, {ru_nswap = 0, __ru_nswap_word = 0}, {ru_inblock = 0, __ru_inblock_word = 0}, 
      {ru_oublock = 0, __ru_oublock_word = 0}, {ru_msgsnd = 0, __ru_msgsnd_word = 0}, {ru_msgrcv = 0, 
        __ru_msgrcv_word = 0}, {ru_nsignals = 0, __ru_nsignals_word = 0}, {ru_nvcsw = 0, __ru_nvcsw_word = 0}, {
        ru_nivcsw = 0, __ru_nivcsw_word = 0}}}}

设置运行状态

(gdb) n
819        AssertArg(nkeys > 0);
(gdb) 
822        if (trace_sort)
(gdb) 
828        state->nKeys = nkeys;
(gdb) 
830        TRACE_POSTGRESQL_SORT_START(HEAP_SORT,
(gdb) 
837        state->comparetup = comparetup_heap;
(gdb) 
838        state->copytup = copytup_heap;
(gdb) 
839        state->writetup = writetup_heap;
(gdb) 
840        state->readtup = readtup_heap;
(gdb) 
842        state->tupDesc = tupDesc;    
(gdb) 
843        state->abbrevNext = 10;
(gdb) 
846        state->sortKeys = (SortSupport) palloc0(nkeys * sizeof(SortSupportData));
(gdb) 
848        for (i = 0; i < nkeys; i++)
(gdb) p *state
$9 = {status = TSS_INITIAL, nKeys = 2, randomAccess = false, bounded = false, boundUsed = false, bound = 0, tuples = true, 
  availMem = 4169704, allowedMem = 4194304, maxTapes = 0, tapeRange = 0, sortcontext = 0x2093290, tuplecontext = 0x20992c0, 
  tapeset = 0x0, comparetup = 0xa7525b <comparetup_heap>, copytup = 0xa76247 <copytup_heap>, 
  writetup = 0xa76de1 <writetup_heap>, readtup = 0xa76ec6 <readtup_heap>, memtuples = 0x209b310, memtupcount = 0, 
  memtupsize = 1024, growmemtuples = true, slabAllocatorUsed = false, slabMemoryBegin = 0x0, slabMemoryEnd = 0x0, 
  slabFreeHead = 0x0, read_buffer_size = 0, lastReturnedTuple = 0x0, currentRun = 0, mergeactive = 0x0, Level = 0, 
  destTape = 0, tp_fib = 0x0, tp_runs = 0x0, tp_dummy = 0x0, tp_tapenum = 0x0, activeTapes = 0, result_tape = -1, 
  current = 0, eof_reached = false, markpos_block = 0, markpos_offset = 0, markpos_eof = false, worker = -1, shared = 0x0, 
  nParticipants = -1, tupDesc = 0x208fa40, sortKeys = 0x20937c0, onlyKey = 0x0, abbrevNext = 10, indexInfo = 0x0, 
  estate = 0x0, heapRel = 0x0, indexRel = 0x0, enforceUnique = false, high_mask = 0, low_mask = 0, max_buckets = 0, 
  datumType = 0, datumTypeLen = 0, ru_start = {tv = {tv_sec = 0, tv_usec = 0}, ru = {ru_utime = {tv_sec = 0, tv_usec = 0}, 
      ru_stime = {tv_sec = 0, tv_usec = 0}, {ru_maxrss = 0, __ru_maxrss_word = 0}, {ru_ixrss = 0, __ru_ixrss_word = 0}, {
        ru_idrss = 0, __ru_idrss_word = 0}, {ru_isrss = 0, __ru_isrss_word = 0}, {ru_minflt = 0, __ru_minflt_word = 0}, {
        ru_majflt = 0, __ru_majflt_word = 0}, {ru_nswap = 0, __ru_nswap_word = 0}, {ru_inblock = 0, __ru_inblock_word = 0}, 
      {ru_oublock = 0, __ru_oublock_word = 0}, {ru_msgsnd = 0, __ru_msgsnd_word = 0}, {ru_msgrcv = 0, 
        __ru_msgrcv_word = 0}, {ru_nsignals = 0, __ru_nsignals_word = 0}, {ru_nvcsw = 0, __ru_nvcsw_word = 0}, {
        ru_nivcsw = 0, __ru_nivcsw_word = 0}}}}
(gdb)

为每一列(c1&c2)准备SortSupport数据(分配内存空间)

(gdb) n
850            SortSupport sortKey = state->sortKeys + i;
(gdb) 
852            AssertArg(attNums[i] != 0);
(gdb) p *state->sortKeys
$10 = {ssup_cxt = 0x0, ssup_collation = 0, ssup_reverse = false, ssup_nulls_first = false, ssup_attno = 0, 
  ssup_extra = 0x0, comparator = 0x0, abbreviate = false, abbrev_converter = 0x0, abbrev_abort = 0x0, 
  abbrev_full_comparator = 0x0}
(gdb) n
853            AssertArg(sortOperators[i] != 0);
(gdb) 
855            sortKey->ssup_cxt = CurrentMemoryContext;
(gdb) 
856            sortKey->ssup_collation = sortCollations[i];
(gdb) 
857            sortKey->ssup_nulls_first = nullsFirstFlags[i];
(gdb) 
858            sortKey->ssup_attno = attNums[i];
(gdb) 
860            sortKey->abbreviate = (i == 0);
(gdb) 
862            PrepareSortSupportFromOrderinGop(sortOperators[i], sortKey);
(gdb) 
848        for (i = 0; i < nkeys; i++)
(gdb) 
850            SortSupport sortKey = state->sortKeys + i;
(gdb) 
852            AssertArg(attNums[i] != 0);
(gdb) 
853            AssertArg(sortOperators[i] != 0);
(gdb) 
855            sortKey->ssup_cxt = CurrentMemoryContext;
(gdb) 
856            sortKey->ssup_collation = sortCollations[i];
(gdb) 
857            sortKey->ssup_nulls_first = nullsFirstFlags[i];
(gdb) 
858            sortKey->ssup_attno = attNums[i];
(gdb) 
860            sortKey->abbreviate = (i == 0);
(gdb) 
862            PrepareSortSupportFromOrderingOp(sortOperators[i], sortKey);
(gdb) 
848        for (i = 0; i < nkeys; i++)
(gdb)

完成初始化,返回state

(gdb) 
871        if (nkeys == 1 && !state->sortKeys->abbrev_converter)
(gdb) n
874        MemoryContextSwitchTo(oldcontext);
(gdb) 
876        return state;
(gdb) p *state
$11 = {status = TSS_INITIAL, nKeys = 2, randomAccess = false, bounded = false, boundUsed = false, bound = 0, tuples = true, 
  availMem = 4169704, allowedMem = 4194304, maxTapes = 0, tapeRange = 0, sortcontext = 0x2093290, tuplecontext = 0x20992c0, 
  tapeset = 0x0, comparetup = 0xa7525b <comparetup_heap>, copytup = 0xa76247 <copytup_heap>, 
  writetup = 0xa76de1 <writetup_heap>, readtup = 0xa76ec6 <readtup_heap>, memtuples = 0x209b310, memtupcount = 0, 
  memtupsize = 1024, growmemtuples = true, slabAllocatorUsed = false, slabMemoryBegin = 0x0, slabMemoryEnd = 0x0, 
  slabFreeHead = 0x0, read_buffer_size = 0, lastReturnedTuple = 0x0, currentRun = 0, mergeactive = 0x0, Level = 0, 
  destTape = 0, tp_fib = 0x0, tp_runs = 0x0, tp_dummy = 0x0, tp_tapenum = 0x0, activeTapes = 0, result_tape = -1, 
  current = 0, eof_reached = false, markpos_block = 0, markpos_offset = 0, markpos_eof = false, worker = -1, shared = 0x0, 
  nParticipants = -1, tupDesc = 0x208fa40, sortKeys = 0x20937c0, onlyKey = 0x0, abbrevNext = 10, indexInfo = 0x0, 
  estate = 0x0, heapRel = 0x0, indexRel = 0x0, enforceUnique = false, high_mask = 0, low_mask = 0, max_buckets = 0, 
  datumType = 0, datumTypeLen = 0, ru_start = {tv = {tv_sec = 0, tv_usec = 0}, ru = {ru_utime = {tv_sec = 0, tv_usec = 0}, 
      ru_stime = {tv_sec = 0, tv_usec = 0}, {ru_maxrss = 0, __ru_maxrss_word = 0}, {ru_ixrss = 0, __ru_ixrss_word = 0}, {
        ru_idrss = 0, __ru_idrss_word = 0}, {ru_isrss = 0, __ru_isrss_word = 0}, {ru_minflt = 0, __ru_minflt_word = 0}, {
        ru_majflt = 0, __ru_majflt_word = 0}, {ru_nswap = 0, __ru_nswap_word = 0}, {ru_inblock = 0, __ru_inblock_word = 0}, 
      {ru_oublock = 0, __ru_oublock_word = 0}, {ru_msgsnd = 0, __ru_msgsnd_word = 0}, {ru_msgrcv = 0, 
        __ru_msgrcv_word = 0}, {ru_nsignals = 0, __ru_nsignals_word = 0}, {ru_nvcsw = 0, __ru_nvcsw_word = 0}, {
        ru_nivcsw = 0, __ru_nivcsw_word = 0}}}}
(gdb)

tuplesort_puttupleslot
出现在循环中

for (;;)
        {
            //从outer plan中获取元组
            slot = ExecProcNode(outerNode);
            if (TupIsNull(slot))
                break;//直至全部获取完毕
            //排序
            tuplesort_puttupleslot(tuplesortstate, slot);
        }

以其中一个slot为例说明

(gdb) c
Continuing.
Breakpoint 2, tuplesort_puttupleslot (state=0x20933a8, slot=0x208f8c8) at tuplesort.c:1436
1436        MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);

输入参数,state为先前调用begin_heap返回的state,slot为outer node返回的元组slot

(gdb) p *slot
$12 = {type = T_TupleTableSlot, tts_isempty = false, tts_shouldFree = false, tts_shouldFreeMin = false, tts_slow = false, 
  tts_tuple = 0x2090678, tts_tupleDescriptor = 0x7f061a300380, tts_mcxt = 0x208f270, tts_buffer = 103, tts_nvalid = 0, 
  tts_values = 0x208f928, tts_isnull = 0x208f960, tts_mintuple = 0x0, tts_minhdr = {t_len = 0, t_self = {ip_blkid = {
        bi_hi = 0, bi_lo = 0}, ip_posid = 0}, t_tableOid = 0, t_data = 0x0}, tts_off = 0, tts_fixedTupleDescriptor = true}
(gdb)

slot中的元组数据

(gdb) p *slot->tts_values
$13 = 0
(gdb) p *slot->tts_tuple
$14 = {t_len = 56, t_self = {ip_blkid = {bi_hi = 0, bi_lo = 0}, ip_posid = 1}, t_tableOid = 286759, t_data = 0x7f05ee0c4648}
(gdb) p *slot->tts_tuple->t_data
$15 = {t_choice = {t_heap = {t_xmin = 839, t_xmax = 0, t_field3 = {t_cid = 0, t_xvac = 0}}, t_datum = {datum_len_ = 839, 
      datum_typmod = 0, datum_typeid = 0}}, t_ctid = {ip_blkid = {bi_hi = 0, bi_lo = 0}, ip_posid = 1}, t_infomask2 = 7, 
  t_infomask = 2306, t_hoff = 24 '\030', t_bits = 0x7f05ee0c465f ""}
(gdb) p *slot->tts_tuple->t_data->t_bits
$16 = 0 '\000'
(gdb) x/16ux *slot->tts_tuple->t_data->t_bits
0x0:    Cannot access memory at address 0x0
(gdb) x/16ux slot->tts_tuple->t_data->t_bits
0x7f05ee0c465f:    0x5a470b00    0x00003130    0x00000100    0x00000100
0x7f05ee0c466f:    0x00000100    0x00000100    0x00000100    0x00000100
0x7f05ee0c467f:    0x00000000    0x8f282800    0x000000da    0x40023800
0x7f05ee0c468f:    0x04200002    0x00000020    0x709fc800    0x709f9000
(gdb) x/16bx slot->tts_tuple->t_data->t_bits
0x7f05ee0c465f:    0x00    0x0b    0x47    0x5a    0x30    0x31    0x00    0x00
0x7f05ee0c4667:    0x00    0x01    0x00    0x00    0x00    0x01    0x00    0x00
(gdb) x/16bc slot->tts_tuple->t_data->t_bits
0x7f05ee0c465f:    0 '\000'    11 '\v'    71 'G'    90 'Z'    48 '0'    49 '1'    0 '\000'    0 '\000'
0x7f05ee0c4667:    0 '\000'    1 '\001'    0 '\000'    0 '\000'    0 '\000'    1 '\001'    0 '\000'    0 '\000'
(gdb) p *slot->tts_tupleDescriptor
$17 = {natts = 7, tdtypeid = 286761, tdtypmod = -1, tdhasoid = false, tdrefcount = 2, constr = 0x0, attrs = 0x7f061a3003a0}
(gdb) p *slot
$18 = {type = T_TupleTableSlot, tts_isempty = false, tts_shouldFree = false, tts_shouldFreeMin = false, tts_slow = false, 
  tts_tuple = 0x2090678, tts_tupleDescriptor = 0x7f061a300380, tts_mcxt = 0x208f270, tts_buffer = 103, tts_nvalid = 0, 
  tts_values = 0x208f928, tts_isnull = 0x208f960, tts_mintuple = 0x0, tts_minhdr = {t_len = 0, t_self = {ip_blkid = {
        bi_hi = 0, bi_lo = 0}, ip_posid = 0}, t_tableOid = 0, t_data = 0x0}, tts_off = 0, tts_fixedTupleDescriptor = true}
(gdb) p *slot->tts_values[0]
Cannot access memory at address 0x0
(gdb) p slot->tts_values[0]
$19 = 0
(gdb) x/32bc slot->tts_tuple->t_data->t_bits
0x7f05ee0c465f:    0 '\000'    11 '\v'    71 'G'    90 'Z'    48 '0'    49 '1'    0 '\000'    0 '\000'
0x7f05ee0c4667:    0 '\000'    1 '\001'    0 '\000'    0 '\000'    0 '\000'    1 '\001'    0 '\000'    0 '\000'
0x7f05ee0c466f:    0 '\000'    1 '\001'    0 '\000'    0 '\000'    0 '\000'    1 '\001'    0 '\000'    0 '\000'
0x7f05ee0c4677:    0 '\000'    1 '\001'    0 '\000'    0 '\000'    0 '\000'    1 '\001'    0 '\000'    0 '\000'
(gdb) x/32bx slot->tts_tuple->t_data->t_bits
0x7f05ee0c465f:    0x00    0x0b    0x47    0x5a    0x30    0x31    0x00    0x00
0x7f05ee0c4667:    0x00    0x01    0x00    0x00    0x00    0x01    0x00    0x00
0x7f05ee0c466f:    0x00    0x01    0x00    0x00    0x00    0x01    0x00    0x00
0x7f05ee0c4677:    0x00    0x01    0x00    0x00    0x00    0x01    0x00    0x00

拷贝元组,并放到state->memtuples中

(gdb) n
1443        COPYTUP(state, &stup, (void *) slot);
(gdb) 
1445        puttuple_common(state, &stup);
(gdb) step
puttuple_common (state=0x20933a8, tuple=0x7ffe890e0b00) at tuplesort.c:1639
1639        Assert(!LEADER(state));
(gdb) n
1641        switch (state->status)
(gdb) p state->status
$20 = TSS_INITIAL
(gdb) n
1652                if (state->memtupcount >= state->memtupsize - 1)
(gdb) p state->memtupcount
$21 = 0
(gdb) p state->memtupsize - 1
$22 = 1023
(gdb) n
1657                state->memtuples[state->memtupcount++] = *tuple;
(gdb) 
1671                if (state->bounded &&
(gdb) p state->bounded
$23 = false
(gdb) n
1688                if (state->memtupcount < state->memtupsize && !LACKMEM(state))
(gdb) 
1689                    return;
(gdb) 
1743    }
(gdb) 
tuplesort_puttupleslot (state=0x20933a8, slot=0x208f8c8) at tuplesort.c:1447
1447        MemoryContextSwitchTo(oldcontext);
(gdb) 
1448    }
(gdb) 
(gdb) p state->memtuples[0]
$25 = {tuple = 0x20993D8, datum1 = 1, isnull1 = false, tupindex = 0}

tuplesort_performsort

(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000a6ffa1 in tuplesort_begin_heap at tuplesort.c:812
    breakpoint already hit 1 time
2       breakpoint     keep y   0x0000000000a7119d in tuplesort_puttupleslot at tuplesort.c:1436
    breakpoint already hit 1 time
3       breakpoint     keep y   0x0000000000a71f45 in tuplesort_performsort at tuplesort.c:1792
(gdb) del 2
(gdb) c
Continuing.
Breakpoint 3, tuplesort_performsort (state=0x20933a8) at tuplesort.c:1792
1792        MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
(gdb)

输入参数

(gdb) p *state
$27 = {status = TSS_BUILDRUNS, nKeys = 2, randomAccess = false, bounded = false, boundUsed = false, bound = 0, 
  tuples = true, availMem = 824360, allowedMem = 4194304, maxTapes = 16, tapeRange = 15, sortcontext = 0x2093290, 
  tuplecontext = 0x20992c0, tapeset = 0x2093a00, comparetup = 0xa7525b <comparetup_heap>, 
  copytup = 0xa76247 <copytup_heap>, writetup = 0xa76de1 <writetup_heap>, readtup = 0xa76ec6 <readtup_heap>, 
  memtuples = 0x2611570, memtupcount = 26592, memtupsize = 37448, growmemtuples = false, slabAllocatorUsed = false, 
  slabMemoryBegin = 0x0, slabMemoryEnd = 0x0, slabFreeHead = 0x0, read_buffer_size = 0, lastReturnedTuple = 0x0, 
  currentRun = 2, mergeactive = 0x2093878, Level = 1, destTape = 2, tp_fib = 0x20938a0, tp_runs = 0x20938f8, 
  tp_dummy = 0x2093950, tp_tapenum = 0x20939a8, activeTapes = 0, result_tape = -1, current = 0, eof_reached = false, 
  markpos_block = 0, markpos_offset = 0, markpos_eof = false, worker = -1, shared = 0x0, nParticipants = -1, 
  tupDesc = 0x208fa40, sortKeys = 0x20937c0, onlyKey = 0x0, abbrevNext = 10, indexInfo = 0x0, estate = 0x0, heapRel = 0x0, 
  indexRel = 0x0, enforceUnique = false, high_mask = 0, low_mask = 0, max_buckets = 0, datumType = 0, datumTypeLen = 0, 
  ru_start = {tv = {tv_sec = 0, tv_usec = 0}, ru = {ru_utime = {tv_sec = 0, tv_usec = 0}, ru_stime = {tv_sec = 0, 
        tv_usec = 0}, {ru_maxrss = 0, __ru_maxrss_word = 0}, {ru_ixrss = 0, __ru_ixrss_word = 0}, {ru_idrss = 0, 
        __ru_idrss_word = 0}, {ru_isrss = 0, __ru_isrss_word = 0}, {ru_minflt = 0, __ru_minflt_word = 0}, {ru_majflt = 0, 
        __ru_majflt_word = 0}, {ru_nswap = 0, __ru_nswap_word = 0}, {ru_inblock = 0, __ru_inblock_word = 0}, {
        ru_oublock = 0, __ru_oublock_word = 0}, {ru_msgsnd = 0, __ru_msgsnd_word = 0}, {ru_msgrcv = 0, 
        __ru_msgrcv_word = 0}, {ru_nsignals = 0, __ru_nsignals_word = 0}, {ru_nvcsw = 0, __ru_nvcsw_word = 0}, {
        ru_nivcsw = 0, __ru_nivcsw_word = 0}}}}
(gdb) p state->memtupsize
$28 = 37448
(gdb)

state->status状态已切换为TSS_BUILDRUNS

(gdb) n
1795        if (trace_sort)
(gdb) 
1800        switch (state->status)
(gdb) p state->status
$29 = TSS_BUILDRUNS
(gdb)

全部刷到磁盘上,归并排序

(gdb) n
1864                dumptuples(state, true);
(gdb) 
1865                mergeruns(state);
(gdb) 
1866                state->eof_reached = false;
(gdb) 
1867                state->markpos_block = 0L;
(gdb) 
1868                state->markpos_offset = 0;
(gdb) 
1869                state->markpos_eof = false;
(gdb) 
1870                break;
(gdb) 
1878        if (trace_sort)
(gdb) 
1890        MemoryContextSwitchTo(oldcontext);
(gdb) 
1891    }
(gdb)

到此,相信大家对“怎么使用PostgreSQL的tuplesort_performsort函数”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

您可能感兴趣的文档:

--结束END--

本文标题: 怎么使用PostgreSQL的tuplesort_performsort函数

本文链接: https://www.lsjlt.com/news/63936.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

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

下载Word文档
猜你喜欢
  • oracle怎么查询当前用户所有的表
    要查询当前用户拥有的所有表,可以使用以下 sql 命令:select * from user_tables; 如何查询当前用户拥有的所有表 要查询当前用户拥有的所有表,可以使...
    99+
    2024-05-15
    oracle
  • oracle怎么备份表中数据
    oracle 表数据备份的方法包括:导出数据 (exp):将表数据导出到外部文件。导入数据 (imp):将导出文件中的数据导入表中。用户管理的备份 (umr):允许用户控制备份和恢复过程...
    99+
    2024-05-15
    oracle
  • oracle怎么做到数据实时备份
    oracle 实时备份通过持续保持数据库和事务日志的副本来实现数据保护,提供快速恢复。实现机制主要包括归档重做日志和 asm 卷管理系统。它最小化数据丢失、加快恢复时间、消除手动备份任务...
    99+
    2024-05-15
    oracle 数据丢失
  • oracle怎么查询所有的表空间
    要查询 oracle 中的所有表空间,可以使用 sql 语句 "select tablespace_name from dba_tablespaces",其中 dba_tabl...
    99+
    2024-05-15
    oracle
  • oracle怎么创建新用户并赋予权限设置
    答案:要创建 oracle 新用户,请执行以下步骤:以具有 create user 权限的用户身份登录;在 sql*plus 窗口中输入 create user identified ...
    99+
    2024-05-15
    oracle
  • oracle怎么建立新用户
    在 oracle 数据库中创建用户的方法:使用 sql*plus 连接数据库;使用 create user 语法创建新用户;根据用户需要授予权限;注销并重新登录以使更改生效。 如何在 ...
    99+
    2024-05-15
    oracle
  • oracle怎么创建新用户并赋予权限密码
    本教程详细介绍了如何使用 oracle 创建一个新用户并授予其权限:创建新用户并设置密码。授予对特定表的读写权限。授予创建序列的权限。根据需要授予其他权限。 如何使用 Oracle 创...
    99+
    2024-05-15
    oracle
  • oracle怎么查询时间段内的数据记录表
    在 oracle 数据库中查询指定时间段内的数据记录表,可以使用 between 操作符,用于比较日期或时间的范围。语法:select * from table_name wh...
    99+
    2024-05-15
    oracle
  • oracle怎么查看表的分区
    问题:如何查看 oracle 表的分区?步骤:查询数据字典视图 all_tab_partitions,指定表名。结果显示分区名称、上边界值和下边界值。 如何查看 Oracle 表的分区...
    99+
    2024-05-15
    oracle
  • oracle怎么导入dump文件
    要导入 dump 文件,请先停止 oracle 服务,然后使用 impdp 命令。步骤包括:停止 oracle 数据库服务。导航到 oracle 数据泵工具目录。使用 impdp 命令导...
    99+
    2024-05-15
    oracle
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作