เมื่อใดที่ฉันควรใช้ตัวแปรตารางเทียบกับตารางชั่วคราวในเซิร์ฟเวอร์ sql


298

ฉันเรียนรู้รายละเอียดเพิ่มเติมในตัวแปรตาราง มันบอกว่าตาราง temp อยู่บนดิสก์เสมอและตัวแปรของตารางอยู่ในหน่วยความจำกล่าวคือประสิทธิภาพของตัวแปรตารางดีกว่าตาราง temp เนื่องจากตัวแปรตารางใช้การดำเนินการ IO น้อยกว่าตาราง temp

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

แต่ฉันไม่รู้ว่า "บันทึกมากเกินไป" คืออะไร 100,000 บันทึก หรือ 1,000,000 บันทึก ฉันจะทราบได้อย่างไรว่าตัวแปรตารางที่ฉันใช้อยู่ในหน่วยความจำหรือบนดิสก์? มีฟังก์ชั่นหรือเครื่องมือใด ๆ ใน SQL Server 2005 เพื่อวัดมาตราส่วนของตัวแปรตารางหรือแจ้งให้ฉันทราบเมื่อตัวแปรตารางถูกวางลงบนดิสก์จากหน่วยความจำ?


5
ตัวแปรตารางมักจะอยู่ในtempDB- ว่า "ในหน่วยความจำ" เป็นตำนาน นอกจากนี้: ตัวแปรตารางจะได้รับการพิจารณาโดยเครื่องมือเพิ่มประสิทธิภาพคิวรีเพื่อเก็บแถวหนึ่งไว้อย่างแน่นอน - หากคุณมีมากขึ้นสิ่งนี้อาจนำไปสู่แผนการปฏิบัติที่ไม่ดีอย่างจริงจัง
marc_s

คุณอาจพบว่าstackoverflow.com/questions/27894/
Igor Borisenko

2
@marc_s - คุณสามารถวาง "เกือบ" ในคำสั่งนั้นได้ เป็นเสมอtempdb(แต่อาจจะอยู่ในความทรงจำทั้งหมด)
Martin Smith

2
ด้วย SQL 2014 คุณสามารถสร้างตัวแปรตารางในหน่วยความจำได้
paparazzo

คำตอบ:


362

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

ฉันได้เขียนคำตอบมากมายในเว็บไซต์ DBA เพื่อดูความแตกต่างระหว่างสองประเภทของวัตถุ สิ่งนี้ยังตอบคำถามของคุณเกี่ยวกับดิสก์ vs หน่วยความจำ (ฉันไม่เห็นความแตกต่างอย่างมีนัยสำคัญระหว่างพฤติกรรมทั้งสอง)

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

ที่คุณมีตัวเลือกคำแนะนำอยู่ด้านล่าง (แม้ว่าวิธีการที่เชื่อถือได้ที่สุดก็คือการทดสอบทั้งกับภาระงานเฉพาะของคุณ)

  1. หากคุณต้องการดัชนีที่ไม่สามารถสร้างบนตัวแปรตารางได้แน่นอนคุณจะต้องมี#temporaryตาราง รายละเอียดของรุ่นนี้ขึ้นอยู่กับรุ่นอย่างไรก็ตาม สำหรับ SQL Server 2012 และต่ำกว่าดัชนีเท่านั้นที่สามารถสร้างขึ้นได้ในตัวแปรตารางคือสิ่งที่สร้างโดยนัยผ่านทางUNIQUEหรือPRIMARY KEYข้อ จำกัด SQL Server 2014 CREATE INDEXแนะนำไวยากรณ์ดัชนีอินไลน์สำหรับย่อยของในตัวเลือกที่มีอยู่ สิ่งนี้ได้รับการขยายตั้งแต่เพื่ออนุญาตเงื่อนไขดัชนีที่กรองแล้ว ดัชนีที่มีINCLUDEคอลัมน์ -d หรือดัชนี columnstore ยังไม่สามารถสร้างบนตัวแปรตารางได้

  2. หากคุณจะเพิ่มและลบแถวจำนวนมากซ้ำ ๆ จากตารางให้ใช้#temporaryตาราง ที่สนับสนุนTRUNCATE(ซึ่งจะมีประสิทธิภาพมากกว่าDELETEสำหรับตารางขนาดใหญ่) และยังแทรกตามมาต่อไปนี้TRUNCATEจะมีประสิทธิภาพที่ดีขึ้นกว่าที่ดังต่อไปนี้เป็นที่แสดงที่นี่DELETE

  3. หากคุณจะลบหรืออัปเดตแถวจำนวนมากตาราง temp อาจทำงานได้ดีกว่าตัวแปรตาราง - หากสามารถใช้การแชร์ rowset ได้ (ดู "ผลของการแชร์ rowset" ด้านล่าง)
  4. หากแผนที่ดีที่สุดโดยใช้ตารางจะแตกต่างกันไปขึ้นอยู่กับข้อมูลจากนั้นใช้#temporaryตาราง ที่รองรับการสร้างสถิติซึ่งช่วยให้แผนสามารถคอมไพล์ใหม่แบบไดนามิกตามข้อมูล (แม้ว่าสำหรับแคชชั่วคราวตารางในกระบวนงานที่เก็บไว้พฤติกรรมการคอมไพล์ซ้ำจะต้องเข้าใจแยกต่างหาก)
  5. หากแผนที่ดีที่สุดสำหรับแบบสอบถามที่ใช้ตารางไม่น่าจะเปลี่ยนแปลงคุณอาจพิจารณาตัวแปรตารางเพื่อข้ามค่าใช้จ่ายในการสร้างสถิติและคอมไพล์ซ้ำ (อาจต้องมีคำแนะนำเพื่อแก้ไขแผนที่คุณต้องการ)
  6. หากแหล่งข้อมูลที่แทรกลงในตารางนั้นมาจากSELECTคำแถลงที่อาจมีราคาแพงให้พิจารณาว่าการใช้ตัวแปรตารางจะป้องกันความเป็นไปได้ของสิ่งนี้โดยใช้แผนคู่ขนาน
  7. ถ้าคุณต้องการข้อมูลในตารางเพื่อเอาตัวรอดการย้อนกลับของธุรกรรมผู้ใช้ภายนอกจากนั้นใช้ตัวแปรตาราง กรณีการใช้งานที่เป็นไปได้สำหรับกรณีนี้อาจเป็นการบันทึกความคืบหน้าของขั้นตอนต่าง ๆ ในชุดงาน SQL แบบยาว
  8. เมื่อใช้#tempตารางภายในล็อกธุรกรรมผู้ใช้สามารถจัดขึ้นนานกว่าสำหรับตัวแปรตาราง (อาจจนกว่าจะสิ้นสุดของการทำธุรกรรม VS ท้ายของคำสั่งขึ้นอยู่กับชนิดของล็อคและระดับแยก) และยังสามารถป้องกันการตัดของtempdbล็อกธุรกรรมจนกว่า การทำธุรกรรมของผู้ใช้จะสิ้นสุดลง ดังนั้นสิ่งนี้อาจสนับสนุนการใช้ตัวแปรตาราง
  9. ภายในรูทีนที่เก็บไว้ทั้งตัวแปรตารางและตารางชั่วคราวสามารถแคชได้ การบำรุงรักษาข้อมูลเมตาสำหรับตัวแปรตารางแคชน้อยกว่าสำหรับ#temporaryตาราง บ๊อบวอร์ดชี้ให้เห็นในtempdbการนำเสนอของเขาว่าสิ่งนี้อาจทำให้เกิดการโต้แย้งเพิ่มเติมในตารางระบบภายใต้เงื่อนไขของการเกิดพร้อมกันสูง นอกจากนี้เมื่อต้องรับมือกับปริมาณขนาดเล็กของข้อมูลนี้สามารถทำให้ความแตกต่างที่สามารถวัดประสิทธิภาพการทำงาน

ผลกระทบของการแบ่งปัน rowset

DECLARE @T TABLE(id INT PRIMARY KEY, Flag BIT);

CREATE TABLE #T (id INT PRIMARY KEY, Flag BIT);

INSERT INTO @T 
output inserted.* into #T
SELECT TOP 1000000 ROW_NUMBER() OVER (ORDER BY @@SPID), 0
FROM master..spt_values v1, master..spt_values v2

SET STATISTICS TIME ON

/*CPU time = 7016 ms,  elapsed time = 7860 ms.*/
UPDATE @T SET Flag=1;

/*CPU time = 6234 ms,  elapsed time = 7236 ms.*/
DELETE FROM @T

/* CPU time = 828 ms,  elapsed time = 1120 ms.*/
UPDATE #T SET Flag=1;

/*CPU time = 672 ms,  elapsed time = 980 ms.*/
DELETE FROM #T

DROP TABLE #T

2
สวัสดีคุณ Martin Smith ในกรณีที่ฉันต้องการเก็บชุดของค่ารหัสเพื่อใช้ในแบบสอบถามอื่น ๆ ภายในขั้นตอนการจัดเก็บ คุณจะแนะนำอะไรให้ฉัน
Jeancarlo Fontalvo

@JeancarloFontalvo - ตัวแปรตารางที่มีคีย์หลักบนidและการใช้OPTION (RECOMPILE)อาจจะดีสำหรับที่ - แต่ทดสอบทั้งสอง
Martin Smith

การช่วงชิงข้อมูลเมตาจะเหมือนกันสำหรับทั้ง temp table และ table table?
Syed Aqeel Ashiq

@Syed โดยทั่วไปน้อยกว่าสำหรับทีวี สามารถปลดล็อคก่อนหน้านี้ได้หากอยู่ในธุรกรรมผู้ใช้ ดูลิงค์บ็อบวอร์ดด้วย
Martin Smith

73

ใช้ตัวแปรตารางหากปริมาณข้อมูลน้อยมาก (พันไบต์)

ใช้ตารางชั่วคราวสำหรับข้อมูลจำนวนมาก

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

ในตัวอย่างของฉันฉันแค่ต้องการวางแถวประมาณ 20 แถวในรูปแบบและแก้ไขเป็นกลุ่มก่อนที่จะใช้เพื่ออัปเดต / INSERT ตารางถาวร ดังนั้นตัวแปรตารางจึงสมบูรณ์แบบ

แต่ฉันยังใช้ SQL เพื่อเติมเต็มหลายพันแถวในเวลาและฉันสามารถพูดได้อย่างแน่นอนว่าตารางชั่วคราวทำงานได้ดีกว่าตัวแปรตาราง

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

ความเข้าใจของฉันส่วนใหญ่จะขึ้นอยู่กับhttp://www.developerfusion.com/article/84397/table-variables-v-temporary-tables-in-sql-server/ซึ่งมีรายละเอียดมากขึ้น


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

42

Microsoft พูดที่นี่

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


14

ฉันเห็นด้วยกับ Abacus ทั้งหมด (ขออภัย - ไม่มีคะแนนเพียงพอที่จะแสดงความคิดเห็น)

นอกจากนี้โปรดจำไว้ว่าไม่จำเป็นต้องคำนึงถึงจำนวนระเบียนที่คุณมี แต่ขนาดของระเบียนของคุณ

ตัวอย่างเช่นคุณเคยพิจารณาความแตกต่างด้านประสิทธิภาพระหว่าง 1,000 เรคคอร์ดที่มี 50 คอลัมน์ต่อ 100,000 เรคคอร์ดโดยมีเพียง 5 คอลัมน์ต่อเรคคอร์ด

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


4

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

วิธีทดสอบตารางชั่วคราว:

  • เปิดโปรแกรมจัดการคิวรี่ studio studio
  • สร้างตารางชั่วคราว
  • เปิดหน้าต่างตัวแก้ไขคิวรีอื่น
  • เลือกจากตารางนี้ "ว่าง"

วิธีทดสอบตารางตัวแปร:

  • เปิดโปรแกรมจัดการคิวรี่ studio studio
  • สร้างตารางตัวแปร
  • เปิดหน้าต่างตัวแก้ไขคิวรีอื่น
  • เลือกจากตารางนี้ "ไม่พร้อมใช้งาน"

สิ่งอื่นที่ฉันมีประสบการณ์คือถ้าสคีมาของคุณไม่มีGRANTสิทธิ์สร้างตารางให้ใช้ตารางตัวแปร


3

การเขียนข้อมูลในตารางที่ประกาศdeclare @tbและหลังจากเข้าร่วมกับตารางอื่นฉันรู้ว่าเวลาตอบสนองเมื่อเทียบกับตารางชั่วคราวtempdb .. # tbนั้นสูงกว่ามาก

เมื่อฉันเข้าร่วมกับ@tbเวลาจะนานกว่าที่จะส่งคืนผลลัพธ์ซึ่งต่างจาก#tmการกลับมาเกือบจะทันที

ฉันทำการทดสอบโดยมี 10,000 แถวเข้าร่วมและเข้าร่วมกับตารางอื่น ๆ 5 ตาราง


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