PostgreSQL Source Code interpretation (89)-query statement # 74 (SeqNext function # 2)
Sk_flags & SK_ISNULL)\ {\ (result) = false;\ break \}\ _ _ atp = heap_getattr ((tuple),\ _ cur_keys- > sk_attno,\ (tupdesc),\ & _ _ isnull) \ if (_ _ isnull)\ {\ (result) = false;\ break \}\ _ _ test = FunctionCall2Coll (& _ cur_keys- > sk_func,\ _ _ cur_keys- > sk_collation,\ _ _ atp, _ _ cur_keys- > sk_argument) \\ if (! DatumGetBool (_ _ test))\ {\ (result) = false;\ break;\}\} while (0) 3. Tracking analysis
The test script is as follows
Testdb=# explain select dw.*,grjf.grbh,grjf.xm,grjf.ny,grjf.je testdb-# from t_dwxx dw,lateral (select gr.grbh,gr.xm,jf.ny Jf.je testdb (# from t_grxx gr inner join t_jfxx jftestdb (# on gr.dwbh = dw.dwbh testdb (# and gr.grbh = jf.grbh) grjftestdb-# order by dw.dwbh QUERY PLAN -Sort (cost=20070.93..20320.93 rows=100000 width=47) Sort Key: dw.dwbh-> Hash Join (cost=3754.00..8689.61 rows=100000 width=47) Hash Cond: (gr.dwbh):: text = (dw.dwbh):: text)-> Hash Join (cost=3465.00..8138.00 rows=100000 width=31) Hash Cond: (jf.grbh):: text = gr.grbh:: text)-> Seq Scan on t_jfxx jf (cost=0.00..1637.00 rows=100000 width=20)-> Hash (cost=1726.00..1726.00 rows=100000 width=16)-> Seq Scan on t_grxx gr (cost=0.00..1726.00 rows=100000 width=16)-> Hash (cost=164.00..164.00 rows=10000 width=20) -> Seq Scan on t_dwxx dw (cost=0.00..164.00 rows=10000 width=20) (11 rows)
Start gdb, set breakpoints, and enter heap_getnext
(gdb) b heap_getnextBreakpoint 1 at 0x4de01f: file heapam.c, line 1841. (gdb) cContinuing.Breakpoint 1, heap_getnext (scan=0x2aadc18, direction=ForwardScanDirection) at heapam.c:18411841 if (scan- > rs_pageatatime)
Check the input parameters, notice that rs_pageatatime = true, query using page-at-a-time mode
(gdb) p * scan$1 = {rs_rd = 0x7efdb8f2dfd8, rs_snapshot = 0x2a2a6d0, rs_nkeys = 0, rs_key = 0x0, rs_bitmapscan = false, rs_samplescan = false, rs_pageatatime = true, rs_allow_strat = true, rs_allow_sync = true, rs_temp_snap = false, rs_nblocks = 726, rs_startblock = 0, rs_numblocks = 4294967295, rs_strategy = 0x0, rs_syncscan = false, rs_inited = false, rs_ctup = {t_len = 2139062143 T_self = {ip_blkid = {bi_hi = 65535, bi_lo = 65535}, ip_posid = 0}, t_tableOid = 16742, t_data = 0x0}, rs_cblock = 4294967295, rs_cbuf = 0, rs_parallel = 0x0, rs_cindex = 2139062143, rs_ntuples = 2139062143, rs_vistuples = {32639}}
Enter the heapgettup_pagemode function
(gdb) n1842 heapgettup_pagemode (scan, direction, (gdb) stepheapgettup_pagemode (scan=0x2aadc18, dir=ForwardScanDirection, nkeys=0, key=0x0) at heapam.c:794794 HeapTuple tuple = & (scan- > rs_ctup); (gdb)
Heapgettup_pagemode- > variable assignment, note that tuple is still a "wild" pointer; p scan- > rs_inited = false has not been initialized
794 HeapTuple tuple = & (scan- > rs_ctup); (gdb) n795 bool backward = ScanDirectionIsBackward (dir); (gdb) p * tuple$2 = {t_len = 2139062143, t_self = {ip_blkid = {bi_hi = 65535, bi_lo = 65535}, ip_posid = 0}, t_tableOid = 16742, t_data = 0x0} (gdb) n808 if (ScanDirectionIsForward (dir) (gdb) p scan- > rs_inited$3 = false
Heapgettup_pagemode- > non-parallel scan, page = scan- > rs_startblock (i.e. page = 0)
(gdb) n815 if (scan- > rs_nblocks = = 0 | | scan- > rs_numblocks = = 0) (gdb) n821 if (scan- > rs_parallel! = NULL) (gdb) 836 page = scan- > rs_startblock; / * first page * / (gdb)
Enter heapgetpage
(gdb) n837 heapgetpage (scan, page); (gdb) stepheapgetpage (scan=0x2aadc18, page=0) at heapam.c:362362 Assert (page)
< scan->Rs_nblocks)
Heapgetpage- > check validation & read page
362Assert (page
< scan->Rs_nblocks); (gdb) n365 if (BufferIsValid (scan- > rs_cbuf)) (gdb) p scan- > rs_cbuf$4 = 0 (gdb) n376 CHECK_FOR_INTERRUPTS (); (gdb) 379 scan- > rs_cbuf = ReadBufferExtended (scan- > rs_rd, MAIN_FORKNUM, page, (gdb) 381scan- > rs_cblock = page; (gdb) 383if (! scan- > rs_pageatatime)
Heapgetpage- > rs_cbuf is 0 for 346/rs_cblock
(gdb) p scan- > rs_cbuf$5 = 346 (gdb) p scan- > rs_cblock$6 = 0
Heapgetpage- > page-at-a-time mode read, variable assignment, lock buffer
(gdb) n386 buffer = scan- > rs_cbuf; (gdb) n386 buffer = scan- > rs_cbuf; (gdb) 387 snapshot = scan- > rs_snapshot; (gdb) 392heap_page_prune_opt (scan- > rs_rd, buffer); (gdb) 399 LockBuffer (buffer, BUFFER_LOCK_SHARE); (gdb) p buffer$7 = 346
Heapgetpage- > get page, check whether the snapshot is too old, and get the number of rows
(gdb) n401 dp = BufferGetPage (buffer); (gdb) 402 TestForOldSnapshot (snapshot, scan- > rs_rd, dp); (gdb) p dp$8 = (Page) 0x7efda4b7ac00 "\ 001" (gdb) n403 lines = PageGetMaxOffsetNumber (dp); (gdb) 404 ntup = 0; (gdb) p lines$11 = 158
Heapgetpage- > verify visibility
(gdb) n426 all_visible = PageIsAllVisible (dp) & &! snapshot- > takenDuringRecovery; (gdb) 428 for (lineoff = FirstOffsetNumber, lpp = PageGetItemId (dp, lineoff); (gdb) p all_visible$12 = false (gdb) n429 lineoff rs_rd); (gdb) 438 loctup.t_data = (HeapTupleHeader) PageGetItem ((Page) dp, lpp); (gdb) 439 loctup.t_len = ItemIdGetLength (lpp) (gdb) 440 ItemPointerSet (& (loctup.t_self), page, lineoff); (gdb) 442 if (all_visible) (gdb) 445 valid = HeapTupleSatisfiesVisibility (& loctup, snapshot, buffer); (gdb) 447 CheckForSerializableConflictOut (valid, scan- > rs_rd, & loctup, (gdb) 450 if (valid) (gdb) 451 scan- > rs_ vistures [ntup + +] = lineoff (gdb) 430 lineoff++, lpp++) (gdb).
Heapgettup_pagemode- > exit heapgetpage, return to heapgettup_pagemode, initialize lineindex to 0, set rs_inited to T
(gdb) finishRun till exit from # 0 heapgetpage (scan=0x2aadc18, page=0) at heapam.c:430heapgettup_pagemode (scan=0x2aadc18, dir=ForwardScanDirection, nkeys=0, key=0x0) at heapam.c:838838 lineindex = 0; (gdb) n839 scan- > rs_inited = true; (gdb) 848 dp = BufferGetPage (scan- > rs_cbuf)
Heapgettup_pagemode- > get page to verify whether the snapshot is too old
(gdb) n849 TestForOldSnapshot (scan- > rs_snapshot, scan- > rs_rd, dp); (gdb) p dp$18 = (Page) 0x7efda4b7ac00 "\ 001"
Heapgettup_pagemode- > count the number of Item and start the loop
(gdb) n850 lines = scan- > rs_ntuples; (gdb) 853 linesleft = lines-lineindex; (gdb) 948 while (linesleft > 0) (gdb) p lines$19 = 158 (gdb) p linesleft$20 = 158 (gdb)
Heapgettup_pagemode- > get Item offset (lineoff) and ItemId
(gdb) p lineoff$21 = 1 (gdb) p lpp$22 = (ItemId) 0x7efda4b7ac18 (gdb) p * lpp$23 = {lp_off = 8152, lp_flags = 1, lp_len = 40}
Heapgettup_pagemode- > assigns values to variables in tuple, and ItemPointer is the pointer to the ItemPointerData structure
(gdb) n954 tuple- > t_data = (HeapTupleHeader) PageGetItem ((Page) dp, lpp); (gdb) 955 tuple- > t_len = ItemIdGetLength (lpp); (gdb) 956 ItemPointerSet (& (tuple- > t_self), page, lineoff) (gdb) 961 if (key! = NULL) (gdb) p * tuple- > t_data$26 = {t_choice = {t_heap = {t_xmin = 862, t_xmax = 0, t_field3 = {t_cid = 0, t_xvac = 0}}, t_datum = {datum_len_ = 862, datum_typmod = 0, datum_typeid = 0}}, t_ctid = {ip_blkid = {bi_hi = 0, bi_lo = 0}, ip_posid = 1} T_infomask2 = 5, t_infomask = 2306, t_hoff = 24'\ 030mm, t_bits = 0x7efda4b7cbef "} (gdb) p tuple- > t_len$28 = 40 (gdb) p tuple- > t_self$29 = {ip_blkid = {bi_hi = 0, bi_lo = 0}, ip_posid = 1}
Heapgettup_pagemode- > set scan- > rs_cindex, return
(gdb) n975 scan- > rs_cindex = lineindex; (gdb) n976 return; (gdb) p scan- > rs_cindex $30 = 0
Back to heap_getnext
(gdb) heap_getnext (scan=0x2aadc18, direction=ForwardScanDirection) at heapam.c:18471847 if (scan- > rs_ctup.t_data = = NULL)
Return the obtained tuple
1847 if (scan- > rs_ctup.t_data = = NULL) (gdb) n1859 pgstat_count_heap_getnext (scan- > rs_rd); (gdb) 1861 return & (scan- > rs_ctup); (gdb) p scan- > rs_ctup$31 = {t_len = 40, t_self = {ip_blkid = {bi_hi = 0, bi_lo = 0}, ip_posid = 1}, t_tableOid = 16742, t_data = 0x7efda4b7cbd8}
Finish the first call and enter the function again
(gdb) cContinuing.Breakpoint 1, heap_getnext (scan=0x2aadc18, direction=ForwardScanDirection) at heapam.c:18411841 if (scan- > rs_pageatatime) (gdb) n1842 heapgettup_pagemode (scan, direction, (gdb) stepheapgettup_pagemode (scan=0x2aadc18, dir=ForwardScanDirection, nkeys=0, key=0x0) at heapam.c:794794 HeapTuple tuple = & (scan- > rs_ctup); (gdb) n795 bool backward = ScanDirectionIsBackward (dir) (gdb) 808 if (ScanDirectionIsForward (dir)) (gdb) 810 if (! scan- > rs_inited) (gdb) 844 page = scan- > rs_cblock; / * current page * /
Check the input parameter scan, which is different from the previous one. It stores some information returned by the last call, such as rs_vistuples, etc.
(gdb) p * scan$32 = {rs_rd = 0x7efdb8f2dfd8, rs_snapshot = 0x2a2a6d0, rs_nkeys = 0, rs_key = 0x0, rs_bitmapscan = false, rs_samplescan = false, rs_pageatatime = true, rs_allow_strat = true, rs_allow_sync = true, rs_temp_snap = false, rs_nblocks = 726, rs_startblock = 0, rs_numblocks = 4294967295, rs_strategy = 0x0, rs_syncscan = false, rs_inited = true, rs_ctup = {t_len = 40 T_self = {ip_blkid = {bi_hi = 0, bi_lo = 0}, ip_posid = 1}, t_tableOid = 16742, t_data = 0x7efda4b7cbd8}, rs_cblock = 0, rs_cbuf = 346, rs_parallel = 0x0, rs_cindex = 0, rs_ntuples = 158,rs_vistuples = {1,2,3,4,5,7,8,9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151 152, 153, 154, 155, 156, 157, 158, 32639}}
DONE!
IV. Reference materials
Analysis of PostgreSQL Page Page structure (1)-Foundation
PostgreSQL Page page structure parsing (2)-header and row data pointer
PostgreSQL Page page structure parsing (3)-row data