As with all open source projects, the internals of the Postgres
COPY statement can be easily discovered. As one can read in the source code comments, Postgres attempts to use batch inserts by default, except in the cases where it is not possible:
- when there are any
INSTEAD OF triggers on the table.
- when the target is a partitioned table and there are any statement-level insert triggers.
- when the target is a foreign table.
- when the target has any volatile
- when there are any volatile expressions in the query
If none of the above is true, insert will happen in batches of up to 1000 rows (the default can be changed by recompiling the Postgres server).
For partitioned tables the decision to use batch inserts is made for each partition individually.
While most of the
COPY processing happens on the server, the client (
psql) responsibility is to send data from a local file one 8K buffer at a time, which is evident from the
\copy command handler source.