pgconfigurator
pgconfigurator

Table Function Scan

Appears in EXPLAIN asTable Function Scan

Reads rows from XMLTABLE / JSON_TABLE.

What it is

A Table Function Scan produces relational rows from a structured-document function such as XMLTABLE (and JSON_TABLE), turning XML/JSON into columns.

When the planner picks it

When the query uses XMLTABLE or JSON_TABLE in FROM.

Is it good or bad?

Expected for document shredding. Parsing large documents per row is the cost to watch.

In depth

XMLTABLE and JSON_TABLE

A Table Function Scan produces relational rows from a structured-document function:

  • XMLTABLE(…) — turns an XML document into columns according to an XPath / row-pattern definition.
  • JSON_TABLE(…) (PostgreSQL 17+) — does the same for JSON documents using SQL/JSON path expressions.
SELECT *
FROM JSON_TABLE(
       (SELECT doc FROM orders WHERE id = 42),
       '$.lines[*]' COLUMNS (
         sku  text PATH '$.sku',
         qty  int  PATH '$.qty'
       )
     );

The node parses the source document, walks the row pattern, and emits one row per match. It's the cleanest way to shred semi-structured data into relational rows inline.

Where the cost goes

For one document the cost is parsing it once; for a query that calls XMLTABLE / JSON_TABLE per row of a table, the cost is per-row parsing — and you pay it again every time. If the documents are large, materializing the shredded form once (into a regular table) is usually faster than calling the table function repeatedly.

Stats are limited

Like ordinary Function Scan, the planner has limited information about how many rows the table function will return. For hot paths over many documents, declaring ROWS on a wrapping PL/pgSQL function — or pre-shredding into a real table — gives the planner the figures it needs to choose well downstream.

See also