Bulk loading into PostgreSQL: Options and comparison
highgo.ca
highgo.ca
One other note:
> Goto solution for bulk loading into PostgreSQL is the native copy command. But one limitation with the copy command is that it requires the CSV file to be placed on the server.
You can use `COPY ... FROM STDIN` and stream the data from the client, this is basically what `/copy` does in psql.
What good do partitions do? Loading in parallel?
Swapping out a child table and dropping the old one is free in that sense, but does require an exclusive lock which can cause issues if you have long running queries.
COPY commands typically write hundreds of thousands of rows per second on a large server/cluster. It's useful to write over multiple connections, but rarely more than ~16.
https://github.com/tlocke/pg8000#copy-from-and-to-a-file
The standard API for database access in Python is DB-API 2 and it doesn't include support for COPY , so each driver may implement it differently.
There's another aspect to this, and that's the format of the file to be ingested as it can be 'text', 'CSV' or 'binary'. If you're generating the file yourself then you have a choice, but whether 'binary' is faster than 'CSV' I just don't know.
I've done it, not out of performance concerns, but because transcoding between proprietary binary formats with types is a lot saner than the alternative.
[1]: https://www.postgresql.org/docs/current/sql-copy.html#id-1.9...
The other thing to keep in mind is that text or CSV can be much more compact for data sets with many small integers or NULLs. On the other hand, the binary format is much more compact for timestamps and floating point numbers. In general, binary format has lower parsing overhead.
We're in the middle of a project in which we use file_fdw to provide an interface to CSV files which are replaced nightly, but we then also have indexed materialized views to provide faster access to the data in those files. The CSVs are only read once per day when REFRESHing the materialized views after a new set of files is dropped in.
One of the nice things file_fdw is that it allows you to create foreign tables even when the source files don't exist on the filesystem. PG only cares about the files at the moment it's trying to read them. There is one downside, though, which is that the files have to be specified via absolute path. This is something that has to be considered given the heterogeneous machine environments on which the application runs.
https://www.postgresql.org/docs/9.1/sql-set-constraints.html
You can definitely have PG ignore rows that would violate constraints by specifying "ON CONFLICT DO NOTHING"[1] as part of your INSERT statement.
If you wanted to capture those rows on the fly, one way would be to perform the load via a PL/PgSQL program and include an exception handler specific to the particular constraint violation(s) you expect to hit. But I guess then you'd have to load them one row at a time...and that's not too different from just doing that in your high-level language of choice. Also the PL/PgSQL docs specifically recommend against this idea.[2]
[1]: https://www.postgresql.org/docs/11/sql-insert.html#SQL-ON-CO...
[2]: https://www.postgresql.org/docs/11/plpgsql-control-structure...
EDIT: formatting and clarity