วิธีการติดตั้งอัลกอริธึมตาม / UDF


13

ฉันมีอัลกอริทึมที่ฉันต้องเรียกใช้กับทุกแถวในตารางที่มี 800K แถวและ 38 คอลัมน์ อัลกอริทึมถูกนำมาใช้ใน VBA และทำการคำนวณทางคณิตศาสตร์โดยใช้ค่าจากบางคอลัมน์เพื่อจัดการคอลัมน์อื่น

ปัจจุบันฉันใช้ Excel (ADO) เพื่อสอบถาม SQL และใช้ VBA กับเคอร์เซอร์ฝั่งไคลเอ็นต์เพื่อใช้อัลกอริทึมโดยวนซ้ำทุกแถว มันใช้งานได้ แต่ใช้เวลา 7 ชั่วโมงในการทำงาน

รหัส VBA นั้นซับซ้อนพอที่จะทำการถอดรหัสเป็น T-SQL ได้เป็นจำนวนมาก

ฉันได้อ่านเกี่ยวกับการรวม CLR และ UDF เป็นเส้นทางที่เป็นไปได้ ฉันคิดเกี่ยวกับการใส่รหัส VBA ในงานสคริปต์ SSIS เพื่อเข้าใกล้ฐานข้อมูล แต่แน่ใจว่ามีผู้เชี่ยวชาญด้านวิธีการสำหรับปัญหาด้านประสิทธิภาพประเภทนี้อยู่

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

ความช่วยเหลือใด ๆ ที่บอกล่วงหน้าถึงวิธีการรับประสิทธิภาพที่ดีที่สุดกับปัญหาประเภทนี้

--Edit

ขอบคุณสำหรับความคิดเห็นฉันใช้ MS SQL 2014 Enterprise ต่อไปนี้เป็นรายละเอียดเพิ่มเติม:

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

คำถามของฉันเกี่ยวกับระเบียบวิธีมากกว่าอัลกอริทึมจริง: ถ้าฉันต้องการบรรลุการคำนวณแบบขนานบนหลายแถวพร้อมกันตัวเลือกของฉันคืออะไร

ฉันเห็นรหัสใหม่เป็น T-SQL ซึ่งเป็นงานที่มาก แต่เป็นไปได้อย่างไรก็ตามนักพัฒนาอัลกอริทึมทำงานใน VBA และมันเปลี่ยนบ่อยดังนั้นฉันต้องซิงค์กับเวอร์ชั่น T-SQL และตรวจสอบใหม่ทุกครั้ง เปลี่ยนแปลง

T-SQL เป็นวิธีเดียวที่จะใช้ฟังก์ชั่นการตั้งค่าหรือไม่


3
SSIS สามารถนำเสนอการขนานแบบเนทีฟโดยสมมติว่าคุณออกแบบการไหลของข้อมูลได้ดี นั่นเป็นภารกิจที่คุณต้องการเพราะคุณต้องทำการคำนวณแบบแถวต่อแถว แต่ที่กล่าวไว้เว้นแต่คุณจะให้รายละเอียดเฉพาะเจาะจง (สคีมาการคำนวณที่เกี่ยวข้องและการคำนวณเหล่านี้หวังว่าจะบรรลุผล) เป็นไปไม่ได้ที่จะช่วยคุณเพิ่มประสิทธิภาพ พวกเขากล่าวว่าสิ่งที่เขียนในการชุมนุมสามารถทำให้สำหรับรหัสที่เร็วที่สุด แต่ถ้าเช่นฉันคุณดูดสยองที่มันไม่ได้เป็นไปอย่างมีประสิทธิภาพในทุก
billinkc

2
หากคุณดำเนินการแต่ละแถวอย่างอิสระคุณสามารถแยกแถว 800K ออกเป็นNแบทช์และเรียกใช้Nอินสแตนซ์ของอัลกอริทึมของคุณในNโปรเซสเซอร์ / คอมพิวเตอร์แยกต่างหาก ในทางกลับกันคอขวดหลักของคุณคืออะไร - ถ่ายโอนข้อมูลจาก SQL Server ไปยัง Excel หรือการคำนวณจริง หากคุณเปลี่ยนฟังก์ชั่น VBA เพื่อส่งกลับผลลัพธ์หุ่นจำลองทันทีกระบวนการทั้งหมดใช้เวลานานแค่ไหน? หากยังคงใช้เวลาหลายชั่วโมงคอขวดจะถูกถ่ายโอนข้อมูล หากใช้เวลาไม่กี่วินาทีคุณจะต้องเพิ่มประสิทธิภาพโค้ด VBA ที่ใช้ในการคำนวณ
Vladimir Baranov

มันเป็นตัวกรองที่ถูกเรียกว่าเป็นกระบวนงานที่เก็บไว้: SELECT AVG([AD_Sensor_Data]) OVER (ORDER BY [RowID] ROWS BETWEEN 5 PRECEDING AND 5 FOLLOWING) as 'AD_Sensor_Data' FROM [AD_Points] WHERE [FileID] = @FileID ORDER BY [RowID] ASC ในสตูดิโอการจัดการฟังก์ชั่นนี้ซึ่งได้รับการเรียกสำหรับแต่ละแถวใช้เวลา 50mS
medwar19

1
ดังนั้นการสืบค้นที่ใช้เวลา 50 มิลลิวินาทีและดำเนินการ 800000 ครั้ง (11 ชั่วโมง) จึงเป็นสิ่งที่ต้องใช้เวลา @FileID ไม่ซ้ำกันสำหรับแต่ละแถวหรือมีข้อมูลซ้ำกันดังนั้นคุณสามารถลดจำนวนครั้งที่คุณต้องดำเนินการค้นหาได้หรือไม่ นอกจากนี้คุณยังสามารถคำนวณการหมุนเฉลี่ยสำหรับ fileid ทั้งหมดไปยังตารางการแสดงในครั้งเดียว (ใช้พาร์ติชันบน FileID) จากนั้นทำการสืบค้นตารางนั้นโดยไม่จำเป็นต้องใช้ฟังก์ชั่นหน้าต่างสำหรับแต่ละแถว (FileID, RowID)การติดตั้งที่ดีที่สุดสำหรับการดูตารางการแสดงละครเหมือนมันควรจะมีดัชนีคลัสเตอร์บน
Mikael Eriksson

1
สิ่งที่ดีที่สุดคือถ้าคุณสามารถลบความจำเป็นที่จะต้องสัมผัสฐานข้อมูลสำหรับแต่ละแถว นั่นหมายความว่าคุณต้องไป TSQL และอาจเข้าร่วมกับการสืบค้น AVG แบบกลิ้งหรือดึงข้อมูลที่เพียงพอสำหรับแต่ละแถวดังนั้นทุกอย่างที่อัลกอริทึมต้องการอยู่ตรงนั้นบนแถวบางทีเข้ารหัสในบางวิธีถ้ามีแถวย่อยหลายแถว (xml) .
Mikael Eriksson

คำตอบ:


8

เกี่ยวกับวิธีการผมเชื่อว่าคุณกำลังเห่า b-tree ;-) ที่ไม่ถูกต้อง

สิ่งที่เรารู้:

อันดับแรกให้รวบรวมและตรวจสอบสิ่งที่เรารู้เกี่ยวกับสถานการณ์:

  • การคำนวณที่ซับซ้อนจะต้องมีการดำเนินการ:
    • สิ่งนี้ต้องเกิดขึ้นในทุกแถวของตารางนี้
    • อัลกอริทึมเปลี่ยนแปลงบ่อยครั้ง
    • อัลกอริทึม ... [ใช้] ค่าจากบางคอลัมน์เพื่อจัดการคอลัมน์อื่น
    • เวลาประมวลผลปัจจุบันคือ: 7 ชั่วโมง
  • โต๊ะ:
    • มี 800,000 แถว
    • มี 38 คอลัมน์
  • แอปพลิเคชันส่วนหลัง:
  • ฐานข้อมูลคือ SQL Server 2014, Enterprise Edition
  • มีขั้นตอนการจัดเก็บที่ถูกเรียกสำหรับทุกแถว:

    • ใช้เวลา 50 ms (โดยเฉลี่ยถือว่าฉันใช้งาน)
    • จะส่งกลับประมาณ 4000 แถว
    • คำจำกัดความ (อย่างน้อยก็ในบางส่วน) คือ:

      SELECT AVG([AD_Sensor_Data])
                 OVER (ORDER BY [RowID] ROWS BETWEEN 5 PRECEDING AND 5 FOLLOWING)
                 as 'AD_Sensor_Data'
      FROM   [AD_Points]
      WHERE  [FileID] = @FileID
      ORDER BY [RowID] ASC
      

สิ่งที่เราสามารถคาดเดาได้:

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

ทิศทางปัจจุบันของความคิดในความคิดเห็นคือปัญหาสำคัญคือการถ่ายโอนข้อมูลระหว่าง SQL Server และ Excel เป็นเช่นนั้นจริงหรือ หากมีการเรียกกระบวนงานที่เก็บไว้สำหรับแต่ละ 800,000 แถวและใช้เวลา 50 ms ต่อการโทรแต่ละครั้ง (เช่นต่อแต่ละแถว) ซึ่งจะเพิ่มขึ้นเป็น 40,000 วินาที (ไม่ใช่ ms) และนั่นเทียบเท่ากับ 666 นาที (hhmm ;-) หรือเพียง 11 ชั่วโมง ทว่ากระบวนการทั้งหมดนี้ใช้เวลาเพียง 7 ชั่วโมงในการดำเนินการ เรามีเวลาทั้งหมด 4 ชั่วโมงแล้วและเรายังเพิ่มเวลาเพื่อทำการคำนวณหรือบันทึกผลลัพธ์กลับไปยัง SQL Server ดังนั้นสิ่งที่ไม่ถูกต้องที่นี่

ดูคำจำกัดความของกระบวนการจัดเก็บมีเพียงพารามิเตอร์ป้อนเข้า@FileIDเท่านั้น @RowIDไม่มีตัวกรองใด ๆ ดังนั้นฉันสงสัยว่าหนึ่งในสองสถานการณ์ต่อไปนี้จะเกิดขึ้น:

  • ขั้นตอนการจัดเก็บนี้ไม่ได้รับการเรียกจริง ๆ สำหรับแต่ละแถว แต่จะมีการเรียกต่อแต่ละแถว@FileIDซึ่งจะมีความยาวประมาณ 4000 แถว หากจำนวนแถวที่ระบุไว้ 4,000 คืนเป็นจำนวนที่สอดคล้องกันจะมีเพียง 200 แถวใน 800,000 แถว และการประหารชีวิต 200 ครั้งโดยใช้ 50 มิลลิวินาทีในแต่ละจำนวนใช้เวลาเพียง 10 วินาทีจาก 7 ชั่วโมงนั้น
  • หากขั้นตอนการจัดเก็บนี้ได้รับการเรียกสำหรับทุกแถวจริง ๆ แล้วจะไม่เป็นครั้งแรกที่มีการ@FileIDส่งผ่านใหม่ใช้เวลานานกว่าเล็กน้อยในการดึงแถวใหม่เข้าสู่ Buffer Pool แต่โดยทั่วไปแล้วการประมวลผล 3999 ครั้งถัดไป แคชใช่ไหม

ผมคิดว่าการมุ่งเน้นเกี่ยวกับเรื่องนี้ "กรอง" ขั้นตอนการเก็บหรือการถ่ายโอนข้อมูลใด ๆ จาก SQL Server ไปยัง Excel เป็นปลาชนิดหนึ่งสีแดง

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

  • มี 800,000 แถว
  • การดำเนินการทำงานได้ครั้งละหนึ่งแถว
  • ข้อมูลจะถูกบันทึกกลับไปยัง SQL Server ดังนั้น "[ใช้] ค่าจากบางคอลัมน์เพื่อจัดการคอลัมน์อื่น ๆ " [my em phas is ;-)]

ฉันสงสัยว่า:

  • ในขณะที่มีห้องสำหรับปรับปรุงในการดึงข้อมูลและการคำนวณทำให้ดีขึ้นเหล่านั้นจะไม่ลดลงอย่างมีนัยสำคัญในเวลาการประมวลผล
  • คอขวดใหญ่กำลังออกUPDATEแถลงการณ์แยกต่างหาก 800,000 ข้อความซึ่งเป็นธุรกรรมแยกกัน 800,000 รายการ

คำแนะนำของฉัน (ขึ้นอยู่กับข้อมูลที่มีอยู่ในปัจจุบัน):

  1. การปรับปรุงที่ใหญ่ที่สุดของคุณคือการอัปเดตหลายแถวพร้อมกัน (เช่นในการทำธุรกรรมเดียว) คุณควรอัพเดตกระบวนการของคุณให้ทำงานในรูปแบบของแต่ละกระบวนการFileIDแทนที่จะเป็นแต่ละRowIDกระบวนการ ดังนั้น:

    1. อ่านแถวทั้งหมด 4000 แถวFileIDในแถวลำดับ
    2. อาร์เรย์ควรมีองค์ประกอบที่เป็นตัวแทนของเขตข้อมูลที่ถูกจัดการ
    3. วนรอบอาร์เรย์เพื่อประมวลผลแต่ละแถวเหมือนที่คุณทำอยู่ในปัจจุบัน
    4. เมื่อFileIDคำนวณแถวทั้งหมดในอาร์เรย์แล้ว (เช่นสำหรับรายการนี้):
      1. เริ่มทำธุรกรรม
      2. เรียกแต่ละการปรับปรุงต่อแต่ละ RowID
      3. หากไม่มีข้อผิดพลาดให้ทำธุรกรรม
      4. หากมีข้อผิดพลาดเกิดขึ้นการย้อนกลับและการจัดการอย่างเหมาะสม
  2. หากดัชนีคลัสเตอร์ของคุณยังไม่ได้กำหนดไว้(FileID, RowID)ดังนั้นคุณควรพิจารณา (ตามที่ @MikaelEriksson แนะนำในการแสดงความคิดเห็นในคำถาม) มันจะไม่ช่วย UPDATEs เดี่ยวเหล่านี้ แต่ที่จะปรับปรุงการดำเนินงานรวมดังกล่าวเป็นสิ่งที่คุณกำลังทำในสิ่งที่ "กรอง" FileIDขั้นตอนการเก็บน้อยเล็กน้อยเนื่องจากพวกเขาจะขึ้นอยู่ทั้งหมดบน

  3. คุณควรพิจารณาย้ายตรรกะไปเป็นภาษาที่รวบรวม ฉันอยากจะแนะนำให้สร้างแอป. NET WinForms หรือแม้แต่แอพคอนโซล ฉันชอบแอพคอนโซลเพราะมันง่ายต่อการกำหนดเวลาผ่าน SQL Agent หรือ Windows Scheduled Tasks มันไม่สำคัญว่าจะทำใน VB.NET หรือ C # VB.NET อาจเหมาะสมกับผู้พัฒนาของคุณมากขึ้น แต่จะมีช่วงการเรียนรู้อยู่บ้าง

    ฉันไม่เห็นเหตุผลใด ๆ ณ จุดนี้เพื่อย้ายไปยัง SQLCLR หากอัลกอริทึมเปลี่ยนแปลงบ่อยนั่นจะทำให้เกิดความรำคาญต้องปรับใช้แอสเซมบลีตลอดเวลาอีกครั้ง การสร้างแอป Console ขึ้นมาใหม่และวาง. exe ไว้ในโฟลเดอร์แชร์ที่เหมาะสมบนเครือข่ายเพื่อให้คุณเรียกใช้โปรแกรมเดียวกันและมันเพิ่งเกิดขึ้นเสมอและทันสมัยอยู่เสมอ

    ฉันไม่คิดว่าการย้ายการประมวลผลอย่างสมบูรณ์ไปยัง T-SQL จะช่วยได้ถ้าปัญหานั้นเป็นสิ่งที่ฉันสงสัยและคุณเพียงแค่ทำการอัพเดทครั้งละหนึ่งครั้ง

  4. หากการประมวลผลถูกย้ายไปยัง. NET คุณสามารถใช้พารามิเตอร์ที่มีมูลค่าของตาราง (TVPs) เพื่อที่คุณจะส่งผ่านอาร์เรย์ไปยังกระบวนงานที่เก็บไว้ซึ่งจะเรียกใช้การรวมUPDATEนั้นกับตัวแปรตาราง TVP และเป็นธุรกรรมเดียว . TVP ควรเร็วกว่าการINSERTจัดกลุ่ม4000 s เป็นธุรกรรมเดียว แต่กำไรที่ได้มาจากการใช้ TVP มากกว่า 4,000 INSERTรายการใน 1 ธุรกรรมนั้นไม่ได้มีนัยสำคัญเท่ากับการปรับปรุงที่เห็นเมื่อย้ายจาก 800,000 ธุรกรรมแยกต่างหากไปเป็น 200 ธุรกรรมของ 4000 แถวต่อครั้ง

    ตัวเลือก TVP นั้นไม่มีอยู่ในฝั่ง VBA แต่มีบางคนที่ทำงานด้วยวิธีการทดสอบที่คุ้มค่า:

    ฉันจะปรับปรุงประสิทธิภาพของฐานข้อมูลได้อย่างไรเมื่อไปจาก VBA เป็น SQL Server 2008 R2

  5. หากตัวกรอง proc ใช้เฉพาะFileIDในWHEREข้อและถ้าเรียกว่า proc จริง ๆ ต่อแต่ละแถวคุณสามารถประหยัดเวลาในการประมวลผลได้โดยการแคชผลลัพธ์ของการเรียกใช้ครั้งแรกและใช้ส่วนที่เหลือของแถวต่อFileIDไป ขวา?

  6. เมื่อคุณได้รับการประมวลผลที่ทำต่อ FileID , แล้วเราสามารถเริ่มต้นการพูดคุยเกี่ยวกับการประมวลผลแบบขนาน แต่นั่นอาจไม่จำเป็น ณ จุดนั้น :) ระบุว่าคุณกำลังเผชิญกับ 3 ส่วนที่ไม่เหมาะเป็นอย่างยิ่ง: Excel, VBA, และธุรกรรม 800k, การพูดคุยของ SSIS, หรือรูปสี่เหลี่ยมด้านขนานหรือผู้รู้อะไรจะได้รับการปรับให้เหมาะสมก่อน / สิ่งที่ประเภทม้า . หากเราสามารถทำให้กระบวนการ 7 ชั่วโมงนี้ลดลงเหลือ 10 นาทีหรือน้อยกว่าคุณจะยังคงคิดหาวิธีเพิ่มเติมเพื่อให้เร็วขึ้นหรือไม่? มีเวลาในการบรรลุเป้าหมายที่คุณมีอยู่ในใจหรือไม่? โปรดทราบว่าเมื่อการประมวลผลเสร็จสิ้นต่อ FileID พื้นฐานถ้าคุณมี VB.NET Console App (เช่น command-line .EXE) จะไม่มีอะไรหยุดคุณจากการรัน FileIDs ในเวลาไม่กี่ครั้ง :) ไม่ว่าจะผ่านขั้นตอน CmdExec ของ SQL Agent หรือ Windows Scheduled Tasks เป็นต้น

และคุณสามารถใช้วิธี "แบ่งเป็นระยะ" และทำการปรับปรุงได้ตลอดเวลา เช่นเริ่มต้นด้วยการอัปเดตต่อFileIDและด้วยการใช้หนึ่งธุรกรรมสำหรับกลุ่มนั้น จากนั้นดูว่าคุณสามารถทำให้ TVP ทำงานได้หรือไม่ จากนั้นดูเกี่ยวกับการรับรหัสนั้นและย้ายไปยัง VB.NET (และ TVPs ทำงานใน. NET เพื่อที่จะได้พอร์ตอย่างสวยงาม)


สิ่งที่เราไม่ทราบว่ายังสามารถช่วย:

  • "ตัวกรอง" กระบวนงานที่เก็บไว้ทำงานต่อ RowIDหรือต่อ FileIDหรือไม่ เรามีคำจำกัดความที่ครบถ้วนของกระบวนงานที่เก็บไว้หรือไม่?
  • สคีมาแบบเต็มของตาราง ตารางนี้กว้างเท่าไหร่ มีฟิลด์ความยาวแปรผันจำนวนเท่าใด NULLable มีกี่เขตข้อมูล ถ้ามีค่า NULLable มี NULL จำนวนเท่าใด
  • ดัชนีสำหรับตารางนี้ มันแบ่งพาร์ติชันหรือไม่ กำลังใช้การบีบอัด ROW หรือ PAGE หรือไม่
  • ตารางนี้มีขนาดเท่าใดสำหรับ MB / GB
  • การบำรุงรักษาดัชนีมีการจัดการอย่างไรสำหรับตารางนี้ ดัชนีมีการแยกส่วนอย่างไร สถิติมีการอัปเดตอย่างไร
  • กระบวนการอื่นใดที่เขียนลงในตารางนี้ในขณะที่กระบวนการนี้ใช้เวลา 7 ชั่วโมงหรือไม่? แหล่งที่มาของความขัดแย้ง
  • กระบวนการอื่นใดที่อ่านจากตารางนี้ในขณะที่กระบวนการนี้ใช้เวลา 7 ชั่วโมงหรือไม่? แหล่งที่มาของความขัดแย้ง

อัปเดต 1:

**ดูเหมือนจะมีความสับสนเกี่ยวกับสิ่งที่ VBA (Visual Basic สำหรับแอปพลิเคชัน) และสิ่งที่สามารถทำได้ด้วยดังนั้นนี่เป็นเพียงเพื่อให้แน่ใจว่าเราทุกคนอยู่ในหน้าเว็บเดียวกัน:


อัปเดต 2:

อีกหนึ่งจุดที่ควรพิจารณา: การเชื่อมต่อถูกจัดการอย่างไร? รหัส VBA เปิดและปิดการเชื่อมต่อต่อการดำเนินการแต่ละครั้งหรือไม่หรือเป็นการเปิดการเชื่อมต่อเมื่อเริ่มต้นกระบวนการและปิดเมื่อสิ้นสุดกระบวนการ (เช่น 7 ชั่วโมงต่อมา) หรือไม่ แม้ว่าจะมีการรวมการเชื่อมต่อ (ซึ่งโดยค่าเริ่มต้นควรเปิดใช้งานสำหรับ ADO) ก็ยังคงมีผลกระทบค่อนข้างมากระหว่างการเปิดและปิดหนึ่งครั้งซึ่งต่างจากการเปิดและปิดทั้ง 800,200 หรือ 1,600,000 ครั้ง ค่าเหล่านั้นจะขึ้นอยู่กับอย่างน้อย 800,000 UPDATEs รวมทั้ง EXEC 200 หรือ 800k EXECs (ขึ้นอยู่กับความถี่ในการดำเนินการตัวกรองที่จัดเก็บจริง)

ปัญหาของการเชื่อมต่อมากเกินไปนี้ได้รับการลดลงโดยอัตโนมัติตามคำแนะนำที่ฉันระบุไว้ข้างต้น ด้วยการสร้างธุรกรรมและทำ UPDATE ทั้งหมดภายในธุรกรรมนั้นคุณจะต้องเปิดการเชื่อมต่อนั้นและนำมาใช้ซ้ำสำหรับแต่ละUPDATEรายการ ไม่ว่าการเชื่อมต่อจะถูกเปิดไว้จากการโทรเริ่มต้นเพื่อรับ 4000 แถวต่อการดำเนินการที่ระบุFileIDหรือปิดหลังจากนั้นการดำเนินการ "รับ" และเปิดอีกครั้งสำหรับการอัปเดตนั้นส่งผลกระทบน้อยกว่าเพราะตอนนี้เรากำลังพูดถึงความแตกต่าง 200 หรือ 400 การเชื่อมต่อทั้งหมดในกระบวนการทั้งหมด

อัปเดต 3:

ฉันทำการทดสอบอย่างรวดเร็ว โปรดทราบว่านี่เป็นการทดสอบในระดับที่ค่อนข้างเล็กและไม่ใช่การดำเนินการเดียวกันที่แน่นอน (INSERT บริสุทธิ์กับ EXEC + UPDATE) อย่างไรก็ตามความแตกต่างในเวลาที่เกี่ยวข้องกับวิธีการจัดการการเชื่อมต่อและการทำธุรกรรมยังคงมีความเกี่ยวข้องดังนั้นข้อมูลสามารถคาดการณ์ว่าจะมีผลกระทบที่ค่อนข้างคล้ายกันที่นี่

พารามิเตอร์การทดสอบ:

  • SQL Server 2012 Developer Edition (64- บิต), SP2
  • โต๊ะ:

     CREATE TABLE dbo.ManyInserts
     (
        RowID INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
        InsertTime DATETIME NOT NULL DEFAULT (GETDATE()),
        SomeValue BIGINT NULL
     );
    
  • การดำเนินงาน:

    INSERT INTO dbo.ManyInserts (SomeValue) VALUES ({LoopIndex * 12});
  • เม็ดมีดรวมต่อการทดสอบแต่ละครั้ง: 10,000
  • รีเซ็ตต่อการทดสอบแต่ละครั้ง: TRUNCATE TABLE dbo.ManyInserts;(ตามลักษณะของการทดสอบนี้การทำ FREEPROCCACHE, FREESYSTEMCACHE และ DROPCLEANBUFFERS นั้นไม่ได้เพิ่มมูลค่ามากนัก)
  • รุ่นการกู้คืน: SIMPLE (และอาจจะ 1 GB ฟรีในล็อกไฟล์)
  • การทดสอบที่ใช้ธุรกรรมใช้การเชื่อมต่อเดียวโดยไม่คำนึงถึงจำนวนธุรกรรม

ผล:

Test                                   Milliseconds
-------                                ------------
10k INSERTs across 10k Connections     3968 - 4163
10k INSERTs across 1 Connection        3466 - 3654
10k INSERTs across 1 Transaction       1074 - 1086
10k INSERTs across 10 Transactions     1095 - 1169

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


มีวิธี "คนกลาง" ที่ดีสำหรับสิ่งที่แนะนำให้ srutzky และนั่นคือการใช้ PowerShell เพื่อรับข้อมูลที่คุณต้องการจาก SQL Server เรียกสคริปต์ VBA ของคุณเพื่อทำงานข้อมูลแล้วเรียก SP ที่ปรับปรุงใน SQL Server ผ่านคีย์และค่าที่อัพเดตกลับไปยังเซิร์ฟเวอร์ SQL ด้วยวิธีนี้คุณจะรวมชุดตามวิธีการกับสิ่งที่คุณมีอยู่แล้ว
Steve Mangiameli

@SteveMangiameli สวัสดี Steve และขอบคุณสำหรับความคิดเห็น ฉันจะตอบกลับเร็วกว่านี้ แต่ป่วย ฉันสงสัยว่าความคิดของคุณนั้นแตกต่างจากที่ฉันแนะนำ สิ่งบ่งชี้ทั้งหมดคือ Excel ยังจำเป็นต้องมีการเรียกใช้ VBA หรือคุณกำลังแนะนำว่า PowerShell จะแทนที่ ADO และถ้าเร็วกว่าที่ I / O จะคุ้มค่าแม้ว่าเพียงแค่แทนที่ I / O เท่านั้น
โซโลมอน Rutzky

1
ไม่ต้องกังวลดีใจที่รู้สึกดีขึ้น ฉันไม่รู้ว่ามันจะดีกว่า เราไม่รู้ว่าเราไม่รู้อะไรและคุณได้ทำการวิเคราะห์ที่ยอดเยี่ยม แต่ยังต้องทำการตั้งสมมติฐาน I / O อาจมีความสำคัญพอที่จะแทนที่ด้วยตัวเอง เราแค่ไม่รู้ ฉันแค่ต้องการนำเสนอวิธีการอื่นที่อาจเป็นประโยชน์กับสิ่งที่คุณแนะนำ
Steve Mangiameli

@SteveMangiameli ขอบคุณ และขอขอบคุณสำหรับการชี้แจงว่า ฉันไม่แน่ใจเกี่ยวกับทิศทางที่แน่นอนของคุณและคิดว่าดีที่สุดที่จะไม่คิด ใช่ฉันยอมรับว่าการมีตัวเลือกเพิ่มเติมนั้นดีกว่าเนื่องจากเราไม่ทราบว่ามีข้อ จำกัด อะไรบ้างเกี่ยวกับการเปลี่ยนแปลงที่สามารถทำได้ :)
โซโลมอน Rutzky

เฮ้ srutzky ขอบคุณสำหรับความคิดอย่างละเอียด! ฉันได้รับการทดสอบด้าน SQL รับดัชนีและแบบสอบถามที่ปรับให้เหมาะสมและพยายามค้นหาคอขวด ฉันได้ลงทุนในเซิร์ฟเวอร์ที่เหมาะสมตอนนี้ 36cores, 1TB ถอด PCIe SSD เนื่องจาก IO เริ่มทำงาน ตอนนี้เรียกรหัส VB ​​โดยตรงใน SSIS ซึ่งปรากฏขึ้นเพื่อเปิดหลายเธรดสำหรับการดำเนินการแบบขนาน
medwar19

2

IMHO และทำงานจากสมมติฐานที่ว่าไม่เป็นไปได้ที่จะเขียนโค้ดย่อย VBA ลงใน SQL อีกครั้งคุณได้พิจารณาอนุญาตให้สคริปต์ VBA ประเมินผลในไฟล์ Excel แล้วเขียนผลลัพธ์กลับไปยังเซิร์ฟเวอร์ SQL ผ่าน SSIS หรือไม่

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

นอกจากนี้คุณอาจมีสคริปต์ VBA เริ่มโดยทางโปรแกรม (สกปรกเล็กน้อย แต่ฉันเคยใช้workbook_open()คุณสมบัตินี้เพื่อเรียกใช้ "ไฟและลืม" งานในลักษณะนี้ในอดีต)

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

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