PostgreSQL在何处处理 sql查询之四十

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介:

接前面,看 SeqNext 函数:

复制代码
/* ----------------------------------------------------------------
 *        SeqNext
 *
 *        This is a workhorse for ExecSeqScan
 * ----------------------------------------------------------------
 */
static TupleTableSlot *
SeqNext(SeqScanState *node)
{
    HeapTuple    tuple;
    HeapScanDesc scandesc;
    EState       *estate;
    ScanDirection direction;
    TupleTableSlot *slot;

    /*
     * get information from the estate and scan state
     */
    scandesc = node->ss_currentScanDesc;
    estate = node->ps.state;
    direction = estate->es_direction;
    slot = node->ss_ScanTupleSlot;

    /*
     * get the next tuple from the table
     */
    tuple = heap_getnext(scandesc, direction);

    /*
     * save the tuple and the buffer returned to us by the access methods in
     * our scan tuple slot and return the slot.  Note: we pass 'false' because
     * tuples returned by heap_getnext() are pointers onto disk pages and were
     * not created with palloc() and so should not be pfree()'d.  Note also
     * that ExecStoreTuple will increment the refcount of the buffer; the
     * refcount will not be dropped until the tuple table slot is cleared.
     */
    if (tuple)
        ExecStoreTuple(tuple,    /* tuple to store */
                       slot,    /* slot to store in */
                       scandesc->rs_cbuf,        /* buffer associated with this
                                                 * tuple */
                       false);    /* don't pfree this pointer */
    else
        ExecClearTuple(slot);

    return slot;
}
复制代码

先来看看 tuple 的数据结构:

复制代码
/*
 * HeapTupleData is an in-memory data structure that points to a tuple.
 *
 * There are several ways in which this data structure is used:
 *
 * * Pointer to a tuple in a disk buffer: t_data points directly into the
 *     buffer (which the code had better be holding a pin on, but this is not
 *     reflected in HeapTupleData itself).
 *
 * * Pointer to nothing: t_data is NULL.  This is used as a failure indication
 *     in some functions.
 *
 * * Part of a palloc'd tuple: the HeapTupleData itself and the tuple
 *     form a single palloc'd chunk.  t_data points to the memory location
 *     immediately following the HeapTupleData struct (at offset HEAPTUPLESIZE).
 *     This is the output format of heap_form_tuple and related routines.
 *
 * * Separately allocated tuple: t_data points to a palloc'd chunk that
 *     is not adjacent to the HeapTupleData.    (This case is deprecated since
 *     it's difficult to tell apart from case #1.  It should be used only in
 *     limited contexts where the code knows that case #1 will never apply.)
 *
 * * Separately allocated minimal tuple: t_data points MINIMAL_TUPLE_OFFSET
 *     bytes before the start of a MinimalTuple.    As with the previous case,
 *     this can't be told apart from case #1 by inspection; code setting up
 *     or destroying this representation has to know what it's doing.
 *
 * t_len should always be valid, except in the pointer-to-nothing case.
 * t_self and t_tableOid should be valid if the HeapTupleData points to
 * a disk buffer, or if it represents a copy of a tuple on disk.  They
 * should be explicitly set invalid in manufactured tuples.
 */
typedef struct HeapTupleData
{
    uint32          t_len;            /* length of *t_data */
    ItemPointerData t_self;        /* SelfItemPointer */
    Oid             t_tableOid;        /* table the tuple came from */
    HeapTupleHeader t_data;        /* -> tuple header and data */
} HeapTupleData;

typedef HeapTupleData *HeapTuple;
复制代码

实际测试 ,

select id from tst04 where id>1, tuple 长度 32。

select id from tst01 where id<10 , tuple 长度 28。

运行如下查询可以看到同样的结果:

复制代码
postgres=# select pg_column_size(t) from tst01 t limit 1;
 pg_column_size 
----------------
             28
(1 row)

postgres=# select pg_column_size(t) from tst04 t limit 1;
 pg_column_size 
----------------
             32
(1 row)

postgres=# 
复制代码

也就是说,tuple 的长度包含了 附属信息的长度和字段本身内容所占的长度(integer 4字节)。

看下一层面的结构:

复制代码
/*
 * ItemPointer:
 *
 * This is a pointer to an item within a disk page of a known file
 * (for example, a cross-link from an index to its parent table).
 * blkid tells us which block, posid tells us which entry in the linp
 * (ItemIdData) array we want.
 *
 * Note: because there is an item pointer in each tuple header and index
 * tuple header on disk, it's very important not to waste space with
 * structure padding bytes.  The struct is designed to be six bytes long
 * (it contains three int16 fields) but a few compilers will pad it to
 * eight bytes unless coerced.    We apply appropriate persuasion where
 * possible, and to cope with unpersuadable compilers, we try to use
 * "SizeOfIptrData" rather than "sizeof(ItemPointerData)" when computing
 * on-disk sizes.
 */
typedef struct ItemPointerData
{
    BlockIdData ip_blkid;
    OffsetNumber ip_posid;
}

#ifdef __arm__
__attribute__((packed))            /* Appropriate whack upside the head for ARM */
#endif
ItemPointerData;
复制代码

在 ItemPointerData中,估计 ip_blkid 是块号, ip_posid是 块内的本条记录所在序号。

再下一层:

typedef struct BlockIdData
{
    uint16        bi_hi;
    uint16        bi_lo;
} BlockIdData;
复制代码
/*
 * OffsetNumber:
 *
 * this is a 1-based index into the linp (ItemIdData) array in the
 * header of each disk page.
 */
typedef uint16 OffsetNumber;
复制代码

在上面的SeqNext里,加入下列调试内容:

复制代码
...
    /*
     * get the next tuple from the table
     */
    tuple = heap_getnext(scandesc, direction);

    if (tuple)
    {
        fprintf(stderr,"tuple's length is: %d\n",(int)(tuple->t_len));

        fprintf(stderr,"tuple's block number hi is: %d...lo is %d \n",
                tuple->t_self.ip_blkid.bi_hi, tuple->t_self.ip_blkid.bi_lo);

        fprintf(stderr, "tuple's offset number is : %d\n", tuple->t_self.ip_posid);

        fprintf(stderr, "-------------------------------\n\n\n");
    }
...
复制代码

看看结果:

复制代码
postgres=# select id from tst04 where id>1;
 id 
----
  4
  3
  2
(3 rows)

postgres=# 
复制代码
复制代码
tuple's length is: 32
tuple's block number hi is: 0...lo is 0 
tuple's offset number is : 1
-------------------------------


tuple's length is: 32
tuple's block number hi is: 0...lo is 0 
tuple's offset number is : 2
-------------------------------


tuple's length is: 32
tuple's block number hi is: 0...lo is 0 
tuple's offset number is : 3
-------------------------------


tuple's length is: 32
tuple's block number hi is: 0...lo is 0 
tuple's offset number is : 4
-------------------------------
复制代码

 再看  HeapTupleData 的 t_tableoid:

先看 tst04 的 oid:

复制代码
postgres=# select oid from pg_class where relname='tst04';
  oid  
-------
 16393
(1 row)

postgres=# 
复制代码

再加入调试信息:

复制代码
    ...
/* * get the next tuple from the table */ tuple = heap_getnext(scandesc, direction); if (tuple) { fprintf(stderr,"tuple's length is: %d\n",(int)(tuple->t_len)); fprintf(stderr,"tuple's block number hi is: %d...lo is %d \n", tuple->t_self.ip_blkid.bi_hi, tuple->t_self.ip_blkid.bi_lo); fprintf(stderr, "tuple's offset number is : %d\n", tuple->t_self.ip_posid); fprintf(stderr, "tuple's table oid is: %d\n",tuple->t_tableOid); fprintf(stderr, "-------------------------------\n\n\n"); }
...
复制代码

然后,我再看运行的情况:

复制代码
postgres=# select id from tst04 where id>1;
 id 
----
  4
  3
  2
(3 rows)

postgres=# 
复制代码
复制代码
tuple's length is: 32
tuple's block number hi is: 0...lo is 0 
tuple's offset number is : 1
tuple's table oid is: 16393
-------------------------------


tuple's length is: 32
tuple's block number hi is: 0...lo is 0 
tuple's offset number is : 2
tuple's table oid is: 16393
-------------------------------


tuple's length is: 32
tuple's block number hi is: 0...lo is 0 
tuple's offset number is : 3
tuple's table oid is: 16393
-------------------------------


tuple's length is: 32
tuple's block number hi is: 0...lo is 0 
tuple's offset number is : 4
tuple's table oid is: 16393
-------------------------------
复制代码
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
1天前
|
SQL NoSQL Java
Java使用sql查询mongodb
通过使用 MongoDB Connector for BI 和 JDBC,开发者可以在 Java 中使用 SQL 语法查询 MongoDB 数据库。这种方法对于熟悉 SQL 的团队非常有帮助,能够快速实现对 MongoDB 数据的操作。同时,也需要注意到这种方法的性能和功能限制,根据具体应用场景进行选择和优化。
23 9
|
22天前
|
SQL 存储 人工智能
Vanna:开源 AI 检索生成框架,自动生成精确的 SQL 查询
Vanna 是一个开源的 Python RAG(Retrieval-Augmented Generation)框架,能够基于大型语言模型(LLMs)为数据库生成精确的 SQL 查询。Vanna 支持多种 LLMs、向量数据库和 SQL 数据库,提供高准确性查询,同时确保数据库内容安全私密,不外泄。
92 7
Vanna:开源 AI 检索生成框架,自动生成精确的 SQL 查询
|
29天前
|
SQL Java
使用java在未知表字段情况下通过sql查询信息
使用java在未知表字段情况下通过sql查询信息
36 8
|
1月前
|
SQL 安全 PHP
PHP开发中防止SQL注入的方法,包括使用参数化查询、对用户输入进行过滤和验证、使用安全的框架和库等,旨在帮助开发者有效应对SQL注入这一常见安全威胁,保障应用安全
本文深入探讨了PHP开发中防止SQL注入的方法,包括使用参数化查询、对用户输入进行过滤和验证、使用安全的框架和库等,旨在帮助开发者有效应对SQL注入这一常见安全威胁,保障应用安全。
59 4
|
1月前
|
SQL 监控 关系型数据库
SQL语句当前及历史信息查询-performance schema的使用
本文介绍了如何使用MySQL的Performance Schema来获取SQL语句的当前和历史执行信息。Performance Schema默认在MySQL 8.0中启用,可以通过查询相关表来获取详细的SQL执行信息,包括当前执行的SQL、历史执行记录和统计汇总信息,从而快速定位和解决性能瓶颈。
|
1月前
|
SQL 存储 缓存
如何优化SQL查询性能?
【10月更文挑战第28天】如何优化SQL查询性能?
151 10
|
1月前
|
SQL 关系型数据库 MySQL
|
1月前
|
SQL 关系型数据库 数据库
PostgreSQL性能飙升的秘密:这几个调优技巧让你的数据库查询速度翻倍!
【10月更文挑战第25天】本文介绍了几种有效提升 PostgreSQL 数据库查询效率的方法,包括索引优化、查询优化、配置优化和硬件优化。通过合理设计索引、编写高效 SQL 查询、调整配置参数和选择合适硬件,可以显著提高数据库性能。
366 1
|
2月前
|
SQL 数据库 开发者
功能发布-自定义SQL查询
本期主要为大家介绍ClkLog九月上线的新功能-自定义SQL查询。
|
1月前
|
SQL 关系型数据库 MySQL
mysql编写sql脚本:要求表没有主键,但是想查询没有相同值的时候才进行插入
mysql编写sql脚本:要求表没有主键,但是想查询没有相同值的时候才进行插入
35 0