MongoDB: How DELETE Works

MongoDB: How the deleteOne() / deleteMany() (DELETE) Works Internally

Table of Contents



1. The Command We Will Follow

The DELETE equivalent in MongoDB is deleteOne() for a single document and deleteMany() for multiple documents. In this post we follow both commands step by step, using the students collection:

MongoDBOracle
// Delete one document
db.students.deleteOne(
  { name: "Ravi" }
)

// Delete many documents
db.students.deleteMany(
  { age: { $lt: 21 } }
)

// Delete all documents (empty filter)
db.students.deleteMany({})
-- Delete one row
DELETE FROM students
WHERE name = 'Ravi'
AND ROWNUM = 1;

-- Delete many rows
DELETE FROM students
WHERE age < 21;

-- Delete all rows
DELETE FROM students;

-- Or faster for all rows:
TRUNCATE TABLE students;

COMMIT;

The command says: find the matching document(s) and remove them from the collection. If no document matches, nothing happens and no error is raised.

Key differences from Oracle:

  • MongoDB deletes are auto-committed per operation. There is no separate COMMIT unless you use a multi-document transaction.
  • MongoDB does not have a TRUNCATE command. To remove all documents efficiently, you can use db.students.drop() (which drops the entire collection including indexes) and then recreate it, or use deleteMany({}) (which removes documents one by one and is slower for large collections).
  • Unlike Oracle, where a DELETE without a WHERE clause is common, in MongoDB you must pass an explicit empty filter {} to deleteMany() to delete all documents. This is a safety measure to prevent accidental data loss.

2. Overall Flowchart

This is the path of the delete command from the client to the acknowledgment. Like updateOne(), a delete has two major phases: a FIND phase (steps 4–6) to locate the documents, and a DELETE phase (steps 7–8) to remove them.


+----------------------------------------------+
| 1. CLIENT (mongosh / driver)                 |
|    db.students.deleteOne(                    |
|      { name: "Ravi" }                        |
|    )                                         |
+-----------------------+----------------------+
                        |  delete command (BSON over TCP)
                        v
+----------------------------------------------+
| 2. mongod: NETWORK LAYER AND SESSION         |
|    accepts the connection, creates an opid   |
+-----------------------+----------------------+
                        |
                        v
+----------------------------------------------+
| 3. AUTHORIZATION CHECK                       |   NO  ──▶ Unauthorized error (stop)
|    does the user have the remove action?     |
+-----------------------+----------------------+
                        | YES
                        v
+==============================================+
║          FIND PHASE                          ║
+==============================================+
                        |
                        v
+----------------------------------------------+
| 4. PARSE AND VALIDATE THE FILTER             |   FAIL ──▶ error (stop)
|    filter becomes a match expression tree    |        e.g. unknown operator
|    empty filter {} is valid for deleteMany   |
|    empty filter {} is NOT valid for          |
|      deleteOne (must match exactly one)      |
+-----------------------+----------------------+
                        | OK
                        v
+----------------------------------------------+
| 5. LOCK                                      |
|    intent-exclusive (IX) lock on DB and      |
|    collection                                |
+-----------------------+----------------------+
                        |
                        v
+----------------------------------------------+
| 6. QUERY PLANNER + FIND MATCHING DOCS        |   uses the same planner as find()
|    plan cache or trial run                   |   IXSCAN or COLLSCAN
|    locate the document(s) to delete          |   for deleteOne: stop after 1 match
+-----------------------+----------------------+
                        |
                        v
+==============================================+
║          DELETE PHASE                        ║
+==============================================+
                        |
                        v
+----------------------------------------------+
| 7. FOR EACH MATCHING DOCUMENT:               |
|    a) read the document from storage         |
|    b) mark the record as DELETED in the      |
|       collection B-tree (tombstone)          |
|    c) remove ALL index entries for this      |
|       document from EVERY index B-tree       |
|    d) write to journal (WAL)                 |
+-----------------------+----------------------+
                        |
                        v
+----------------------------------------------+
| 8. OPLOG ENTRY (replica set only)            |
|    write to local.oplog.rs                   |
|    op: "d", o: { _id: ... }                  |
+-----------------------+----------------------+
                        |
                        v
+----------------------------------------------+
| 9. WAIT FOR WRITE CONCERN                    |   w:1 ──▶ primary acknowledged
|    w:1 (default), w:"majority", w:0          |   w:majority ──▶ wait for secondaries
+-----------------------+----------------------+
                        |
                        v
+----------------------------------------------+
| 10. RELEASE LOCKS                            |
|     release IX lock on collection and DB     |
+-----------------------+----------------------+
                        |
                        v
+----------------------------------------------+
| 11. RESPONSE TO CLIENT                       |
|     { acknowledged: true,                    |
|       deletedCount: 1 }                      |
+-----------------------+----------------------+

No matching document?
  deletedCount: 0
  No error is raised — this is normal behavior.

Space reclamation?
  The tombstone is cleaned up later during
  WiredTiger eviction or checkpoint.

3. Step-by-Step Explanation

Step 1 — The client builds the command
mongosh turns deleteOne() or deleteMany() into a delete command document that includes the collection name and an array of delete statements. Each statement has a filter q and a limit field (limit: 1 for deleteOne(), limit: 0 for deleteMany(), where 0 means “no limit”). The command is sent to mongod immediately as a BSON message.

// What the driver actually sends for deleteOne:
{
  delete: "students",
  deletes: [
    { q: { name: "Ravi" }, limit: 1 }
  ],
  $db: "myFirstDB"
}

// What the driver sends for deleteMany:
{
  delete: "students",
  deletes: [
    { q: { age: { $lt: 21 } }, limit: 0 }
  ],
  $db: "myFirstDB"
}

Step 2 — mongod receives the request
The network layer accepts the message and creates an operation context with an opid. You can see active deletes by running db.currentOp().

Step 3 — Authorization check
MongoDB checks that the user’s roles include the remove action on myFirstDB.students. Note that the action is called remove, not delete, in MongoDB’s privilege system. If the privilege is missing, the command stops with a not authorized error.

Step 4 — Parse and validate the filter
The filter is parsed into a match expression tree, exactly like find() and the find phase of updateOne(). The same validation rules apply: unknown operators produce an error, and the query shape is extracted for the plan cache.

  • For deleteMany({}), the empty filter is valid and matches all documents.
  • For deleteOne(), the filter must be specific enough to identify the intended document. MongoDB does not reject a broad filter on deleteOne(), but it will only delete the first document it finds (which may not be deterministic without a sort).
  • If you need to delete a specific document by its _id, use deleteOne({ _id: ObjectId("...") }). This is the fastest and safest approach because the _id index is always present.

Step 5 — Take locks
MongoDB takes intent-exclusive (IX) locks on the database and the collection. These are the same locks used by insertOne() and updateOne(). They allow concurrent operations on different documents but prevent conflicting schema changes on the collection.

Step 6 — Query planner finds the matching documents
This step reuses the same query planner that find() uses (see the find() post, Section 4). MongoDB checks the plan cache for the filter’s query shape, or runs a trial of candidate plans.

  • For deleteOne(), MongoDB stops scanning as soon as it finds one matching document. If an index on name exists, the planner will likely choose an IXSCAN on that index.
  • For deleteMany(), MongoDB continues scanning until all matching documents are found. If no suitable index exists, a COLLSCAN is performed.
  • The choice of index can significantly affect delete performance. Deleting 10,000 documents with a COLLSCAN on a million-document collection is much slower than using an index that directly identifies the 10,000 documents.

Step 7 — Delete each matching document
For each document found in Step 6, MongoDB performs the following sub-steps:

  1. Read the document from the WiredTiger cache (or from disk if the page is not cached). The document is needed to identify all index entries that must be removed.
  2. Mark the record as deleted in the collection B-tree. WiredTiger does not immediately remove the record from the B-tree leaf page. Instead, it places a tombstone (a deletion marker) on the record. The space is reclaimed later during eviction or checkpoint (see Section 4 for details).
  3. Remove all index entries for this document from every index on the collection. Unlike updateOne(), where only changed fields trigger index updates, a delete must remove all index entries for the document because the document no longer exists. This includes the default _id index and any secondary indexes.
  4. Write to the journal (WAL) for crash recovery. The journal records the deletion operation so it can be replayed if the server crashes before the next checkpoint.

Step 8 — Write the oplog entry (replica set only)
In a replica set, MongoDB writes an oplog entry to local.oplog.rs. The oplog entry type is "d" (delete), and the entry contains the _id of the deleted document:

// Example oplog entry for a delete:
{
  ts: Timestamp(1700000000, 1),
  op: "d",
  ns: "myFirstDB.students",
  o: { _id: ObjectId("65a1b2c3d4e5f6a7b8c9d0e1") },
  wall: ISODate("2024-01-15T10:30:00Z")
}

Note that the oplog entry contains only the _id, not the full document. This is because secondaries only need the _id to find and delete the same document on their side. This makes delete oplog entries very compact compared to insert or replace oplog entries.

Step 9 — Wait for write concern
Same as insertOne() and updateOne(). The default w: 1 acknowledges as soon as the primary has written the data. w: "majority" waits for a majority of replica set members. j: true ensures the journal is flushed to disk.

Step 10 — Release locks
The IX locks on the collection and database are released. The deleted document is no longer visible to other operations (subject to their read concern and snapshot).

Step 11 — Send the response to the client
The response includes a single counter:

  • deletedCount: how many documents were actually deleted. If no documents matched the filter, deletedCount is 0 and no error is raised. This is different from Oracle, where a DELETE that affects 0 rows still succeeds but SQL%ROWCOUNT returns 0.

4. How the Storage Engine Handles the Delete

This is Step 7b in detail. WiredTiger uses a tombstone mechanism rather than immediately removing the record from the B-tree. This is essential for MVCC — other transactions that started before the delete may still need to read the old version of the document.


+----------------------------------------------+
| Application calls deleteOne()                |
+-----------------------+----------------------+
                        |
                        v
+----------------------------------------------+
| READ PHASE                                   |
| WiredTiger: read the document from the       |
| collection B-tree (cache or disk)            |
| The full document is needed to identify      |
| all index entries to remove                  |
+-----------------------+----------------------+
                        |
                        v
+----------------------------------------------+
| TOMBSTONE PHASE (collection B-tree)          |
|                                              |
| Before:                                      |
|   Leaf page: [docA] [docB] [docC] [docD]    |
|                          ↑                   |
|                     delete docC              |
|                                              |
| After:                                       |
|   Leaf page: [docA] [docB] [☠ docC] [docD]  |
|                          ↑                   |
|                     tombstone                |
|                                              |
| The record is NOT physically removed yet.    |
| It is marked with a deletion timestamp.      |
+-----------------------+----------------------+
                        |
                        v
+----------------------------------------------+
| INDEX CLEANUP (every index B-tree)           |
|                                              |
| For each index on the collection:            |
|   1. Find all entries pointing to docC       |
|   2. Mark each entry as deleted (tombstone)  |
|                                              |
| _id index:    remove (_id:3 → docC)         |
| age index:    remove (22 → docC)            |
| name index:   remove ("Ravi" → docC)        |
| grade index:  remove ("A" → docC)           |
+-----------------------+----------------------+
                        |
                        v
+----------------------------------------------+
| JOURNAL (WAL)                                |
| Write the delete record to the journal.      |
| Flushed to disk every 100 ms (default)       |
| or immediately if j:true.                    |
+-----------------------+----------------------+
                        |
                        v
+----------------------------------------------+
| SPACE RECLAMATION (later, background)        |
|                                              |
| During eviction or checkpoint:               |
|   1. WiredTiger checks if any active         |
|      snapshot still needs the old version    |
|   2. If no snapshot needs it, the tombstone  |
|      and the record data are removed         |
|   3. The freed space on the B-tree page      |
|      becomes available for new records       |
|                                              |
| This is NOT immediate. A large delete        |
| operation may not free disk space right away.|
+----------------------------------------------+

Key points:

  • Tombstone, not immediate removal: WiredTiger marks the record as deleted but keeps it in the B-tree until no active snapshot needs it. This is required for MVCC — a query that started before the delete must still be able to read the document.
  • Space reclamation is deferred: The physical space is reclaimed during WiredTiger’s eviction process or during a checkpoint. This means that after a large deleteMany(), the data files on disk may not shrink immediately. This is similar to Oracle, where deleted rows leave free space in blocks that is reused later but does not reduce the tablespace size.
  • Compaction: If you need to reclaim disk space after a large delete, you can run the compact command: db.runCommand({ compact: "students" }). This rewrites the collection and its indexes, removing all tombstones and freeing space. Note that compact locks the collection and is an expensive operation — run it during a maintenance window.
  • Journal: The journal records the logical delete operation (the _id of the deleted document). On crash recovery, WiredTiger replays the journal from the last checkpoint to re-apply any deletes that were in memory but not yet in the data files.
  • MVCC visibility: After the delete, new queries (with a new snapshot) will not see the deleted document. Queries that started before the delete (with an older snapshot) will still see it. This is the same read-consistency model used by Oracle’s undo-based read consistency.

Comparison with Oracle:

MongoDB (WiredTiger)Oracle
Tombstone on the B-tree recordRow marked as deleted in the data block (ITL entry updated, row flag set)
Old version retained for MVCC snapshotsOld version retained in undo segment for read consistency
Space reclaimed during eviction / checkpointSpace reused in the block when new rows are inserted (ASSM bitmap updated)
compact to reclaim disk spaceALTER TABLE ... MOVE or ALTER TABLE ... SHRINK SPACE
Data files do not shrink automaticallyDatafiles do not shrink automatically (unless auto-shrink is configured)
Journal records logical delete (by _id)Redo log records physical block changes

5. Index Cleanup During Delete

Index cleanup is one of the most expensive parts of a delete operation. Unlike updateOne(), where only changed indexed fields trigger index maintenance, a delete must remove all index entries for the document because the document no longer exists.

Example — index cleanup during a delete:


Collection: students
Indexes: { _id: 1 }, { age: 1 }, { name: 1 }, { grade: 1 }

Document to delete: { _id: 1, name: "Ravi", age: 22, grade: "A" }

Index cleanup:
  _id index:    REMOVE (1 → record)          ← always present
  age index:    REMOVE (22 → _id:1)          ← secondary index
  name index:   REMOVE ("Ravi" → _id:1)      ← secondary index
  grade index:  REMOVE ("A" → _id:1)         ← secondary index

Total index operations: 4 removals

Compare with updateOne({ $set: { grade: "A+" } }):
  _id index:    NO CHANGE
  age index:    NO CHANGE
  name index:   NO CHANGE
  grade index:  REMOVE ("A" → _id:1), INSERT ("A+" → _id:1)

Total index operations: 2 (1 removal + 1 insertion)

Key points:

  • More indexes = slower deletes: Each additional index on the collection adds one more B-tree removal per deleted document. If you have 10 indexes and delete 10,000 documents, WiredTiger must perform 100,000 index removals. This is the same principle as in Oracle, where heavily indexed tables have slower DML.
  • Multikey indexes: If the document contains an array field with a multikey index, there may be multiple index entries per document (one per array element). All of them must be removed. For example, a document with tags: ["math", "science", "history"] and a multikey index on tags has three index entries that must be removed.
  • Index entries are tombstoned, not immediately removed: Just like the collection record, index entries are marked with a tombstone and physically removed later during eviction or checkpoint.
  • Unique indexes: The unique constraint is released as soon as the tombstone is placed. Other operations can immediately insert a document with the same unique key value, even though the old record’s tombstone is still in the B-tree.

6. Replica Set Write Path

Like inserts and updates, all deletes go to the primary. Secondaries replicate by tailing the oplog.


+----------------+          +-------------------+         +-------------------+
|    CLIENT      |          |   PRIMARY (mongod) |         | SECONDARY (mongod)|
+-------+--------+          +--------+----------+         +--------+----------+
        |                            |                              |
        |  deleteOne()               |                              |
        +──────────────────────▶     |                              |
        |                            |                              |
        |                    4. Validate filter                     |
        |                    5. Take IX lock                        |
        |                    6. Find matching document(s)           |
        |                    7. Tombstone the record                |
        |                       Remove all index entries            |
        |                       Write to WT cache + journal         |
        |                    8. Write oplog entry                   |
        |                       op: "d", o: { _id: ... }           |
        |                            |                              |
        |                            |     oplog tailing            |
        |                            + ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ▶|
        |                            |                              |
        |                            |                     Replay the delete:
        |                            |                     find doc by _id
        |                            |                     tombstone the record
        |                            |                     remove index entries
        |                            |                     write to WT cache
        |                            |                              |
        |                            |◀ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─+
        |                            |     acknowledgment           |
        |                            |                              |
        |    9. Write concern        |                              |
        |    w:1 ── ack immediately  |                              |
        |    w:majority ── wait      |                              |
        |                            |                              |
        |◀───────────────────────────+                              |
        |    11. Response to client  |                              |
        |                            |                              |

Key points for deletes:

  • The oplog entry for a delete is very compact — it contains only the _id of the deleted document. This is much smaller than an insert oplog entry (which contains the full document) or a replacement update oplog entry.
  • Secondaries find the document by _id and apply the same delete. If the document does not exist on the secondary (e.g., it was already deleted by a previous operation), the secondary silently skips the operation. This is called idempotent replication.
  • If a secondary is significantly behind the primary (high replication lag), the deleted document may still be visible on the secondary for some time. This is why w: "majority" read concern is important for applications that need to ensure a deleted document is no longer visible anywhere.

7. Sharded Cluster Delete Path

In a sharded cluster, the client connects to mongos, which determines which shard(s) own the matching documents.


+----------------+         +-------------------+
|    CLIENT      |         |      mongos       |
+-------+--------+         +--------+----------+
        |                            |
        |  deleteOne()               |
        +──────────────────────▶     |
        |                            |
        |                  Which shard(s)?
        |                  Check the filter for
        |                  the shard key.
        |                            |
        |               +────────────+────────────+
        |               |                         |
        |          Shard key in              Shard key NOT
        |          the filter?               in the filter?
        |               |                         |
        |               v                         v
        |     +-------------------+     +-------------------+
        |     | TARGETED DELETE   |     | SCATTER-GATHER    |
        |     | Send to 1 shard   |     | Send to ALL shards|
        |     +-------------------+     +-------------------+
        |               |                         |
        |               v                         v
        |     +-------------------+     +-------------------+
        |     |  Shard A          |     |  Shard A, B, C... |
        |     |  Steps 4-10       |     |  Steps 4-10 on    |
        |     |  run here         |     |  each shard        |
        |     +-------------------+     +-------------------+
        |               |                         |
        |◀──────────────+─────────────────────────+
        |   mongos merges deletedCount
        |   and sends response

Key points:

  • Targeted delete: If the filter contains the shard key, mongos sends the delete only to the shard that owns the matching chunk. This is fast and efficient.
  • Scatter-gather delete: If the filter does not contain the shard key, mongos must send the delete to all shards because any shard might have matching documents. Each shard runs the delete independently, and mongos sums up the deletedCount from all shards. This is slower and puts more load on the cluster.
  • deleteOne() with scatter-gather: Even though deleteOne() deletes only one document, mongos must still contact all shards (in the worst case) because it does not know which shard has the matching document. Once one shard confirms a deletion, mongos can stop, but the initial routing is still a scatter-gather.
  • Each shard is itself a replica set, so Steps 5–10 (lock, tombstone, index cleanup, oplog, write concern) happen on that shard’s primary.

8. deleteOne vs deleteMany vs drop

AspectdeleteOne()deleteMany()drop()
Documents removedAt most 1All matching documentsAll documents (entire collection)
Internal limitlimit: 1limit: 0 (no limit)N/A (drops the namespace)
IndexesEntries removed for the deleted docEntries removed for each deleted docAll indexes are dropped entirely
Collection exists after?YesYes (even if empty)No (collection is removed)
Oplog entries1 entry (op: "d")1 entry per document (op: "d")1 entry (op: "c", command: drop)
Speed for large datasetsFast (1 doc)Slow for millions of docs (per-doc overhead)Very fast (drops files directly)
AtomicityAtomic (single document)Not atomic across documentsAtomic (collection-level)
Disk space reclaimed?Eventually (eviction / checkpoint)Eventually (eviction / checkpoint)Immediately (files deleted)
Oracle equivalentDELETE ... WHERE ... AND ROWNUM = 1DELETE FROM ... WHERE ...TRUNCATE TABLE or DROP TABLE

When to use drop() instead of deleteMany({}):

  • If you want to remove all documents from a collection and the collection has millions of documents, drop() is dramatically faster because it removes the data files directly instead of deleting documents one by one.
  • However, drop() also removes all indexes, validation rules, and the collection itself. You must recreate them if needed.
  • drop() requires the dropCollection action, not the remove action.
  • In a sharded cluster, drop() must be routed through mongos and drops the collection on all shards.

Atomicity:

  • deleteOne() is atomic at the document level. No other operation can see a partially deleted document.
  • deleteMany() is not atomic across documents. Other operations may see some documents deleted and others not yet deleted. If you need multi-document atomicity, use a multi-document transaction (MongoDB 4.0+ for replica sets, 4.2+ for sharded clusters).

9. See It Yourself

Like insertOne() and updateOne(), there is no explain() for the delete phase. However, you can use explain() on the find phase (the filter), and you can observe the delete behavior using these tools:

// 1. Run a delete and see the response
var result = db.students.deleteOne({ name: "Ravi" })
printjson(result)
// { acknowledged: true, deletedCount: 1 }

// 2. Delete with no match — no error
var result2 = db.students.deleteOne({ name: "NonExistent" })
printjson(result2)
// { acknowledged: true, deletedCount: 0 }

// 3. Explain the FIND phase of the delete (which indexes are used?)
db.students.explain("executionStats").deleteMany(
  { age: { $lt: 21 } }
)
// Look at winningPlan to see if IXSCAN or COLLSCAN is used for the filter

// 4. Check the oplog entry (replica set)
use local
db.oplog.rs.find({ ns: "myFirstDB.students", op: "d" })
  .sort({ ts: -1 }).limit(1)
// You will see: { op: "d", o: { _id: ObjectId("...") } }

// 5. Check current operations while running a large deleteMany
// In another mongosh session:
db.currentOp({ "command.delete": "students" })

// 6. Check write metrics
db.serverStatus().opcounters
// { insert: 1523, query: 4821, update: 345, delete: 128, ... }

// 7. Enable profiling to see slow deletes
db.setProfilingLevel(2)
db.students.deleteMany({ age: { $lt: 21 } })
db.system.profile.find({ op: "remove" }).sort({ ts: -1 }).limit(1)
db.setProfilingLevel(0)
// Note: in the profiler, deletes appear as op: "remove"

// 8. Check disk space after a large delete
db.students.stats()
// Look at "size" (data size) and "storageSize" (allocated space)
// After a large delete, storageSize may be much larger than size
// because tombstones have not been reclaimed yet.

// 9. Reclaim space with compact (maintenance window only!)
db.runCommand({ compact: "students" })
// This rewrites the collection and indexes, removing tombstones.
// The collection is locked during compaction.

// 10. Compare deleteMany vs drop for removing all documents
// Slow: deletes one by one
db.students.deleteMany({})

// Fast: drops the entire collection
db.students.drop()
// Remember: drop() removes indexes and the collection itself!

Key fields in the oplog entry for a delete:

FieldWhat It Tells You
tsTimestamp of the operation
op"d" for delete
nsNamespace: myFirstDB.students
oContains only the _id of the deleted document (very compact)
wallWall clock time when the operation occurred

10. Oracle Terms Comparison

For DBAs coming from Oracle, here is a side-by-side mapping of every delete step:

MongoDBOracle
Client sends the delete commandClient sends the DELETE SQL statement
Authorization check (remove action)Privilege check (DELETE on the table)
Parse filter (query shape)Parse (syntax + semantic check on WHERE)
Query planner finds matching docs (IXSCAN / COLLSCAN)Optimizer chooses access path for WHERE (INDEX RANGE SCAN / FULL TABLE SCAN)
Intent-exclusive (IX) lock on collectionRow-level exclusive lock (TX) + table-level row exclusive (RX/SX)
Tombstone on B-tree recordRow marked as deleted in data block (ITL entry, row flag)
Remove ALL index entries for the documentRemove index entries for all indexed columns of the row
Old version retained for MVCC snapshotsOld version retained in undo segment for read consistency
Journal (WAL) for crash recoveryRedo log for crash recovery
Oplog entry (op: "d", only _id)Redo log record (physical block change) + undo record
Secondaries replay the delete by _idStandby applies redo logs (Data Guard Redo Apply)
Auto-commit (single-document atomic)Explicit COMMIT required
Write concern w: "majority"Data Guard SYNC transport
Space reclaimed during eviction / checkpointSpace reused in block (ASSM bitmap); HWM does not move
compact to reclaim disk spaceALTER TABLE ... SHRINK SPACE or ALTER TABLE ... MOVE
deleteMany({}) — slow for large collectionsDELETE FROM table — slow, generates lots of undo and redo
drop() — fast, removes files directlyTRUNCATE TABLE — fast, resets HWM, minimal redo
deletedCountSQL%ROWCOUNT
No error when 0 documents matchNo error when 0 rows match (SQL%ROWCOUNT = 0)
Multi-document transaction (4.0+)Standard transaction (BEGIN … COMMIT / ROLLBACK)
explain() on the filterEXPLAIN PLAN on the WHERE clause
Profiler shows op: "remove"AWR / ASH / V$SQL with command_type = 7 (DELETE)
Caution: Your use of any information or materials on this website is entirely at your own risk. It is provided for educational purposes only. It has been tested internally, however, we do not guarantee that it will work for you. Ensure that you run it in your test environment before using.
Thank you
Rajasekhar Amudala