เวอร์ชั่นสั้น: การค้นหาดีกว่ามาก
เวอร์ชันย่อน้อยกว่า: การค้นหาโดยทั่วไปจะดีกว่ามาก แต่การค้นหาจำนวนมาก (เกิดจากการออกแบบการค้นหาที่ไม่ดีพร้อมแบบสอบถามย่อยที่มีความสัมพันธ์ที่น่ารังเกียจหรือเนื่องจากคุณทำการสืบค้นจำนวนมากในการดำเนินการเคอร์เซอร์หรือวงอื่น ๆ ) อาจแย่กว่า สแกนโดยเฉพาะอย่างยิ่งหากแบบสอบถามของคุณอาจสิ้นสุดการส่งคืนข้อมูลจากแถวส่วนใหญ่ในตารางที่ได้รับผลกระทบ
ช่วยครอบคลุมทั้งครอบครัวสำหรับการดำเนินการค้นหาข้อมูลเพื่อให้เข้าใจถึงผลกระทบด้านประสิทธิภาพอย่างสมบูรณ์
การสแกนตาราง:เมื่อไม่มีดัชนีใด ๆ ที่เกี่ยวข้องกับการสืบค้นของคุณผู้วางแผนจะถูกบังคับให้ใช้การสแกนตารางซึ่งหมายความว่าทุก ๆ แถวจะถูกมอง สิ่งนี้สามารถส่งผลให้ทุกหน้าเกี่ยวกับข้อมูลของตารางที่อ่านจากดิสก์ซึ่งมักเป็นกรณีที่เลวร้ายที่สุด โปรดทราบว่าสำหรับการสืบค้นบางอย่างมันจะใช้การสแกนแบบตารางแม้ว่าจะมีดัชนีที่มีประโยชน์ - โดยปกติแล้วเป็นเพราะข้อมูลในตารางมีขนาดเล็กจนรบกวนการสำรวจดัชนีได้ง่ายขึ้น (หากเป็นกรณีนี้ วางแผนที่จะเปลี่ยนแปลงเมื่อข้อมูลเติบโตขึ้นโดยสมมติว่าการวัดแบบเลือกเฉพาะของดัชนีนั้นดี)
การสแกนดัชนีด้วยการค้นหาแถว:เมื่อไม่พบดัชนีที่สามารถใช้สำหรับการค้นหาได้โดยตรง แต่ดัชนีที่มีคอลัมน์ที่ถูกต้องจะแสดงการสแกนดัชนี ตัวอย่างเช่นหากคุณมีตารางขนาดใหญ่ที่มี 20 คอลัมน์ที่มีดัชนีในคอลัมน์ 1, col2, col3 และคุณออกSELECT col4 FROM exampletable WHERE col2=616
ในกรณีนี้การสแกนดัชนีเพื่อค้นหาcol2
จะดีกว่าการสแกนทั้งตาราง เมื่อพบแถวที่ตรงกันแล้วหน้าข้อมูลจะต้องอ่านเพื่อรับ col4 สำหรับเอาท์พุท (หรือการเข้าร่วมเพิ่มเติม) ซึ่งเป็นขั้นตอน "การค้นหาบุ๊กมาร์ก" เมื่อคุณเห็นในแผนคิวรี
การสแกนดัชนีโดยไม่มีการค้นหาแถว:หากตัวอย่างด้านบนเป็นเช่นSELECT col1, col2, col3 FROM exampletable WHERE col2=616
นั้นไม่จำเป็นต้องใช้ความพยายามในการอ่านหน้าข้อมูลเพิ่มเติม: เมื่อcol2=616
พบการจับคู่แถวดัชนีแล้วจะต้องทราบข้อมูลที่ร้องขอทั้งหมด นี่คือเหตุผลที่บางครั้งคุณเห็นคอลัมน์ที่จะไม่ถูกค้นหา แต่มีแนวโน้มที่จะถูกร้องขอสำหรับเอาท์พุทเพิ่มไปยังจุดสิ้นสุดของดัชนี - มันสามารถบันทึกการค้นหาแถว เมื่อเพิ่มคอลัมน์ในดัชนีด้วยเหตุผลนี้และด้วยเหตุผลนี้เท่านั้นเพิ่มคอลัมน์ด้วยINCLUDE
ประโยคเพื่อบอกเอ็นจินว่าไม่จำเป็นต้องปรับเลย์เอาต์ดัชนีสำหรับการสืบค้นตามคอลัมน์เหล่านี้ (สิ่งนี้สามารถเร่งความเร็วการอัปเดตของคอลัมน์เหล่านั้น) . การสแกนดัชนีอาจเป็นผลมาจากการสืบค้นที่ไม่มีคำสั่งการกรองเช่นกัน: SELECT col2 FROM exampletable
จะสแกนดัชนีตัวอย่างนี้แทนที่จะเป็นหน้าตาราง
การค้นหาดัชนี (โดยมีหรือไม่มีการค้นหาแถว) :ในการค้นหาดัชนีทั้งหมดจะไม่ได้รับการพิจารณา สำหรับเคียวรีเคียวรีSELECT * FROM exampletable WHERE c1 BETWEEN 1234 AND 4567
เคียวรีสามารถค้นหาแถวแรกที่จะจับคู่โดยทำการค้นหาแบบทรีบนดัชนีc1
จากนั้นมันสามารถนำทางดัชนีตามลำดับจนกว่ามันจะถึงจุดสิ้นสุดของช่วง (ซึ่งจะเหมือนกับแบบสอบถาม เพราะc1=1234
อาจมีหลายแถวที่ตรงกับเงื่อนไขแม้สำหรับการ=
ดำเนินการ) ซึ่งหมายความว่าต้องอ่านหน้าดัชนีที่เกี่ยวข้องเท่านั้น (บวกกับจำนวนเล็กน้อยที่จำเป็นสำหรับการค้นหาเริ่มต้น) แทนที่จะเป็นทุกหน้าในดัชนี (หรือตาราง)
ดัชนีแบบคลัสเตอร์:ด้วยดัชนีแบบคลัสเตอร์ข้อมูลตารางจะถูกเก็บไว้ในโหนดใบไม้ของดัชนีนั้นแทนที่จะอยู่ในโครงสร้างฮีปที่แยกต่างหาก ซึ่งหมายความว่าไม่จำเป็นต้องมีการค้นหาแถวพิเศษใด ๆ หลังจากค้นหาแถวโดยใช้ดัชนีนั้นไม่ว่าจะต้องการคอลัมน์ใด [เว้นแต่ว่าคุณมีข้อมูลนอกหน้าเช่นTEXT
คอลัมน์หรือVARCHAR(MAX)
คอลัมน์ที่มีข้อมูลยาว]
คุณสามารถมีดัชนีคลัสเตอร์เดียวได้ด้วยเหตุนี้[1]ดัชนีคลัสเตอร์คือตารางของคุณแทนที่จะมีโครงสร้างฮีปแยกต่างหากดังนั้นหากคุณใช้[2]เลือกตำแหน่งที่คุณวางไว้อย่างระมัดระวังเพื่อให้ได้รับประโยชน์สูงสุด
นอกจากนี้โปรดทราบว่าดัชนีคลัสเตอร์เนื่องจาก "คีย์การทำคลัสเตอร์" สำหรับตารางและรวมอยู่ในดัชนีที่ไม่ทำคลัสเตอร์ทุกรายการในตารางดังนั้นดัชนีที่ทำคลัสเตอร์แบบกว้างจึงไม่ใช่ความคิดที่ดี
[1] ที่จริงคุณสามารถมีดัชนีหลายคลัสเตอร์ได้อย่างมีประสิทธิภาพโดยการกำหนดดัชนีที่ไม่ใช่คลัสเตอร์ที่ครอบคลุมหรือรวมทุกคอลัมน์ในตาราง แต่น่าจะเป็นพื้นที่ที่สิ้นเปลืองมีผลกระทบต่อประสิทธิภาพการเขียนดังนั้นหากคุณพิจารณาให้แน่ใจว่า คุณต้องการจริงๆ
[2] เมื่อผมบอกว่า "ถ้าคุณใช้ดัชนีคลัสเตอร์" ไม่ทราบว่าจะแนะนำกันโดยทั่วไปว่าคุณทำมีหนึ่งในแต่ละโต๊ะ มีข้อยกเว้นเช่นเดียวกับกฎ - ของ - นิ้วหัวแม่มือทุกตารางที่เห็นนอกเหนือจากเม็ดมีดจำนวนมากและการอ่านแบบไม่เรียงลำดับ (ตารางการจัดเตรียมสำหรับกระบวนการ ETL) อาจเป็นตัวอย่างเคาน์เตอร์ทั่วไป
จุดเพิ่มเติม: การสแกนที่ไม่สมบูรณ์:
เป็นสิ่งสำคัญที่ต้องจำไว้ว่าขึ้นอยู่กับส่วนที่เหลือของแบบสอบถามสแกนตาราง / ดัชนีอาจไม่สแกนทั้งตารางจริง - ถ้าตรรกะช่วยให้แผนแบบสอบถามอาจจะทำให้มันยกเลิกก่อน ตัวอย่างที่ง่ายที่สุดของเรื่องนี้คือSELECT TOP(1) * FROM HugeTable
- ถ้าคุณดูที่แผนแบบสอบถามสำหรับสิ่งที่คุณจะเห็นว่ามีเพียงหนึ่งแถวที่ถูกส่งคืนจากการสแกนและถ้าคุณดูสถิติ IO ( SET STATISTICS IO ON; SELECT TOP(1) * FROM HugeTable
) คุณจะเห็นว่ามันอ่านตัวเลขเพียงเล็กน้อยเท่านั้น จากหน้า (อาจเป็นเพียงหนึ่ง)
สิ่งเดียวกันสามารถเกิดขึ้นได้หากเพรดิเคตของ a WHERE
หรือJOIN ... ON
ประโยคสามารถรันพร้อมกันกับการสแกนที่เป็นแหล่งหากข้อมูลของมัน ตัววางแผนคิวรี / รันเนอร์สามารถฉลาดมากเกี่ยวกับการผลักเพรดิเคตกลับไปยังแหล่งข้อมูลเพื่อให้สามารถยกเลิกการสแกนก่อนหน้านี้ด้วยวิธีนี้ (และบางครั้งคุณสามารถฉลาดในการจัดคิวรีใหม่เพื่อช่วยทำ! ในขณะที่ข้อมูลไหลจากขวาไปซ้ายตามลูกศรในการแสดงแผนแบบสอบถามมาตรฐานตรรกะวิ่งจากซ้ายไปขวาและแต่ละขั้นตอน (จากขวาไปซ้าย) ไม่จำเป็นต้องเรียกใช้ให้เสร็จก่อนที่จะเริ่มต้นต่อไป ในตัวอย่างง่ายๆข้างต้นหากคุณดูแต่ละบล็อกในแผนแบบสอบถามเป็นตัวแทนSELECT
ตัวแทนจะขอให้TOP
ตัวแทนแถวซึ่งจะถามTABLE SCAN
ตัวแทนหนึ่งจากนั้นSELECT
ตัวแทนขออีก แต่TOP
ตัวแทนรู้ว่าไม่จำเป็นต้องไม่รำคาญแม้แต่จะถามผู้อ่านตารางSELECT
ตัวแทนได้รับการตอบสนอง "ไม่เกี่ยวข้องมาก" และรู้ว่างานทั้งหมดจะทำ การดำเนินงานหลายป้องกันการเรียงลำดับของการเพิ่มประสิทธิภาพของหลักสูตรนี้จึงมักจะอยู่ในตัวอย่างที่ซับซ้อนมากขึ้นตารางการสแกน / ดัชนีจริงๆไม่อ่านทุกแถว แต่ต้องระวังไม่ให้ข้ามไปยังข้อสรุปว่าการสแกนอื่น ๆ จะต้องมีการดำเนินการที่มีราคาแพง