คำอธิบายความเป็นมา: โดยปกติหากคุณต้องการอัปเดตข้อมูลหลายครั้งในแต่ละครั้งมีสองวิธีในการอัปเดตทีละวิธี (1) วนซ้ำรหัสธุรกิจเพื่ออัปเดตทีละรายการ (2) อัปเดตข้อมูลทั้งหมดในครั้งเดียว (เพื่อให้แม่นยำยิ่งขึ้นเป็นคำสั่ง SQL เพื่ออัปเดตข้อมูลทั้งหมดใส่การดำเนินการอัปเดตทีละตัวบนฝั่งฐานข้อมูลและด้านรหัสธุรกิจคือการอัปเดตข้อมูลทั้งหมดในครั้งเดียว) ทั้งสองวิธีมีข้อดีและข้อเสียของพวกเขา ต่อไปนี้จะวิเคราะห์ข้อดีและข้อเสียของสองวิธีโดยย่อและส่วนใหญ่แนะนำการใช้วิธีที่สองใน mybatis
อัปเดตทีละตัว
วิธีนี้เห็นได้ชัดว่าเป็นข้อผิดพลาดที่ง่ายที่สุดและน้อยที่สุด แม้ว่าจะมีข้อผิดพลาดเกิดขึ้น แต่ก็มีผลต่อข้อมูลข้อผิดพลาดเท่านั้น สามารถควบคุมได้ด้วยข้อมูลแต่ละชิ้น หากการอัปเดตล้มเหลวหรือประสบความสำเร็จสามารถรับได้จากเนื้อหาที่อัปเดตเป็นเนื้อหาใด รหัสอาจมีลักษณะเช่นนี้:
UpdateBatch (รายการ <MyData> DATAS) {สำหรับ (myData data: data) {ลอง {myDatadao.Update (ข้อมูล); // อัปเดตข้อมูลอัปเดตไฟล์ XML ด้านล่างใน MYBATIS <อัปเดต> อัปเดตชุด myData ... ที่ไหน ... </update>ปัญหาที่ใหญ่ที่สุดของวิธีนี้คือปัญหาประสิทธิภาพ มันอัปเดตทีละตัวและเชื่อมต่อกับฐานข้อมูลในแต่ละครั้งจากนั้นอัปเดตแล้วปล่อยทรัพยากรการเชื่อมต่อ (แม้ว่าประสิทธิภาพของข้อมูลที่เชื่อมต่อบ่อยครั้งสามารถปรับปรุงได้อย่างมากผ่านกลุ่มการเชื่อมต่อซึ่งไม่สามารถทนต่อข้อมูลจำนวนมาก) การสูญเสียนี้จะสะท้อนให้เห็นถึงปัญหาประสิทธิภาพเมื่อปริมาณข้อมูลมีขนาดใหญ่ นี่คือเมื่อการตอบสนองความต้องการทางธุรกิจการใช้งานการอัปเดตชุดที่สองที่กล่าวถึงข้างต้นมักจะใช้ (แน่นอนวิธีนี้ยังมีข้อ จำกัด มาตราส่วนข้อมูลซึ่งจะกล่าวถึงในภายหลัง)
การอัปเดตแบตช์ SQL
คำสั่ง SQL ใช้เพื่ออัปเดตข้อมูลทั้งหมดในแบทช์ ลองมาดูกันว่ามันมักจะเขียนใน mybatis (ลบไวยากรณ์ mybatis เป็นคำสั่ง SQL ดั้งเดิมดังนั้นฉันไม่ได้พูดถึงวิธีการเขียนใน SQL)
<update id = "updateBatch" parameterType = "java.util.list"> อัปเดตสถานะ set myData_Table = <foreach collection = "list" item = "item" index = "index" separator = "" case id "close =" end "> item = "item" separator = "," open = "(" close = ")"> #{item.id, jdbcType = bigint} </foreach> </update>ที่ไหนเมื่อ ... แล้ว ... คือ "สวิตช์" ไวยากรณ์ใน SQL ที่นี่ไวยากรณ์ <Foreach> ของ MyBatis ใช้เพื่อรวมการอัปเดตแบทช์ SQL เข้าด้วยกัน ข้างต้นหมายความว่าฟิลด์สถานะของข้อมูลที่ส่งผ่านในรายการ ID ในพารามิเตอร์ UpdateBatch นั้นได้รับการอัปเดตแบทช์ นอกจากนี้คุณยังสามารถใช้ <Trim> เพื่อใช้งานฟังก์ชั่นเดียวกันรหัสมีดังนี้:
<update id = "updateBatch" parameterType = "java.util.list"> อัปเดต mydata_table <trim prefix = "set" suffixoverrides = ","> <trim prefix = "สถานะ = case" suffix = "end"> <foreach collection = </foreach> </trim> </trim> โดยที่ id ใน <foreach collection = "list" index = "index" item = "item" separator = "," open = "(" close = ")"> #{item.id, jdbctype = bigint} </foreach> </อัปเดต><Trim> คำอธิบายคุณสมบัติ
1. PREFIX คำต่อท้ายหมายถึงการเพิ่มเนื้อหาในด้านหน้าหรือหลังส่วนที่ห่อไว้ในแท็กตัดแต่ง
2. หากมีคำนำหน้าในเวลาเดียวกัน SuffixOverrides หมายความว่าเนื้อหาในการแทนที่จะถูกเขียนทับด้วยคำนำหน้าและคำต่อท้าย
3. ถ้าเพียงคำนำหน้าแบบ prefiveOverrides, SuffixOverrides หมายถึงการลบเนื้อหาที่ระบุโดย XXXOverides ที่จุดเริ่มต้นหรือสิ้นสุด
รหัสข้างต้นจะถูกแปลงเป็น SQL ดังนี้:
อัปเดต MyData_Table Set Status = กรณีเมื่อ id = #{item.id} จากนั้น #{item.status} // นี่ควรเป็น <foreach> ขยายค่า ... สิ้นสุดที่ id ใน (... );แน่นอนว่านี่คือการใช้งานการอัปเดตแบบแบทช์ที่ง่ายที่สุด บางครั้งอาจต้องมีการอัปเดตหลายฟิลด์ดังนั้นคุณต้องมี
<trim prefix = "status = case" suffix = "end,"> <foreach collection = "list" item = "item" index = "index"> เมื่อ id = #imit.id} จากนั้น #{item.status} </foreach> </trim>คัดลอกหลายครั้งเปลี่ยนเนื้อหาของคำนำหน้าและเมื่อ ... จากนั้น ... และหากคุณต้องการตั้งค่าเริ่มต้นสำหรับฟิลด์ที่แน่นอนคุณสามารถใช้อย่างอื่น
<trim prefix = "status = case" suffix = "end,"> <foreach collection = "list" item = "item" index = "index"> เมื่อ id = #imit.id} จากนั้น #{item.status} </foreach> else default_value </trim>นอกจากนี้ยังมีสถานการณ์ที่พบบ่อยมากขึ้นที่ต้องมีการอัพเดทข้อมูลและข้อมูลที่ตรงกับเงื่อนไขเท่านั้นที่สามารถอัปเดตได้ สถานการณ์นี้สามารถทำได้:
<trim prefix = "status = case" suffix = "end,"> <foreach collection = "list" item = "item" index = "index"> <ถ้า test = "item.status! = null และ item.status! = -1"> เมื่อ id = #{item.id} ในกรณีนี้เฉพาะ status != null && status != -1 ข้อมูลในรายการที่จะอัปเดตเท่านั้นที่สามารถอัปเดตได้ คนอื่น ๆ จะได้รับการอัปเดตด้วยค่าเริ่มต้นโดยไม่ต้องเก็บข้อมูลต้นฉบับไม่เปลี่ยนแปลง ถ้าคุณต้องการเก็บข้อมูลต้นฉบับไม่เปลี่ยนแปลง นั่นคือการอัปเดตที่ตรงตามเงื่อนไขและเงื่อนไขที่ไม่ตรงตามเงื่อนไขยังคงไม่เปลี่ยนแปลง วิธีง่ายๆในการทำคือการเพิ่มอีก <ถ้า> เพราะไม่มีถ้า ... อื่น ... ไวยากรณ์ใน mybatis แต่เอฟเฟกต์เดียวกันสามารถทำได้ผ่านหลาย ๆ <fic> ดังต่อไปนี้:
<trim prefix = "status = case" suffix = "end,"> <foreach collection = "list" item = "item" index = "index"> <ถ้า test = "item.status! = null และ item.status! = -1"> เมื่อ id = #{item.id} id =#{item.id} จากนั้น mydata_table.status // นี่คือข้อมูลต้นฉบับ </if> </foreach> </trim>การอัปเดตแบทช์โดยรวมนั้นเขียนขึ้นดังนี้:
<update id = "updateBatch" parameterType = "java.util.list"> อัปเดต mydata_table <trim prefix = "set" suffixoverrides = ","> <trim prefix = "สถานะ = case" suffix = "end,"> <foreach collection = "รายการ" รายการ " -1 "> เมื่อ id =#{item.id} จากนั้น#{item.status} </if> <ถ้า test =" item.status == null หรือ item.status == -1 "> เมื่อ id =#{item.id}" indeach> "indeach> item = "item" separator = "," open = "(" close = ")"> #{item.id, jdbcType = bigint} </foreach> </update>แบทช์และฐานข้อมูลหลักนี้สามารถอัปเดตข้อมูลทั้งหมดในการเชื่อมต่อฐานข้อมูลหลีกเลี่ยงค่าใช้จ่ายของการสร้างฐานข้อมูลบ่อยครั้งและการตัดการเชื่อมต่อและปรับปรุงประสิทธิภาพการปรับปรุงข้อมูลอย่างมาก อย่างไรก็ตามปัญหาคือหากเกิดข้อผิดพลาดในการอัปเดตในระหว่างกระบวนการนี้มันจะยากที่จะรู้ว่าข้อมูลใดผิด หากใช้การรับประกันการทำธุรกรรมของข้อมูลเองแล้วเมื่อเกิดข้อผิดพลาดการอัปเดตทั้งหมดจะถูกย้อนกลับโดยอัตโนมัติ และวิธีนี้มักจะมีแนวโน้มที่จะเกิดข้อผิดพลาดมากขึ้น ดังนั้นวิธีการแก้ปัญหาปกติคือการประนีประนอมนั่นคือการอัปเดตบางส่วนของมันในแบตช์ (การปนเปื้อนเสร็จสิ้นเช่นมีข้อมูลทั้งหมด 1,000 ชิ้นและข้อมูล 100 ชิ้นได้รับการอัปเดตในแต่ละครั้ง) สิ่งนี้สามารถแบ่งปันความน่าจะเป็นของข้อผิดพลาดและง่ายต่อการค้นหาข้อผิดพลาด
แน่นอนว่าหากจำนวนข้อมูลมีขนาดใหญ่มากการอัปเดตชุดนี้จะนำไปสู่การอัปเดตที่ไม่มีประสิทธิภาพ (ตัวอย่างเช่นหากมีการอัปเดต 100 รายการในแต่ละครั้งหากมีการอัปเดตข้อมูล 1 พันล้านครั้งจะต้องมีการอัปเดต 10 ล้านครั้งเพื่อสร้างแบทช์ 10 ล้านครั้ง ในเวลานี้คุณอาจจะสามารถพิจารณาวิธีแก้ปัญหาอื่น ๆ เช่นการแนะนำกลไกการแคช
สรุป
ด้านบนเป็นแบทช์อัพเดทที่แนะนำโดยตัวแก้ไขให้คุณโดยใช้ UpdateBatch ใน MyBatis ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับทุกคนในเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!