@ -3,42 +3,40 @@
< TITLE > How PostgreSQL Processes a Query< / TITLE >
< / HEAD >
< BODY BGCOLOR = "#FFFFFF" TEXT = "#000000" LINK = "#FF0000" VLINK = "#A00000" ALINK = "#0000FF" >
< H1 ALIGN = CENTER >
< H1 >
How PostgreSQL Processes a Query
< / H1 >
< H2 ALIGN = CENTER >
< H2 >
by Bruce Momjian
< / H2 >
< P >
< CENTER >
< IMG src = "flow.gif" usemap = "#flowmap" alt = "flowchart" border = 0 >
< / CENTER >
< MAP name = "flowmap" >
< AREA COORDS = "125,35,245,65" HREF = "backend_dirs.html#main" >
< AREA COORDS = "125,100,245,125" HREF = "backend_dirs.html#postmaster" >
< AREA COORDS = "325,65,450,95" HREF = "backend_dirs.html#libpq" >
< AREA COORDS = "125,160,245,190" HREF = "backend_dirs.html#tcop" >
< AREA COORDS = "325,160,450,190" HREF = "backend_dirs.html#tcop" >
< AREA COORDS = "125,240,245,265" HREF = "backend_dirs.html#parser" >
< AREA COORDS = "125,300,250,330" HREF = "backend_dirs.html#tcop" >
< AREA COORDS = "125,360,250,390" HREF = "backend_dirs.html#optimizer" >
< AREA COORDS = "125,425,245,455" HREF = "backend_dirs.html#optimizer/plan" >
< AREA COORDS = "125,490,245,515" HREF = "backend_dirs.html#executor" >
< AREA COORDS = "325,300,450,330" HREF = "backend_dirs.html#commands" >
< AREA COORDS = "75,575,195,605" HREF = "backend_dirs.html#utils" >
< AREA COORDS = "235,575,360,605" HREF = "backend_dirs.html#catalog" >
< AREA COORDS = "405,575,525,605" HREF = "backend_dirs.html#storage" >
< AREA COORDS = "155,635,275,665" HREF = "backend_dirs.html#access" >
< AREA COORDS = "325,635,450,665" HREF = "backend_dirs.html#nodes" >
< AREA COORDS = "75,705,200,730" HREF = "backend_dirs.html#bootstrap" >
< IMG src = "flow.gif" usemap = "#flowmap" alt = "flowchart" >
< MAP name = "flowmap" id = "flowmap" >
< AREA coords = "125,35,245,65" HREF = "backend_dirs.html#main" alt = "main" > < / AREA >
< AREA coords = "125,100,245,125" HREF = "backend_dirs.html#postmaster" alt = "postmaster" > < / AREA >
< AREA coords = "325,65,450,95" HREF = "backend_dirs.html#libpq" alt = "libpq" > < / AREA >
< AREA coords = "125,160,245,190" HREF = "backend_dirs.html#tcop" alt = "tcop" > < / AREA >
< AREA coords = "325,160,450,190" HREF = "backend_dirs.html#tcop" alt = "tcop" > < / AREA >
< AREA coords = "125,240,245,265" HREF = "backend_dirs.html#parser" alt = "parser" > < / AREA >
< AREA coords = "125,300,250,330" HREF = "backend_dirs.html#tcop" alt = "tcop" > < / AREA >
< AREA coords = "125,360,250,390" HREF = "backend_dirs.html#optimizer" alt = "optimizer" > < / AREA >
< AREA coords = "125,425,245,455" HREF = "backend_dirs.html#optimizer_plan" alt = "plan" > < / AREA >
< AREA coords = "125,490,245,515" HREF = "backend_dirs.html#executor" alt = "executor" > < / AREA >
< AREA coords = "325,300,450,330" HREF = "backend_dirs.html#commands" alt = "commands" > < / AREA >
< AREA coords = "75,575,195,605" HREF = "backend_dirs.html#utils" alt = "utils" > < / AREA >
< AREA coords = "235,575,360,605" HREF = "backend_dirs.html#catalog" alt = "catalog" > < / AREA >
< AREA coords = "405,575,525,605" HREF = "backend_dirs.html#storage" alt = "storage" > < / AREA >
< AREA coords = "155,635,275,665" HREF = "backend_dirs.html#access" alt = "access" > < / AREA >
< AREA coords = "325,635,450,665" HREF = "backend_dirs.html#nodes" alt = "nodes" > < / AREA >
< AREA coords = "75,705,200,730" HREF = "backend_dirs.html#bootstrap" alt = "bootstrap" > < / AREA >
< / MAP >
< CENTER > < EM >
< EM >
Click on an item to see more detail or look at the full
< A HREF = "backend_dirs.html" > index.< / A >
< / EM > < / CENTER >
< / EM >
< BR >
< BR >
< / P >
< P >
A query comes to the backend via data packets arriving through TCP/IP or
@ -49,13 +47,13 @@ into tokens(words). The parser uses <A
HREF="../../backend/parser/gram.y">gram.y< / A > and the tokens to identify
the query type, and load the proper query-specific structure, like < A
HREF="../../include/nodes/parsenodes.h">CreateStmt< / A > or < A
HREF="../../include/nodes/parsenodes.h">SelectStmt.< / A > < P >
HREF="../../include/nodes/parsenodes.h">SelectStmt.< / A > < / P > < P >
The query is then identified as a < I > Utility< / I > query or a more complex
query. A < I > Utility< / I > query is processed by a query-specific function
in < A HREF = "../../backend/commands" > commands.< / A > A complex query, like
< I > SELECT, UPDATE,< / I > and < I > DELETE< / I > requires much more handling.< P >
< I > SELECT, UPDATE,< / I > and < I > DELETE< / I > requires much more handling.< / P > < P >
The parser takes a complex query, and creates a
@ -67,7 +65,7 @@ Each table referenced in the query is represented by a <A
HREF="../../include/nodes/parsenodes.h"> RangeTableEntry,< / A > and they
are linked together to form the < I > range table< / I > of the query, which
is generated by < A HREF = "../../backend/parser/parse_clause.c" >
transformFromClause().< / A > Query.rtable holds the query's range table.< P >
transformFromClause().< / A > Query.rtable holds the query's range table.< / P > < P >
Certain queries, like < I > SELECT,< / I > return columns of data. Other
@ -78,16 +76,16 @@ placed in <A HREF="../../include/nodes/parsenodes.h">target list
entries,< / A > and linked together to make up the < I > target list< / I > of
the query. The target list is stored in Query.targetList, which is
generated by < A
HREF="../../backend/parser/parse_target.c">transformTargetList().< / A > < P >
HREF="../../backend/parser/parse_target.c">transformTargetList().< / A > < / P > < P >
Other query elements, like aggregates(< I > SUM()< / I > ), < I > GROUP BY,< / I >
and < I > ORDER BY< / I > are also stored in their own Query fields.< P >
and < I > ORDER BY< / I > are also stored in their own Query fields.< / P > < P >
The next step is for the Query to be modified by any < I > VIEWS< / I > or
< I > RULES< / I > that may apply to the query. This is performed by the < A
HREF="../../backend/rewrite">rewrite< / A > system.< P >
HREF="../../backend/rewrite">rewrite< / A > system.< / P > < P >
The < A HREF = "../../backend/optimizer" > optimizer< / A > takes the Query
@ -96,18 +94,17 @@ HREF="../../include/nodes/plannodes.h">Plan,</A> which contains the
operations to be performed to execute the query. The < A
HREF="../../backend/optimizer/path">path< / A > module determines the best
table join order and join type of each table in the RangeTable, using
Query.qual(< I > WHERE< / I > clause) to consider optimal index usage.< P >
Query.qual(< I > WHERE< / I > clause) to consider optimal index usage.< / P > < P >
The Plan is then passed to the < A
HREF="../../backend/executor">executor< / A > for execution, and the result
returned to the client. The Plan actually as set of nodes, arranged in
a tree structure with a top-level node, and various sub-nodes as
children.< P >
children.< / P > < P >
There are many other modules that support this basic functionality. They
can be accessed by clicking on the flowchart.< P >
can be accessed by clicking on the flowchart.< / P >
< HR > < P >
@ -117,19 +114,20 @@ Another area of interest is the shared memory area, which contains data
accessable to all backends. It has recently used data/index blocks,
locks, backend process information, and lookup tables for these
structures:
< / P >
< UL >
< LI > ShmemIndex - lookup shared memory addresses using structure names
< LI > ShmemIndex - lookup shared memory addresses using structure names< / LI >
< LI > < A HREF = "../../include/storage/buf_internals.h" > Buffer
Descriptor< / A > - control header for buffer cache block
Descriptor< / A > - control header for buffer cache block< / LI >
< LI > < A HREF = "../../include/storage/buf_internals.h" > Buffer Block< / A > -
data/index buffer cache block
data/index buffer cache block< / LI >
< LI > Shared Buffer Lookup Table - lookup of buffer cache block addresses
using table name and block number(< A
HREF="../../include/storage/buf_internals.h"> BufferTag< / A > )
HREF="../../include/storage/buf_internals.h"> BufferTag< / A > )< / LI >
< LI > MultiLevelLockTable (ctl) - control structure for each locking
method. Currently, only multi-level locking is used(< A
HREF="../../include/storage/lock.h">LOCKMETHODCTL< / A > ).
HREF="../../include/storage/lock.h">LOCKMETHODCTL< / A > ).< / LI >
< LI > MultiLevelLockTable (lock hash) - the < A
HREF="../../include/storage/lock.h">LOCK< / A > structure, looked up using
relation, database object ids(< A
@ -137,31 +135,29 @@ HREF="../../include/storage/lock.h">LOCKTAG)</A>. The lock table
structure contains the lock modes(read/write or shared/exclusive) and
circular linked list of backends (< A
HREF="../../include/storage/proc.h">PROC< / A > structure pointers) waiting
on the lock.
on the lock.< / LI >
< LI > MultiLevelLockTable (xid hash) - lookup of LOCK structure address
using transaction id, LOCK address. It is used to quickly check if the
current transaction already has any locks on a table, rather than having
to search through all the held locks. It also stores the modes
(read/write) of the locks held by the current transaction. The returned
< A HREF = "../../include/storage/lock.h" > XIDLookupEnt< / A > structure also
contains a pointer to the backend's PROC.lockQueue.
contains a pointer to the backend's PROC.lockQueue.< / LI >
< LI > < A HREF = "../../include/storage/proc.h" > Proc Header< / A > - information
about each backend, including locks held/waiting, indexed by process id
about each backend, including locks held/waiting, indexed by process id< / LI >
< / UL >
Each data structure is created by calling < A
< P > Each data structure is created by calling < A
HREF="../../backend/storage/ipc/shmem.c">ShmemInitStruct(),< / A > and the
lookups are created by < A
HREF="../../backend/storage/ipc/shmem.c">ShmemInitHash().< / A > < P >
HREF="../../backend/storage/ipc/shmem.c">ShmemInitHash().< / A > < / P >
< HR SIZE = "2" NOSHADE >
< HR >
< SMALL >
< ADDRESS >
Maintainer: Bruce Momjian (< A
HREF="mailto:pgman@candle.pha.pa.us">pgman@candle.pha.pa.us< / A > )< BR >
Last updated: Mon Aug 10 10:48:06 EDT 1998
< / ADDRESS >
< / SMALL >
< / BODY >
< / HTML >