expdp full=y and hope is not a migration plan. It’s how you find out at 3 a.m. that the dump ran out of
space, or the import invented a half-populated schema, or the “quick refresh” locked the source for an hour
because nobody set a consistency point.
Data Pump is the workhorse that moves Oracle data — schema refreshes, database migrations, the lift into the
cloud, the copy into a test environment. Almost every Oracle shop runs expdp and impdp; far fewer run them
deliberately, with the handful of options that turn “it seemed to work” into “the row counts match and I can
prove it.” This post is the architecture worth understanding, the flags that actually matter, the quoting trap
that eats an afternoon, and — the part that ends the argument — a lab that exports a schema, drops it, imports
it back, and asserts nothing was lost.
What Data Pump actually is
The first thing to internalize: Data Pump runs inside the database server, not on your client. When you
launch expdp, the client just starts and monitors a job; the actual reading and writing is done by server
processes, and the dump file is written to a path on the database server, referenced through a DIRECTORY
object — never a client-side path. This is the big break from the legacy exp/imp tools (which streamed
through the client and are deprecated for good reason): Data Pump is faster, parallelizable, restartable, and
runs where the data is.
That architecture has direct consequences you plan around:
- You need a
DIRECTORY.CREATE DIRECTORY dp_dir AS '/path/on/the/server'and grant read/write on it. The dump lives there, not on your laptop. - It has modes.
FULL=Y(whole database),SCHEMAS=(one or more schemas — the common one),TABLES=, andTABLESPACES=. Pick the narrowest mode that covers what you’re moving. - It can skip the dump file entirely. With
NETWORK_LINK=,impdppulls straight from a source database over a database link — no dump file, no staging, no copying gigabytes twice. For a migration into a new database this is often the cleanest path.
flowchart LR SRC["Source schema<br/>DPSHOP — 5,000 + 20,000 rows"] -->|expdp SCHEMAS=dpshop| DMP["shop.dmp<br/>in a DIRECTORY on the server"] DMP -->|impdp| RT["Back into DPSHOP<br/>lossless round trip"] DMP -->|"impdp REMAP_SCHEMA=dpshop:dpclone"| TGT["DPCLONE<br/>same rows, new name"] SRC -. "impdp NETWORK_LINK (no dump file)" .-> TGT
The flags that actually matter
Most of Data Pump’s power is in a dozen parameters. These are the ones that decide whether a migration is clean:
REMAP_SCHEMA=source:target— import the data into a different schema than it came from. This is the heart of most migrations and refreshes: exportPROD_APP, import asTEST_APP. Its siblingsREMAP_TABLESPACEandREMAP_DATAFILEdo the same for storage when the target’s layout differs.PARALLEL=n— run the job with n worker processes. Essential for anything large, but with one catch people miss: give it multiple dump files with the%Uwildcard (DUMPFILE=exp_%U.dmp) so the workers aren’t all fighting over one file.PARALLEL=8against a single dumpfile is mostly waiting.INCLUDE/EXCLUDE/QUERY— move part of the data.INCLUDE=TABLE:"IN ('ORDERS')"takes one table;EXCLUDE=STATISTICSskips stats (regather them faster on the target);QUERYexports only rows matching a predicate. These are also the parameters with the notorious quoting problem — more on that below.CONTENT=—DATA_ONLY,METADATA_ONLY, orALL. Migrate structure first and data later, or refresh data into an existing schema without touching its objects.TABLE_EXISTS_ACTION=— whatimpdpdoes when a table is already there:SKIP(the surprising default — it silently leaves existing tables alone),APPEND,TRUNCATE, orREPLACE. Getting this wrong is how a “refresh” ends up with yesterday’s data quietly untouched.FLASHBACK_TIME/FLASHBACK_SCN— export a consistent point in time. Without it, a long export of a busy database can capture different tables at different moments, and referential integrity in the dump is a coin flip.FLASHBACK_TIME=SYSTIMESTAMPcosts nothing and buys you a consistent snapshot.ENCRYPTION/ENCRYPTION_PASSWORD— the dump file is plaintext data sitting on disk. If it contains anything sensitive, encrypt it, or you’ve just made an unprotected copy of your production data — the same “least-protected copy” problem that undoes encryption at rest.VERSION=— writing a dump a lower version can import (e.g., migrating down a release). Set it when the target is older than the source; forget it and the import simply refuses the file.
A minimal, deliberate schema export and remap looks like this:
# export one schema, consistent as of now, in parallel across 4 dump files
expdp system/*** DIRECTORY=dp_dir SCHEMAS=app \
DUMPFILE=app_%U.dmp PARALLEL=4 FLASHBACK_TIME=SYSTIMESTAMP LOGFILE=exp.log
# import it into a DIFFERENT schema on the target
impdp system/*** DIRECTORY=dp_dir DUMPFILE=app_%U.dmp PARALLEL=4 \
REMAP_SCHEMA=app:app_test TABLE_EXISTS_ACTION=REPLACE LOGFILE=imp.log
The quoting trap — use a parfile
The single most common way a Data Pump command fails is the shell mangling a filter. This looks right and almost never works from a normal shell:
expdp system/*** SCHEMAS=app INCLUDE=TABLE:"IN ('ORDERS')" DIRECTORY=dp_dir DUMPFILE=x.dmp
The double quotes, single quotes, and parentheses get eaten or reinterpreted by the shell before Data Pump ever sees them. The fix that always works is a parameter file — put the parameters in a text file, where no shell touches them:
# filt.par
SCHEMAS=app
INCLUDE=TABLE:"IN ('ORDERS')"
DIRECTORY=dp_dir
DUMPFILE=orders_only.dmp
expdp system/*** parfile=filt.par
If you take one operational habit from this post: any Data Pump job with an INCLUDE, EXCLUDE, or QUERY
goes in a parfile. It’s the difference between a repeatable command and a guessing game.
Now prove it
The whole promise of a migration is that the data arrives intact. That’s checkable. Build a schema of known size — 5,000 customers and 20,000 orders — export it, drop it, and import it back:
after re-import: DPSHOP customers=5000 orders=20000
-> lossless round trip: exact same 5,000 + 20,000 rows came back.
Then the actual migration move — import into a new schema with REMAP_SCHEMA:
impdp ... REMAP_SCHEMA=dpshop:dpclone
DPCLONE customers=5000 orders=20000
-> same data, new schema name.
And a selective export — INCLUDE just one table, via a parfile — lands only that table in the target:
DPONLY tables=[ORDERS] orders=20000
-> only ORDERS came across (no CUSTOMERS). INCLUDE filtered the export exactly.
Same rows, every time, with the counts asserted rather than eyeballed. That’s a migration you can hand to a change-approval board.
Don’t take my word for it — run it. The Data Pump lab stands up an Oracle Database Free container, builds the 5,000/20,000-row
DPSHOPschema, and runs four drills:expdpthe schema, drop it andimpdpit back (asserting the row counts match),impdpwithREMAP_SCHEMAinto a new schema, and a parfile-drivenINCLUDEexport that asserts only the chosen table crosses over. If the round trip loses a row or the filter leaks a table, the run fails. It’s proven on every CI push.
What teams get wrong
- Command-line filters without a parfile.
INCLUDE/EXCLUDE/QUERYtyped at the shell get their quotes mangled. Put them in a parfile, always. PARALLELagainst one dump file. The workers serialize on the single file. UseDUMPFILE=name_%U.dmpso each worker writes its own, and match the dumpfile count toPARALLEL.- No consistency point on a busy source. A multi-minute export without
FLASHBACK_TIMEcan capture tables at different SCNs, so foreign keys in the dump don’t line up. Always setFLASHBACK_TIME=SYSTIMESTAMP(or anSCN) for anything transactional. - Trusting the default
TABLE_EXISTS_ACTION. It’sSKIP— existing tables are left as-is, so a “data refresh” into a populated schema can silently do nothing. ChooseTRUNCATE,APPEND, orREPLACEon purpose. - A plaintext dump of sensitive data. The
.dmpis readable data on disk and in whatever bucket you copy it to. Encrypt it (ENCRYPTION_PASSWORD) if it holds anything you’d protect in the database, and delete it when the move is done. - Forgetting the things that aren’t rows. Grants, stored code, and statistics need to arrive too.
Data Pump moves them by default, but people who script
CONTENT=DATA_ONLYmigrations often forget to also move privileges and to regather or import stats — and then the target is “there” but slow and half-broken. - Copying a dump when
NETWORK_LINKwould do. Exporting to a file, copying it to the target host, and importing is three steps and double the storage. For a straight database-to-database move,impdp NETWORK_LINK=pulls directly and skips the file entirely.
Frequently asked questions
What is Oracle Data Pump and how is it different from the old exp/imp?
Data Pump (the expdp and impdp utilities, introduced in Oracle 10g) is Oracle’s tool for exporting and importing data and metadata. The key difference from the legacy exp/imp tools is that Data Pump runs server-side: the client only launches and monitors the job while server processes do the work and read or write the dump file on the database host through a DIRECTORY object. This makes it substantially faster, parallelizable with the PARALLEL parameter, restartable after a failure, and able to remap schemas, tablespaces, and datafiles during import. The original exp/imp streamed through the client, cannot be parallelized, and are deprecated; new work should use Data Pump. Dump files from the two tools are not interchangeable.
Why does Data Pump need a DIRECTORY object?
Because Data Pump reads and writes dump and log files on the database server, not on the client machine, it needs a server-side location it is allowed to use, and Oracle represents that as a DIRECTORY database object mapping a name to a filesystem path. You create it with CREATE DIRECTORY dp_dir AS ’/path/on/server’ and grant READ and WRITE on it to the user running the job. This indirection is a security feature: it means a user can only write dumps to paths a DBA has explicitly sanctioned, rather than anywhere on the server filesystem. On Autonomous Database and some cloud services you use a pre-provided directory (such as DATA_PUMP_DIR) or an object-store location instead of an arbitrary path.
How do I migrate a schema to a different name with Data Pump?
Use REMAP_SCHEMA=source_schema:target_schema on the impdp command. Data Pump imports all of the source schema’s objects and data into the target schema, creating the target user if the dump was a schema-mode export (which includes the user definition). For example, impdp system/*** DIRECTORY=dp_dir DUMPFILE=app.dmp REMAP_SCHEMA=app:app_test loads the exported APP schema into APP_TEST. You can combine it with REMAP_TABLESPACE to redirect storage when the target database has a different tablespace layout, and with TABLE_EXISTS_ACTION to control what happens if objects already exist. This schema remap is the core of most refreshes and migrations between environments.
How do I export or import only some tables or rows?
Use INCLUDE, EXCLUDE, and QUERY. INCLUDE=TABLE:"IN (’ORDERS’,’CUSTOMERS’)" exports only those tables; EXCLUDE=TABLE:"=’AUDIT_LOG’" exports everything except one; EXCLUDE=STATISTICS skips optimizer statistics; and QUERY="WHERE created > DATE ’2026-01-01’" exports only matching rows. The crucial practical point is quoting: these filters contain quotes and parentheses that a shell will mangle, so put them in a parameter file (parfile) and run expdp parfile=my.par rather than typing them on the command line. A parfile passes the filter to Data Pump verbatim, which is why it is the reliable way to use any of these parameters.
How do I make a Data Pump export consistent?
By default a Data Pump export is not guaranteed to be consistent across tables: on a busy database a long-running export can read different tables at different points in time, so foreign-key relationships in the dump may not line up. To get a single consistent snapshot, set FLASHBACK_TIME=SYSTIMESTAMP (or a specific timestamp) or FLASHBACK_SCN=<scn> on the expdp job, which makes every table read as of the same system change number using undo, the same mechanism behind Flashback Query. This is essential for any transactional system and effectively free, so it should be a default habit for production exports. The database must have enough undo retention to cover the duration of the export.
How do I speed up a large Data Pump job?
Use PARALLEL=n to run the job with multiple worker processes, and give it multiple dump files so the workers do not serialize on one file, using the %U wildcard in the dumpfile name (DUMPFILE=exp_%U.dmp), ideally with the dumpfile count at least equal to the parallelism. On import you can also EXCLUDE=STATISTICS and regather stats afterward, which is often faster than importing them. For a database-to-database migration, NETWORK_LINK lets impdp pull directly from the source over a database link, avoiding the write-copy-read cost of a dump file entirely. Finally, size the DIRECTORY location and undo appropriately, and put the dump on fast storage; Data Pump is frequently I/O bound.
Can I move data directly between databases without a dump file?
Yes, with NETWORK_LINK on impdp. You create a database link from the target to the source, then run impdp with NETWORK_LINK=<link_name> and the usual SCHEMAS or FULL and REMAP parameters, and Data Pump transfers the objects and data straight over the link with no dump file written or copied. This is ideal for migrations where staging a dump would mean copying large files between hosts, and it composes with REMAP_SCHEMA and the filter parameters. The trade-offs are that it holds a connection to the source for the duration and that some data types and options behave slightly differently over a link than through a file, so test the specific objects you are moving.
Does Data Pump require a separate license?
No. Data Pump is a feature of Oracle Database at no additional license cost and is available in all editions, including Oracle Database Free, which is what makes it straightforward to practice with in a local container. The related but separate features you might layer on can have their own licensing: Advanced Security governs dump-file encryption with certain options (though ENCRYPTION_PASSWORD-based encryption is broadly available), and transportable tablespaces and some parallelism characteristics differ by edition. The core expdp/impdp workflow, including schema mode, remap, filters, network mode, and consistency, is available everywhere, so the techniques in this post apply from Free up to Exadata.
Data Pump is the connective tissue of the cloud-migration story: once you’ve chosen which migration method fits and where the database should live, Data Pump is usually how the data actually moves — into Autonomous or a new home. Do it deliberately: the right mode, a consistency point, a parfile for every filter, parallelism with real dump files, and encryption on anything sensitive. Then prove the move the way that ends the argument — with the Data Pump lab, where a schema goes out, comes back, and the row counts still match to the last row.
Have a question or some feedback?
I write here in a personal capacity and enjoy comparing notes with other Oracle folks. Say hello.
Get in touch