Docs Menu

๊ณ„ํš ๊ฒฐ๊ณผ ์„ค๋ช… ํ•ด์„

์ด ํŽ˜์ด์ง€์˜ ๋‚ด์šฉ

๊ฒฐ๊ณผ ์„ค๋ช…์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ๋‹ค์Œ ์ •๋ณด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ฟผ๋ฆฌ๋ฅผ ์™„๋ฃŒํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฐ ์‹œ๊ฐ„

  • ์ฟผ๋ฆฌ๊ฐ€ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€

  • ์ฟผ๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์Šค์บ”ํ•œ ๋ฌธ์„œ ๋ฐ ์ธ๋ฑ์Šค ํ‚ค์˜ ์ˆ˜

์ฐธ๊ณ 

์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ๊ณ„ํš ๊ฒฐ๊ณผ ์„ค๋ช…์€ MongoDB ๋ฒ„์ „์— ๋”ฐ๋ผ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

cursor.explain("executionStats") ๋ฐ db.collection.explain("executionStats") ๋ฉ”์„œ๋“œ๋Š” ์ฟผ๋ฆฌ ์„ฑ๋Šฅ์— ๋Œ€ํ•œ ํ†ต๊ณ„๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํ†ต๊ณ„๋Š” ์ฟผ๋ฆฌ์—์„œ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์—ฌ๋ถ€์™€ ๋ฐฉ๋ฒ•์„ ์ธก์ •ํ•˜๋Š” ๋ฐ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ db.collection.explain()๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

MongoDB Compass ๋Š” ์ฟผ๋ฆฌ ์„ฑ๋Šฅ์— ๋Œ€ํ•œ ํ†ต๊ณ„๋ฅผ ํ‘œ์‹œํ•˜๋Š” Explain Plan ํƒญ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํ†ต๊ณ„๋Š” ์ฟผ๋ฆฌ ์—์„œ ์ธ๋ฑ์Šค ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์—ฌ๋ถ€์™€ ๋ฐฉ๋ฒ•์„ ์ธก์ •ํ•˜๋Š” ๋ฐ ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ๋ฌธ์„œ๊ฐ€ ํฌํ•จ๋œ inventory ์ปฌ๋ ‰์…˜์„ ์ƒ๊ฐํ•ด ๋ณด์„ธ์š”.

{ "_id" : 1, "item" : "f1", type: "food", quantity: 500 }
{ "_id" : 2, "item" : "f2", type: "food", quantity: 100 }
{ "_id" : 3, "item" : "p1", type: "paper", quantity: 200 }
{ "_id" : 4, "item" : "p2", type: "paper", quantity: 150 }
{ "_id" : 5, "item" : "f3", type: "food", quantity: 300 }
{ "_id" : 6, "item" : "t1", type: "toys", quantity: 500 }
{ "_id" : 7, "item" : "a1", type: "apparel", quantity: 250 }
{ "_id" : 8, "item" : "a2", type: "apparel", quantity: 400 }
{ "_id" : 9, "item" : "t2", type: "toys", quantity: 50 }
{ "_id" : 10, "item" : "f4", type: "food", quantity: 75 }

ํ•ด๋‹น ๋ฌธ์„œ๋Š” MongoDB Compass์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ์ฟผ๋ฆฌ๋Š” quantity ํ•„๋“œ์˜ ๊ฐ’์ด 100 ~ 200 ์‚ฌ์ด์ธ ๋ฌธ์„œ๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.

db.inventory.find( { quantity: { $gte: 100, $lte: 200 } } )

์ด ์ฟผ๋ฆฌ๋Š” ๋‹ค์Œ ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

{ "_id" : 2, "item" : "f2", "type" : "food", "quantity" : 100 }
{ "_id" : 3, "item" : "p1", "type" : "paper", "quantity" : 200 }
{ "_id" : 4, "item" : "p2", "type" : "paper", "quantity" : 150 }

์„ ํƒํ•œ ์ฟผ๋ฆฌ ๊ณ„ํš์„ ๋ณด๋ ค๋ฉด cursor.explain("executionStats") ์ปค์„œ ๋ฉ”์„œ๋“œ๋ฅผ find ๋ช…๋ น์˜ ๋์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

db.inventory.find(
{ quantity: { $gte: 100, $lte: 200 } }
).explain("executionStats")

explain() ๋Š” ๋‹ค์Œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

{
queryPlanner: {
...
winningPlan: {
queryPlan: {
stage: 'COLLSCAN',
...
}
}
},
executionStats: {
executionSuccess: true,
nReturned: 3,
executionTimeMillis: 0,
totalKeysExamined: 0,
totalDocsExamined: 10,
executionStages: {
stage: 'COLLSCAN',
...
},
...
},
...
}
  • ์ปฌ๋ ‰์…˜ ์Šค์บ”์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด queryPlanner.winningPlan.queryPlan.stage์—์„œ COLLSCAN์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

    ์ปฌ๋ ‰์…˜ ์Šค์บ”์€ mongod๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด ์ „์ฒด ์ปฌ๋ ‰์…˜ ๋ฌธ์„œ๋ฅผ ๋ฌธ์„œ๋ณ„๋กœ ์Šค์บ”ํ•ด์•ผ ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด ์ž‘์—…์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ์ž‘์—…์ด๋ฉฐ ์ฟผ๋ฆฌ ์†๋„๊ฐ€ ๋А๋ ค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • executionStats.nReturned์€(๋Š”) 3์„(๋ฅผ) ํ‘œ์‹œํ•˜์—ฌ ์šฐ์Šนํ•œ ์ฟผ๋ฆฌ ๊ณ„ํš์ด 3๊ฐœ์˜ ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

  • executionStats.totalKeysExamined๊ฐ€ 0์„ ํ‘œ์‹œํ•˜์—ฌ ์ด ์ฟผ๋ฆฌ๊ฐ€ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

  • executionStats.totalDocsExamined๊ฐ€ 10์„ ํ‘œ์‹œํ•˜์—ฌ MongoDB๊ฐ€ ์ผ์น˜ํ•˜๋Š” 3๊ฐœ์˜ ๋ฌธ์„œ๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด 10๊ฐœ์˜ ๋ฌธ์„œ(์ฆ‰, ์ปฌ๋ ‰์…˜์˜ ๋ชจ๋“  ๋ฌธ์„œ ์Šค์บ”)๋ฅผ ์Šค์บ”ํ•ด์•ผ ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

๋‹ค์Œ ์ฟผ๋ฆฌ๋Š” quantity ํ•„๋“œ์˜ ๊ฐ’์ด 100 ~ 200 ์‚ฌ์ด์ธ ๋ฌธ์„œ๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ํ•„ํ„ฐ๋ฅผ Compass ์ฟผ๋ฆฌ ํ‘œ์‹œ์ค„์— ๋ณต์‚ฌํ•˜๊ณ  Find๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

{ quantity: { $gte: 100, $lte: 200 } }

์ด ์ฟผ๋ฆฌ๋Š” ๋‹ค์Œ ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์„ ํƒํ•œ ์ฟผ๋ฆฌ ๊ณ„ํš์„ ๋ณด๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•˜์„ธ์š”.

  1. test.inventory collection์˜ Explain Plan ํƒญ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  2. Explain๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

MongoDB Compass๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฟผ๋ฆฌ ๊ณ„ํš์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ 

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ๋งค์šฐ ์ž‘์€ ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„ Actual Query Execution Time์€ 0์ดˆ๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

๋” ํฐ ๋ฐ์ดํ„ฐ ์„ธํŠธ์—์„œ๋Š” ์ธ๋ฑ์‹ฑ๋œ ์ฟผ๋ฆฌ์™€ ์ธ๋ฑ์‹ฑ๋˜์ง€ ์•Š์€ ์ฟผ๋ฆฌ ๊ฐ„์˜ ์ฟผ๋ฆฌ ์‹คํ–‰ ์‹œ๊ฐ„ ์ฐจ์ด๊ฐ€ ํ›จ์”ฌ ํด ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • Query Performance Summary์€(๋Š”) ์ฟผ๋ฆฌ์˜ ์‹คํ–‰ ํ†ต๊ณ„๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

    • Documents Returned ์€ 3 ์„ ํ‘œ์‹œํ•˜์—ฌ ์„ฑ๊ณต์ ์ธ ์ฟผ๋ฆฌ ๊ณ„ํš ์ด ์„ธ ๊ฐœ์˜ ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

    • Index Keys Examined ์€(๋Š”) 0 ์„(๋ฅผ) ํ‘œ์‹œํ•˜์—ฌ ์ด ์ฟผ๋ฆฌ ๊ฐ€ ์ธ๋ฑ์Šค ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€ ์•Š์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

    • Documents Examined์€(๋Š”) 10์„(๋ฅผ) ํ‘œ์‹œํ•˜์—ฌ MongoDB๊ฐ€ ์ผ์น˜ํ•˜๋Š” 3๊ฐœ์˜ ๋ฌธ์„œ๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด10๊ฐœ์˜ ๋ฌธ์„œ(์ฆ‰, ์ปฌ๋ ‰์…˜์˜ ๋ชจ๋“  ๋ฌธ์„œ ์Šค์บ”)๋ฅผ ์Šค์บ”ํ•ด์•ผ ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

  • Query Performance Summary ์•„๋ž˜์— MongoDB Compass๋Š” COLLSCAN ์ฟผ๋ฆฌ ๋‹จ๊ณ„๋ฅผ ํ‘œ์‹œํ•˜์—ฌ ์ด ์ฟผ๋ฆฌ์— ์ปฌ๋ ‰์…˜ ์Šค์บ”์ด ์‚ฌ์šฉ๋˜์—ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

    ์ปฌ๋ ‰์…˜ ์Šค์บ”์€ mongod๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด ์ „์ฒด ์ปฌ๋ ‰์…˜ ๋ฌธ์„œ๋ฅผ ๋ฌธ์„œ๋ณ„๋กœ ์Šค์บ”ํ•ด์•ผ ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด ์ž‘์—…์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ์ž‘์—…์ด๋ฉฐ ์ฟผ๋ฆฌ ์†๋„๊ฐ€ ๋А๋ ค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ ํ‘œ์‹œ์ค„ ์•„๋ž˜์˜ Raw JSON์„ ํด๋ฆญํ•˜์—ฌ ์›์‹œ JSON ํ˜•์‹์œผ๋กœ ์„ค๋ช… ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ๋ณผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ผ์น˜ํ•˜๋Š” ๋ฌธ์„œ ์ˆ˜์™€ ๊ฒ€ํ† ๋œ ๋ฌธ์„œ ์ˆ˜์˜ ์ฐจ์ด๋Š” ํšจ์œจ์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด ์ฟผ๋ฆฌ์— ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Œ์„ ์‹œ์‚ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

quantity ํ•„๋“œ์— ๋Œ€ํ•œ ์ฟผ๋ฆฌ๋ฅผ ์ง€์›ํ•˜๋ ค๋ฉด quantity ํ•„๋“œ์— ์ธ๋ฑ์Šค๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

db.inventory.createIndex( { quantity: 1 } )

์ฟผ๋ฆฌ ๊ณ„ํš ํ†ต๊ณ„๋ฅผ ๋ณด๋ ค๋ฉด explain() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

db.inventory.find(
{ quantity: { $gte: 100, $lte: 200 } }
).explain("executionStats")

explain() ๋ฉ”์„œ๋“œ๋Š” ๋‹ค์Œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

{
queryPlanner: {
...
winningPlan: {
queryPlan: {
stage: 'FETCH',
inputStage: {
stage: 'IXSCAN',
keyPattern: {
quantity: 1
},
...
}
}
},
rejectedPlans: [ ]
},
executionStats: {
executionSuccess: true,
nReturned: 3,
executionTimeMillis: 0,
totalKeysExamined: 3,
totalDocsExamined: 3,
executionStages: {
...
},
...
},
...
}
  • queryPlanner.winningPlan.queryPlan.inputStage.stage๊ฐ€ IXSCAN์„ ํ‘œ์‹œํ•ด ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

  • executionStats.nReturned์€(๋Š”) 3์„(๋ฅผ) ํ‘œ์‹œํ•˜์—ฌ ์šฐ์Šนํ•œ ์ฟผ๋ฆฌ ๊ณ„ํš์ด 3๊ฐœ์˜ ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

  • executionStats.totalKeysExamined๊ฐ€ 3์„ ํ‘œ์‹œํ•ด MongoDB๊ฐ€ ์„ธ ๊ฐœ์˜ ์ธ๋ฑ์Šค ํ•ญ๋ชฉ์„ ์Šค์บ”ํ–ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๊ฒ€์‚ฌํ•œ ํ‚ค์˜ ์ˆ˜๋Š” ๋ฐ˜ํ™˜๋œ ๋ฌธ์„œ ์ˆ˜์™€ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, mongod ํ•จ์ˆ˜๊ฐ€ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด ์ธ๋ฑ์Šค ํ‚ค๋งŒ์„ ๊ฒ€์ƒ‰ํ–ˆ์Œ์„๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. mongod๋Š” ๋ชจ๋“  ๋ฌธ์„œ๋ฅผ ์Šค์บ”ํ•  ํ•„์š”๊ฐ€ ์—†์—ˆ๊ณ  ์ผ์น˜ํ•˜๋Š” ๋ฌธ์„œ 3๊ฐœ๋งŒ์„ ๋ฉ”๋ชจ๋ฆฌ๋กœ ๊ฐ€์ ธ์™”์Šต๋‹ˆ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ ๋งค์šฐ ํšจ์œจ์ ์ธ ์ฟผ๋ฆฌ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

  • executionStats.totalDocsExamined๋Š” 3 ์„ ํ‘œ์‹œํ•ด MongoDB๊ฐ€ ๋ฌธ์„œ 3๊ฐœ๋ฅผ ์Šค์บ”ํ–ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

  1. test.inventory collection์˜ Indexes ํƒญ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  2. Create Index๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  3. Select a field name ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด์—์„œ quantity์„(๋ฅผ) ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  4. ์œ ํ˜• ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด์—์„œ 1 (asc)๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  5. Create๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ 

์ธ๋ฑ์Šค ์ด๋ฆ„ ํ•„๋“œ๋ฅผ ๋น„์›Œ๋‘๋ฉด MongoDB Compass๊ฐ€ ์ธ๋ฑ์Šค์— ๊ธฐ๋ณธ ์ด๋ฆ„์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ Indexes ํƒญ์—์„œ ์ƒˆ๋กœ ๋งŒ๋“  ์ธ๋ฑ์Šค๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

inventory ์ปฌ๋ ‰์…˜์— ๋Œ€ํ•œ Explain Plan ํƒญ์œผ๋กœ ๋Œ์•„๊ฐ€์„œ ์ด์ „ ๋‹จ๊ณ„์˜ ์ฟผ๋ฆฌ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

{ quantity: { $gte: 100, $lte: 200 } }

MongoDB Compass๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฟผ๋ฆฌ ๊ณ„ํš์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

  • Query Performance Summary์€(๋Š”) ์ฟผ๋ฆฌ์˜ ์‹คํ–‰ ํ†ต๊ณ„๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

    • Documents Returned ์€ 3 ์„ ํ‘œ์‹œํ•˜์—ฌ ์„ฑ๊ณต์ ์ธ ์ฟผ๋ฆฌ ๊ณ„ํš ์ด ์„ธ ๊ฐœ์˜ ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

    • Index Keys Examined ์€ 3 ์„ ํ‘œ์‹œํ•˜์—ฌ MongoDB ๊ฐ€ ์„ธ ๊ฐœ์˜ ์ธ๋ฑ์Šค ํ•ญ๋ชฉ์„ ์Šค์บ”ํ–ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๊ฒ€์‚ฌํ•œ ํ‚ค์˜ ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜๋œ ๋ฌธ์„œ์˜ ์ˆ˜์™€ ์ผ์น˜ํ•˜๋ฏ€๋กœ mongod ๋Š” ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด ์ธ๋ฑ์Šค ํ‚ค๋งŒ ๊ฒ€์‚ฌํ•˜๋ฉด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. mongod ๋Š” ๋ชจ๋“  ๋ฌธ์„œ๋ฅผ ์Šค์บ”ํ•  ํ•„์š”๊ฐ€ ์—†์—ˆ๊ณ , ์ผ์น˜ํ•˜๋Š” ๋ฌธ์„œ 3๊ฐœ๋งŒ ๋ฉ”๋ชจ๋ฆฌ๋กœ ๊ฐ€์ ธ์˜ค๋ฉด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ ๋งค์šฐ ํšจ์œจ์ ์ธ ์ฟผ๋ฆฌ ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

    • Documents Examined ์€ 3 ์„ ํ‘œ์‹œํ•˜์—ฌ MongoDB ๊ฐ€ ์„ธ ๊ฐœ์˜ ๋ฌธ์„œ๋ฅผ ์Šค์บ”ํ–ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

    • Query Performance Summary์˜ ์˜ค๋ฅธ์ชฝ์—์„œ MongoDB Compass๋Š” ์ฟผ๋ฆฌ๊ฐ€ quantity ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ–ˆ์Œ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

  • Query Performance Summary ์•„๋ž˜์—์„œ MongoDB Compass๋Š” ์ฟผ๋ฆฌ ๋‹จ๊ณ„์ธ FETCH์™€ IXSCAN์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. IXSCAN์€ mongod๊ฐ€ FETCH ๋‹จ๊ณ„๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๋ฌธ์„œ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ธฐ ์ „์— ์ฟผ๋ฆฌ๋ฅผ ๋งŒ์กฑ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ–ˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ ํ‘œ์‹œ์ค„ ์•„๋ž˜์˜ Raw JSON์„ ํด๋ฆญํ•˜์—ฌ ์›์‹œ JSON ํ˜•์‹์œผ๋กœ ์„ค๋ช… ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ๋ณผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ธ๋ฑ์Šค๊ฐ€ ์—†์œผ๋ฉด ์ฟผ๋ฆฌ๋Š” 10๊ฐœ ๋ฌธ์„œ์˜ ์ „์ฒด ์ปฌ๋ ‰์…˜์„ ์Šค์บ”ํ•˜์—ฌ 3๊ฐœ์˜ ์ผ์น˜ํ•˜๋Š” ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ฟผ๋ฆฌ๋Š” ๊ฐ ๋ฌธ์„œ ์ „์ฒด๋ฅผ ์Šค์บ”ํ•˜์—ฌ ์ž ์žฌ์ ์œผ๋กœ ํ•ด๋‹น ๋ฌธ์„œ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ๋กœ ๊ฐ€์ ธ์™€์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ๋น„์šฉ์ด ๋งŽ์ด ๋“ค๊ณ  ์ฟผ๋ฆฌ ์ž‘์—…์ด ๋А๋ ค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด 3๊ฐœ์˜ ์ธ๋ฑ์Šค ํ•ญ๋ชฉ๊ณผ 3๊ฐœ์˜ ๋ฌธ์„œ๋ฅผ ์Šค์บ”ํ•˜์—ฌ 3๊ฐœ์˜ ์ผ์น˜ํ•˜๋Š” ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ๋งค์šฐ ํšจ์œจ์ ์ธ ์ฟผ๋ฆฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

์ธ๋ฑ์Šค ์„ฑ๋Šฅ ๋น„๊ต

๋‘˜ ์ด์ƒ์˜ ์ธ๋ฑ์Šค ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ ์˜ ์„ฑ๋Šฅ์„ ์ˆ˜๋™์œผ๋กœ ๋น„๊ตํ•˜๋ ค๋ฉด hint() ๋ฉ”์„œ๋“œ๋ฅผ explain() ๋ฉ”์„œ๋“œ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ์ฟผ๋ฆฌ๋ฅผ ์ƒ๊ฐํ•ด ๋ณด์„ธ์š”.

db.inventory.find( {
quantity: {
$gte: 100, $lte: 300
},
type: "food"
} )

์ด ์ฟผ๋ฆฌ๋Š” ๋‹ค์Œ ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

{ "_id" : 2, "item" : "f2", "type" : "food", "quantity" : 100 }
{ "_id" : 5, "item" : "f3", "type" : "food", "quantity" : 300 }

์ฟผ๋ฆฌ ์ง€์› ํ•˜๋ ค๋ฉด ๋ณตํ•ฉ ์ธ๋ฑ์Šค ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๋ณตํ•ฉ ์ธ๋ฑ์Šค์—์„œ๋Š” ํ•„๋“œ์˜ ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ ๋“ค์–ด, ๋‹ค์Œ ๋‘ ๊ฐœ์˜ ๋ณตํ•ฉ ์ธ๋ฑ์Šค๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ์ธ๋ฑ์Šค ๋จผ์ € quantity ํ•„๋“œ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•œ ๋‹ค์Œ type ํ•„๋“œ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ์ธ๋ฑ์Šค ๋จผ์ € type ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•œ ๋‹ค์Œ quantity ํ•„๋“œ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค.

db.inventory.createIndex( { quantity: 1, type: 1 } )
db.inventory.createIndex( { type: 1, quantity: 1 } )

์ฒซ ๋ฒˆ์งธ ์ธ๋ฑ์Šค ์ฟผ๋ฆฌ ์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์„ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

db.inventory.find(
{ quantity: { $gte: 100, $lte: 300 }, type: "food" }
).hint({ quantity: 1, type: 1 }).explain("executionStats")

explain() ๋ฉ”์„œ๋“œ๋Š” ๋‹ค์Œ ์ถœ๋ ฅ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

{
queryPlanner: {
...
winningPlan: {
queryPlan: {
stage: 'FETCH',
inputStage: {
stage: 'IXSCAN',
keyPattern: {
quantity: 1,
type: 1
},
...
}
}
}
},
rejectedPlans: [ ]
},
executionStats: {
executionSuccess: true,
nReturned: 2,
executionTimeMillis: 0,
totalKeysExamined: 5,
totalDocsExamined: 2,
executionStages: {
...
}
},
...
}

MongoDB 5 ๊ฐœ์˜ ์ธ๋ฑ์Šค ํ‚ค(executionStats.totalKeysExamined)๋ฅผ ์Šค์บ”ํ•˜์—ฌ 2 ๊ฐœ์˜ ์ผ์น˜ํ•˜๋Š” ๋ฌธ์„œ(executionStats.nReturned)๋ฅผ ๋ฐ˜ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‘ ๋ฒˆ์งธ ์ธ๋ฑ์Šค ์ฟผ๋ฆฌ ์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์„ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

db.inventory.find(
{ quantity: { $gte: 100, $lte: 300 }, type: "food" }
).hint({ type: 1, quantity: 1 }).explain("executionStats")

explain() ๋ฉ”์„œ๋“œ๋Š” ๋‹ค์Œ ์ถœ๋ ฅ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

{
queryPlanner: {
...
queryPlan: {
winningPlan: {
stage: 'FETCH',
inputStage: {
stage: 'IXSCAN',
keyPattern: {
type: 1,
quantity: 1
},
...
}
}
},
rejectedPlans: [ ]
},
executionStats: {
executionSuccess: true,
nReturned: 2,
executionTimeMillis: 0,
totalKeysExamined: 2,
totalDocsExamined: 2,
executionStages: {
...
}
},
...
}

MongoDB 2 ๊ฐœ์˜ ์ธ๋ฑ์Šค ํ‚ค(executionStats.totalKeysExamined)๋ฅผ ์Šค์บ”ํ•˜์—ฌ 2 ๊ฐœ์˜ ์ผ์น˜ํ•˜๋Š” ๋ฌธ์„œ(executionStats.nReturned)๋ฅผ ๋ฐ˜ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋‘ ๋ฒˆ์งธ ๋ณตํ•ฉ ์ธ๋ฑ์Šค { type: 1, quantity: 1 }์€ ์˜ˆ์‹œ ์ฟผ๋ฆฌ ์ง€์›ํ•˜๊ธฐ์— ๋” ํšจ์œจ์ ์ธ ์ธ๋ฑ์Šค ์ด๋ฉฐ, MongoDB ์„œ๋ฒ„ 5 ์™€ ๋น„๊ตํ–ˆ์„ ๋•Œ ์ด ์ธ๋ฑ์Šค ์‚ฌ์šฉํ•˜์—ฌ ์ผ์น˜ํ•˜๋Š” ๋ชจ๋“  ๋ฌธ์„œ๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด 2 index keys ๋งŒ ์Šค์บ”ํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋ณตํ•ฉ ์ธ๋ฑ์Šค { quantity: 1, type: 1 }์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ.

๋‹ค์Œ๋„ ์ฐธ์กฐํ•˜์„ธ์š”.

์ด ํŽ˜์ด์ง€์˜ ๋‚ด์šฉ