我有一个包含超过一亿个文档的庞大集合,每个文档都有一个时间戳字段(很长),其中包含事件的时间跨度。
有时我们需要清除这个集合,只维护最新的文档,比如说上个月的文档。
所以我的应用程序(Java)执行删除操作,这个操作有点慢。仔细观察该操作,我发现它正在执行COLLSCAN。
{
type: 'op',
host: 'myserver:27017',
desc: 'conn1402',
connectionId: 1402,
client: '10.101.74.5:57972',
clientMetadata: {
driver: { name: 'mongo-java-driver|sync', version: '4.8.2' },
os: {
type: 'Linux',
name: 'Linux',
architecture: 'amd64',
version: '3.10.0-1160.24.1.el7.x86_64'
},
platform: 'Java/Red Hat, Inc./1.8.0_292-b10'
},
active: true,
currentOpTime: '2024-09-27T18:21:18.043+00:00',
effectiveUsers: [ { user: 'live', db: 'live' } ],
threaded: true,
opid: 13882499,
lsid: {
id: UUID('db3c7afc-61e6-44f4-b370-8780ec9945d3'),
uid: Binary.createFromBase64('VvWgJA6DwjHnyaWi2eVO3B/hb1/6f9RI7ui47NU9J2g=', 0)
},
secs_running: Long('1577'),
microsecs_running: Long('1577944218'),
op: 'remove',
ns: 'live_time.events.rig_second_od2_1_hour_replay',
redacted: false,
command: {
q: {
timestamp: { '$gte': Long('0'), '$lt': Long('1726854900023') }
},
limit: 0
},
planSummary: 'COLLSCAN',
numYields: 92653,
locks: {
ParallelBatchWriterMode: 'r',
FeatureCompatibilityVersion: 'w',
ReplicationStateTransition: 'w',
Global: 'w',
Database: 'w',
Collection: 'w'
},
waitingForLock: false,
lockStats: {
ParallelBatchWriterMode: { acquireCount: { r: Long('92654') } },
FeatureCompatibilityVersion: { acquireCount: { w: Long('92654') } },
ReplicationStateTransition: { acquireCount: { w: Long('92654') } },
Global: { acquireCount: { w: Long('92654') } },
Database: { acquireCount: { w: Long('92654') } },
Collection: { acquireCount: { w: Long('92654') } }
},
waitingForFlowControl: false,
flowControlStats: { acquireCount: Long('92654') }
},
该集合在时间戳字段上有一个索引。
这是正常行为吗?
由于这是一个删除操作,Mongodb 选择执行 COLLSCAN,因为无论如何它都必须以物理方式删除文档,因此 IXSCAN 没有意义。我的感觉是否正确,或者我可以采取一些措施来提高净化性能?
看起来您删除了集合的主要部分。在这种情况下,COLLSCAN 是最有效的。当您需要查找(更新/删除)所有文档的一小部分时,Infex 扫描非常有用。
也许这是一个创建副本的选项,即仅选择您需要的数据,然后
$out
将其复制到新集合中,然后将整个集合与旧数据一起删除。