ขนาดแบทช์ที่แนะนำสำหรับ SqlBulkCopy คืออะไร?


คำตอบ:


97

ฉันมียูทิลิตี้นำเข้าซึ่งนั่งอยู่บนเซิร์ฟเวอร์จริงเดียวกันกับอินสแตนซ์ SQL Server ของฉัน การใช้แบบกำหนดเองIDataReaderจะแยกวิเคราะห์ไฟล์แบบแบนและแทรกลงในฐานข้อมูลโดยใช้SQLBulkCopy. ไฟล์ทั่วไปมีแถวที่มีคุณสมบัติประมาณ 6 ล้านแถวโดยเฉลี่ย 5 คอลัมน์ของทศนิยมและข้อความสั้น ๆ ประมาณ 30 ไบต์ต่อแถว

จากสถานการณ์นี้ฉันพบว่าขนาดแบตช์ 5,000 จะเป็นการประนีประนอมความเร็วและการใช้หน่วยความจำที่ดีที่สุด ฉันเริ่มต้นด้วย 500 และทดลองกับขนาดใหญ่ขึ้น ฉันพบว่า 5,000 เร็วขึ้น 2.5 เท่าโดยเฉลี่ยมากกว่า 500 การแทรก 6 ล้านแถวใช้เวลาประมาณ 30 วินาทีโดยมีขนาดชุด 5,000 และประมาณ 80 วินาทีโดยมีขนาดแบตช์ 500

10,000 ไม่ได้เร็วขึ้นอย่างวัดได้ การย้ายขึ้นไป 50,000 ทำให้ความเร็วเพิ่มขึ้นสองสามเปอร์เซ็นต์ แต่ก็ไม่คุ้มกับภาระที่เพิ่มขึ้นบนเซิร์ฟเวอร์ มากกว่า 50,000 แสดงว่าไม่มีการปรับปรุงความเร็ว

นี่ไม่ใช่สูตร แต่เป็นจุดข้อมูลอื่นให้คุณใช้


3
สิ่งหนึ่งที่ต้องพิจารณาคือถ้าตารางว่างเปล่าและมีดัชนี ในกรณีเหล่านี้คุณอาจต้องการอัปโหลดทุกอย่างในชุดเดียวดังที่กล่าวไว้ที่นี่: technet.microsoft.com/en-us/library/ms177445(v=sql.105).aspx "หากคุณนำเข้าข้อมูลจำนวนมากไปยังตารางว่างที่มีดัชนี และคุณระบุขนาดชุดงานตารางจะไม่ว่างเปล่าหลังจากชุดแรกเริ่มต้นด้วยชุดที่สองข้อมูลจะถูกบันทึกอย่างสมบูรณ์สำหรับตารางที่จัดทำดัชนีว่างให้พิจารณาดำเนินการนำเข้าจำนวนมากในชุดงานเดียว "
Sal

SqlBulkCopy สตรีมข้อมูลจากแหล่งที่มา (เช่น DataTable) ไปยัง Sql แล้ว "การเพิ่มโหลดบนเซิร์ฟเวอร์" มีขนาดเท่าใดในชุดใหญ่ (เช่น 50,000)
BornToCode

29

นี่เป็นปัญหาที่ฉันใช้เวลาในการตรวจสอบ ฉันต้องการเพิ่มประสิทธิภาพการนำเข้าไฟล์ CSV ขนาดใหญ่ (16+ GB, 65+ ล้านระเบียนและเพิ่มขึ้นเรื่อย ๆ ) ไปยังฐานข้อมูล SQL Server 2005 โดยใช้แอปพลิเคชันคอนโซล C # (.Net 2.0) ดังที่Jeremyได้ชี้ให้เห็นแล้วคุณจะต้องทำการปรับแต่งบางอย่างสำหรับสถานการณ์เฉพาะของคุณ แต่ฉันขอแนะนำให้คุณมีขนาดแบทช์เริ่มต้นที่ 500 และทดสอบค่าทั้งด้านบนและด้านล่างนี้

ฉันได้รับคำแนะนำให้ทดสอบค่าระหว่าง 100 ถึง 1,000 สำหรับขนาดแบทช์จากโพสต์ฟอรัม MSDNนี้และไม่เชื่อ แต่เมื่อฉันทดสอบขนาดแบทช์ระหว่าง 100 ถึง 10,000 ฉันพบว่า 500 เป็นค่าที่เหมาะสมที่สุดสำหรับแอปพลิเคชันของฉัน 500 คุ้มค่าสำหรับSqlBulkCopy.BatchSizeยังแนะนำที่นี่

เพื่อเพิ่มประสิทธิภาพการดำเนินงานต่อไป SqlBulkCopy ของคุณตรวจสอบนี้คำแนะนำ MSDN ; ฉันพบว่าการใช้ SqlBulkCopyOptions.TableLock ช่วยลดเวลาในการโหลด


ฉันคิดว่าการเรียกใช้คำสั่งสำเนาจำนวนมากในเซิร์ฟเวอร์นั้นอาจเร็วกว่า
Captain Kenpachi

16

ตามที่คนอื่นระบุไว้ขึ้นอยู่กับสภาพแวดล้อมของคุณโดยเฉพาะปริมาณแถวและเวลาแฝงของเครือข่าย

โดยส่วนตัวแล้วฉันจะเริ่มต้นด้วยการตั้งค่าBatchSizeคุณสมบัติเป็น 1,000 แถวและดูว่ามีประสิทธิภาพอย่างไร ถ้ามันใช้งานได้ฉันจะเพิ่มจำนวนแถวเป็นสองเท่า (เช่นเป็น 2000, 4000 เป็นต้น) จนกว่าฉันจะหมดเวลา

มิฉะนั้นหากหมดเวลาที่ 1,000 ฉันจะลดจำนวนแถวลงครึ่งหนึ่ง (เช่น 500) จนกว่าจะได้ผล

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

ปัจจัยอื่น ๆ ที่ต้องพิจารณาคือการคัดลอกแถวชุดเดียวใช้เวลานานเท่าใด การหมดเวลาจะเกิดขึ้นหากชุดแถวที่คัดลอกเกินBulkCopyTimeoutคุณสมบัติซึ่งโดยค่าเริ่มต้นคือ 30 วินาที คุณอาจลองเพิ่มBulkCopyTimeoutคุณสมบัติเป็นสองเท่าเป็น60 วินาที ซึ่งจะช่วยให้สามารถคัดลอกแถวแบตช์ชุดใหญ่ได้นานขึ้น ตัวอย่างเช่นชุดแถว 50,000 แถวอาจใช้เวลาประมาณ 40 วินาทีหากเกินเวลาที่กำหนด 30 วินาทีดังนั้นการชนกันนานถึง 60 วินาทีอาจช่วยในเรื่องประสิทธิภาพ


4

ทั้งหมดนี้ขึ้นอยู่กับการใช้งานของคุณ

คุณคาดหวังความเร็วระดับใดบนเครือข่ายของคุณ คุณกำลังใช้มันในฟอร์มหรือ ASP.Net? คุณต้องการแจ้งเตือนผู้ใช้ถึงความคืบหน้าหรือไม่? ขนาดของงานทั้งหมดคืออะไร?

จากประสบการณ์ของฉันที่เรียกใช้สำเนาจำนวนมากโดยไม่ระบุขนาดชุดงานจะทำให้เกิดปัญหาการหมดเวลา ฉันชอบเริ่มต้นด้วยบางอย่างเช่นบันทึก 1,000 รายการและทำการปรับเปลี่ยนบางอย่างจากที่นั่น


ความเร็ว: แตกต่างกันไป WebForms: ใช่ ASP.NET: ใช่ตารางกว้าง: ใช่ตารางแคบใช่ หลายพันแถว: ใช่ หลายล้านแถว: ใช่ ถ้าคุณคิดสถานการณ์ได้ฉันก็คงทำ
Jonathan Allen

1
ฉันต้องยึดตามคำตอบก่อนหน้านี้แล้ว ฉันไม่คิดว่าจะมีกระสุนเงิน
Jeremy

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.