พังพอนทำดัชนีในรหัสการผลิต


124

ตามเอกสารพังพอนสำหรับMongooseJSและMongoDB/ Node.js:

เมื่อแอปพลิเคชันของคุณเริ่มต้นขึ้น Mongoose จะเรียกensureIndexใช้ดัชนีที่กำหนดไว้ในสคีมาของคุณโดยอัตโนมัติ แม้ว่าจะเหมาะสำหรับการพัฒนา แต่ขอแนะนำให้ปิดใช้งานพฤติกรรมนี้ในการผลิตเนื่องจากการสร้างดัชนีอาจทำให้เกิดผลกระทบต่อประสิทธิภาพอย่างมาก ปิดการทำงานโดยตั้งค่าautoIndexตัวเลือกของสคีมาของคุณเป็นเท็จ

สิ่งนี้ดูเหมือนจะแนะนำให้ลบการจัดทำดัชนีอัตโนมัติจากพังพอนก่อนที่จะปรับใช้เพื่อเพิ่มประสิทธิภาพ Mongoose จากการสั่งให้ Mongo ไปและปั่นผ่านดัชนีทั้งหมดในการเริ่มต้นแอปพลิเคชันซึ่งดูเหมือนจะสมเหตุสมผล

วิธีที่เหมาะสมในการจัดการการจัดทำดัชนีในรหัสการผลิตคืออะไร? บางทีสคริปต์ภายนอกควรสร้างดัชนี? หรืออาจensureIndexไม่จำเป็นหากแอปพลิเคชั่นเดียวเป็นผู้อ่าน / เขียนเพียงคนเดียวในคอลเลคชันเนื่องจากจะดำเนินการต่อดัชนีทุกครั้งที่มีการเขียน DB

แก้ไข:เพื่อเสริม MongoDB มีเอกสารที่ดีสำหรับวิธีการจัดทำดัชนี แต่ไม่ควรทำทำไมหรือเมื่อใดจึงควรทำคำสั่งการจัดทำดัชนีอย่างชัดเจน สำหรับฉันแล้วดูเหมือนว่าดัชนีควรได้รับการอัปเดตโดยแอปพลิเคชันนักเขียนโดยอัตโนมัติในคอลเลกชันที่มีดัชนีที่มีอยู่และนั่นensureIndexเป็นสิ่งที่ทำได้เพียงครั้งเดียว (ทำเมื่อมีการใช้ดัชนีใหม่) ซึ่งในกรณีนี้ Mongoose autoIndexควรเป็น no-op ภายใต้การรีสตาร์ทเซิร์ฟเวอร์ปกติ

คำตอบ:


135

ฉันไม่เคยเข้าใจเลยว่าเหตุใดเอกสารของพังพอนจึงแนะนำให้ปิดใช้งานautoIndexในการผลิตอย่างกว้างขวาง เมื่อเพิ่มดัชนีแล้วการensureIndexเรียกที่ตามมาก็จะเห็นว่ามีดัชนีอยู่แล้วจึงกลับมา ดังนั้นจึงมีผลต่อประสิทธิภาพเมื่อคุณสร้างดัชนีเป็นครั้งแรกเท่านั้นและในเวลานั้นคอลเลกชันมักจะว่างเปล่าดังนั้นการสร้างดัชนีจึงทำได้อย่างรวดเร็ว

ข้อเสนอแนะของฉันคือการปล่อยให้autoIndexเปิดใช้งานเว้นแต่คุณจะมีสถานการณ์เฉพาะที่ทำให้คุณมีปัญหา เช่นหากคุณต้องการเพิ่มดัชนีใหม่ลงในคอลเล็กชันที่มีอยู่ซึ่งมีเอกสารหลายล้านชุดและคุณต้องการควบคุมมากขึ้นเมื่อสร้างขึ้น


10
ฉันมีคำถามเพิ่มเติม ... ถ้าฉันตั้งค่าเป็นเท็จล่ะ? ดัชนีจะถูกสร้างขึ้นเมื่อฉันแทรกข้อมูลหรือฉันจำเป็นต้องสร้างอย่างชัดเจน ขออภัยหากนี่เป็นคำถามมือใหม่ แต่จะมีประโยชน์มากถ้าคุณตอบ
Saransh Mohapatra

5
@SaranshMohapatra เมื่อautoIndexเป็นเท็จคุณต้องเรียกsureIndexesบนโมเดลของคุณเพื่อสร้างดัชนี
JohnnyHK

กว่าจะต้องเรียกมันทุกครั้งหรือแค่กำหนดแบบจำลองครั้งเดียว?
Saransh Mohapatra

@SaranshMohapatra เมื่อคุณกำหนด (คอมไพล์) โมเดลของคุณ ฉันทำเช่นนั้นเมื่อฉันเริ่มแอปครั้งแรก ตอนนี้ความคิดที่ยากคือการตัดสินใจทิ้งดัชนีทั้งหมดและสร้างขึ้นใหม่ในกรณีที่คุณเปลี่ยนแปลงสคีมา
มอส

3
@JohnnyHK คุณยังเห็นด้วยกับคำตอบของคุณตอนนี้ว่าเกือบปี 2016 หรือไม่?
Alexander Mills

41

แม้ว่าฉันจะเห็นด้วยกับคำตอบที่ยอมรับ แต่ก็น่าสังเกตว่าตามคู่มือ MongoDBนี่ไม่ใช่วิธีที่แนะนำในการเพิ่มดัชนีบนเซิร์ฟเวอร์ที่ใช้งานจริง:

หากแอปพลิเคชันของคุณมีการดำเนินการ sureIndex () และไม่มีดัชนีสำหรับข้อกังวลด้านการดำเนินงานอื่น ๆ การสร้างดัชนีอาจส่งผลกระทบอย่างรุนแรงต่อประสิทธิภาพของฐานข้อมูล

เพื่อหลีกเลี่ยงปัญหาด้านประสิทธิภาพตรวจสอบให้แน่ใจว่าแอปพลิเคชันของคุณตรวจสอบดัชนีเมื่อเริ่มต้นใช้งานโดยใช้เมธอด getIndexes () หรือวิธีการที่เทียบเท่าสำหรับไดรเวอร์ของคุณและจะยุติหากไม่มีดัชนีที่เหมาะสม สร้างดัชนีในอินสแตนซ์การผลิตโดยใช้รหัสแอปพลิเคชันที่แยกจากกันเสมอในช่วงเวลาการบำรุงรักษาที่กำหนด

แน่นอนว่ามันขึ้นอยู่กับว่าแอปพลิเคชันของคุณมีโครงสร้างและปรับใช้อย่างไร ตัวอย่างเช่นหากคุณกำลังปรับใช้กับ Heroku และคุณไม่ได้ใช้คุณสมบัติพรีบูตของ Heroku เป็นไปได้ว่าแอปพลิเคชันของคุณไม่ได้ให้บริการคำขอเลยในระหว่างการเริ่มต้นระบบดังนั้นจึงอาจปลอดภัยที่จะสร้างดัชนีในเวลานั้น

นอกจากนี้จากคำตอบที่ยอมรับ:

ดังนั้นจึงมีผลต่อประสิทธิภาพเมื่อคุณสร้างดัชนีเป็นครั้งแรกและในเวลานั้นคอลเลกชันมักจะว่างเปล่าดังนั้นการสร้างดัชนีจึงทำได้อย่างรวดเร็ว

หากคุณได้จัดการเพื่อรับโมเดลข้อมูลและการค้นหาของคุณในครั้งแรกนี่เป็นเรื่องปกติและมักจะเป็นเช่นนั้น อย่างไรก็ตามหากคุณกำลังเพิ่มฟังก์ชันการทำงานใหม่ให้กับแอปของคุณด้วยแบบสอบถาม DB ใหม่ในคุณสมบัติที่ไม่มีดัชนีคุณมักจะพบว่าตัวเองกำลังเพิ่มดัชนีลงในคอลเล็กชันที่มีเอกสารที่มีอยู่จำนวนมาก

นี่เป็นเวลาที่คุณต้องระมัดระวังในการเพิ่มดัชนีและพิจารณาผลกระทบด้านประสิทธิภาพของการทำเช่นนั้นอย่างรอบคอบ ตัวอย่างเช่นคุณสามารถสร้างดัชนีในพื้นหลัง :

db.ensureIndex({ name: 1 }, { background: true });

3
ตกลงดังนั้นสิ่งที่คุณต้องทำคืออย่าเริ่มเซิร์ฟเวอร์ของคุณจนกว่าการเรียกกลับของ sureIndex ทั้งหมดจะเริ่มทำงานสำหรับแต่ละคอลเล็กชัน
Alexander Mills

@AlexMills คุณมั่นใจได้อย่างไร?
lonelymo

async.each (Object.keys (โมเดล), ฟังก์ชัน (คีย์, cb) {แบบจำลอง [คีย์] .ensureIndexes (cb)}, cb)
Alexander Mills

เพียงแค่โทร sureIndexes ในแต่ละแบบพังพอนรอให้ทั้งหมดเสร็จสิ้นจากนั้นเริ่มเซิร์ฟเวอร์ของคุณ ฉันขอแนะนำให้รอให้การเชื่อมต่อ db เกิดขึ้นก่อนที่จะเริ่มเซิร์ฟเวอร์ของคุณเช่นกัน
Alexander Mills

2
ไม่มีensureIndexอีกแล้ว. มีcreateIndexแทน ฉันถูกไหม?
แจ็คเปล่า

1

ใช้รหัสบล็อกนี้เพื่อจัดการกับโหมดการผลิต:

const autoIndex = process.env.NODE_ENV !== 'production';
mongoose.connect('mongodb://localhost/collection', { autoIndex });
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.