การจัดทำดัชนีกับสตริงที่ไม่คำนึงถึงขนาดตัวพิมพ์ แต่เคสของข้อมูลยังคงอยู่ มันใช้งานได้จริงอย่างไร?
นี่ไม่ใช่พฤติกรรมที่เฉพาะเจาะจงของ SQL Server แต่เป็นสิ่งที่สิ่งเหล่านี้ทำงานโดยทั่วไป
ดังนั้นข้อมูลคือข้อมูล หากคุณกำลังพูดเกี่ยวกับดัชนีเฉพาะข้อมูลที่ต้องการจะถูกเก็บไว้เป็นมันเป็นอื่นมันจะต้องมีการมองขึ้นในตารางหลักในแต่ละครั้งจะได้รับค่าที่เกิดขึ้นจริงและจะมีความเป็นไปได้ของดัชนีที่ครอบคลุมไม่มี (อย่าง อย่างน้อยไม่ได้สำหรับประเภทสตริง)
ข้อมูลทั้งในตาราง / ดัชนีคลัสเตอร์หรือดัชนีที่ไม่ใช่คลัสเตอร์ไม่ได้มีการตรวจทาน / ข้อมูลใด ๆ เรียงลำดับ มันเป็นเพียงข้อมูล การจัดเรียง (โลแคล / กฎของวัฒนธรรมและความไว) เป็นเพียงข้อมูลเมตาที่แนบมากับคอลัมน์และใช้เมื่อเรียกใช้การดำเนินการเรียงลำดับ (เว้นแต่จะถูกแทนที่โดยCOLLATEข้อ) ซึ่งจะรวมถึงการสร้าง / สร้างใหม่ของดัชนี กฎที่กำหนดโดยการเปรียบเทียบที่ไม่ใช่ไบนารีถูกใช้เพื่อสร้างการเรียงลำดับคีย์ซึ่งเป็นการแทนไบนารีของสตริง (คีย์การเรียงลำดับไม่จำเป็นในการเปรียบเทียบไบนารี) การเป็นตัวแทนไบนารีเหล่านี้รวมกฎของโลแคล / วัฒนธรรมและความไวที่เลือกไว้ทั้งหมด การเรียงลำดับคีย์ถูกใช้เพื่อวางเร็กคอร์ดในลำดับที่เหมาะสม แต่จะไม่ถูกเก็บไว้ในดัชนีหรือตาราง พวกเขาจะไม่ถูกเก็บไว้ (อย่างน้อยฉันไม่ได้เห็นค่าเหล่านี้ในดัชนีและบอกว่าพวกเขาไม่ได้เก็บไว้) เพราะ:
- พวกเขาไม่จำเป็นต้องเรียงลำดับอย่างแท้จริงเพราะพวกเขาจะอยู่ในลำดับเดียวกับแถวในตารางหรือดัชนีอย่างไรก็ตาม แต่ลำดับทางกายภาพของดัชนีเป็นเพียงการเรียงลำดับไม่ใช่การเปรียบเทียบ
- ในขณะที่การจัดเก็บอาจทำให้การเปรียบเทียบเร็วขึ้น แต่ก็จะทำให้ดัชนีมีขนาดใหญ่ขึ้นเนื่องจากขนาดต่ำสุดสำหรับอักขระตัวเดียวคือ 5 ไบต์และนั่นเป็นเพียง "ค่าใช้จ่าย" (ของโครงสร้างคีย์การเรียงลำดับ) อักขระส่วนใหญ่มีขนาด 2 ไบต์และอีก 1 ไบต์หากมีการเน้นเสียงและอีก 1 ไบต์หากเป็นตัวพิมพ์ใหญ่ ตัวอย่างเช่น "e" เป็นคีย์ขนาด 7 ไบต์ "E" และ "é" มีทั้ง 8 ไบต์และ "É" เป็นคีย์ขนาด 9 ไบต์ ดังนั้นอย่าเก็บสิ่งเหล่านี้ไว้ในที่สุด
การเปรียบเทียบมีสองประเภท: SQL Server และ Windows
เซิร์ฟเวอร์ SQL
การเปรียบเทียบ SQL Server (ชื่อที่ขึ้นต้นด้วยSQL_) เป็นวิธีการเรียงลำดับ / เปรียบเทียบก่อนหน้าของ SQL Server 2000 (แม้ว่าSQL_Latin1_General_CP1_CI_ASจะยังคงเป็นค่าเริ่มต้นในการติดตั้งบนระบบปฏิบัติการภาษาอังกฤษของสหรัฐฯ ในรูปแบบเก่าที่เรียบง่ายไม่ใช่ยูนิโคดการรวมกันของสถานที่เกิดเหตุหน้ารหัสและความไวต่างๆจะได้รับการทำแผนที่แบบคงที่ของตัวละครแต่ละตัวในหน้ารหัสที่ อักขระแต่ละตัวได้รับการกำหนดค่า (เช่นน้ำหนักการเรียงลำดับ) เพื่อแสดงว่ามันมีความสอดคล้องกับอักขระอื่นอย่างไร การเปรียบเทียบในรุ่นนี้ดูเหมือนจะเป็นการดำเนินการสองรอบ:
- ก่อนอื่นมันจะกำจัดสำเนียงทั้งหมด (เช่น " ü " กลายเป็น " u ") ขยายตัวอักขระเช่น " Æ " เป็น " A " และ " E " จากนั้นทำการเรียงลำดับเริ่มต้นเพื่อให้คำเรียงตามลำดับตามธรรมชาติ คาดว่าจะพบพวกเขาในพจนานุกรม)
- จากนั้นมันจะไปตามตัวอักษรเพื่อกำหนดความเท่าเทียมกันตามค่าพื้นฐานเหล่านี้ต่อตัวละครแต่ละตัว นี้ส่วนที่สองคือสิ่งที่ mustaccio จะอธิบายในคำตอบของเขา
ความไวต่อแสงเพียงอย่างเดียวที่สามารถปรับได้ในการเปรียบเทียบนี้คือ: "ตัวพิมพ์ใหญ่" และ "เน้น" ("ความกว้าง", "ประเภทคะนะ" และ "ตัวเลือกชุดรูปแบบ" ไม่พร้อมใช้งาน) นอกจากนี้ยังไม่มีการเปรียบเทียบเหล่านี้ที่สนับสนุนอักขระเพิ่มเติม (ซึ่งสมเหตุสมผลว่าเป็น Unicode เฉพาะและการเปรียบเทียบเหล่านี้ใช้กับข้อมูลที่ไม่ใช่ Unicode เท่านั้น)
วิธีการนี้ใช้เพียงเพื่อที่ไม่ใช่ Unicode VARCHARข้อมูล การผสมผสานที่ไม่ซ้ำกันของสถานที่, รหัสหน้า, ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ - เสียงเน้นเสียงมี "รหัสการเรียงลำดับ" เฉพาะซึ่งคุณสามารถดูได้ในตัวอย่างต่อไปนี้:
SELECT COLLATIONPROPERTY(N'SQL_Latin1_General_CP1_CI_AS', 'SortID'), -- 52
COLLATIONPROPERTY(N'SQL_Latin1_General_CP1_CS_AS', 'SortID'), -- 51
COLLATIONPROPERTY(N'Latin1_General_100_CI_AS', 'SortID'); -- 0
ข้อแตกต่างระหว่างการเปรียบเทียบสองครั้งแรกคือการพิจารณาตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ การเปรียบเทียบที่สามคือการเปรียบเทียบ Windows และดังนั้นจึงไม่มีตารางการแมปแบบคงที่
นอกจากนี้การเปรียบเทียบเหล่านี้ควรเรียงลำดับและเปรียบเทียบเร็วกว่าการเปรียบเทียบ Windows เนื่องจากการค้นหาแบบง่ายสำหรับอักขระเพื่อเรียงลำดับน้ำหนัก อย่างไรก็ตามการเปรียบเทียบเหล่านี้ยังใช้งานได้น้อยกว่ามากและควรหลีกเลี่ยงโดยทั่วไปหากเป็นไปได้
ของ windows
การจัดเรียง Windows (ชื่อที่ไม่ได้ขึ้นต้นด้วยSQL_) เป็นวิธีการเรียงลำดับ / การเปรียบเทียบที่ใหม่กว่า (เริ่มต้นใน SQL Server 2000) ในโมเดล Unicode ที่ใหม่กว่าซับซ้อนนี้การรวมกันของสถานที่เกิดเหตุแต่ละหน้ารหัสและความไวที่แตกต่างกันจะไม่ได้รับการทำแผนที่แบบคงที่ สิ่งหนึ่งที่ไม่มีรหัสหน้าในรุ่นนี้ รุ่นนี้กำหนดค่าการเรียงเริ่มต้นให้กับแต่ละอักขระจากนั้นแต่ละโลแคล / วัฒนธรรมสามารถกำหนดค่าการเรียงใหม่ให้กับจำนวนอักขระได้ สิ่งนี้ทำให้หลายวัฒนธรรมสามารถใช้อักขระเดียวกันในวิธีที่ต่างกัน สิ่งนี้มีผลต่อการอนุญาตให้เรียงหลายภาษาโดยธรรมชาติโดยใช้การเรียงเดียวกันหากไม่ใช้อักขระเดียวกัน (และหากหนึ่งในนั้นไม่จำเป็นต้องกำหนดค่าใหม่อีกครั้งและสามารถใช้ค่าเริ่มต้นได้)
ค่าการเรียงลำดับในรุ่นนี้ไม่ใช่ค่าเดียว พวกมันคืออาร์เรย์ของค่าที่กำหนดน้ำหนักสัมพัทธ์ให้กับตัวอักษรฐานการกำกับเสียงใด ๆ (เช่นการเน้นเสียง) การบรรจุและอื่น ๆ หากการเปรียบเทียบเป็นแบบตัวพิมพ์ใหญ่และตัวเล็กต้องใช้ส่วน "case" ของอาร์เรย์นั้น ด้วยเหตุนี้จึงไม่มีความรู้สึก) หากการเปรียบเทียบนั้นมีความอ่อนไหวต่อสำเนียงดังนั้นส่วน "diacritic" ของอาร์เรย์จะถูกนำมาใช้มิฉะนั้นก็จะถูกละเว้น
การเปรียบเทียบในรุ่นนี้เป็นการทำงานแบบมัลติพาส:
- ก่อนอื่นสตริงจะถูกทำให้เป็นมาตรฐานเพื่อให้วิธีที่หลากหลายในการแสดงอักขระเดียวกันจะถือเอา ตัวอย่างเช่น " ü " อาจเป็นอักขระ / จุดรหัสเดียว (U + 00FC) คุณสามารถรวม " u " ที่ไม่เน้นเสียงได้(U + 0075) เข้ากับการรวมการรวม " ̈ " (U + 0308) เพื่อรับ: " ü " ซึ่งไม่เพียง แต่ดูเหมือนจะเหมือนกันเมื่อเรนเดอร์ (เว้นแต่มีปัญหากับ แบบอักษรของคุณ) แต่ก็ถือว่าเหมือนกันกับเวอร์ชันอักขระตัวเดียว (U + 00FC) ยกเว้นว่าใช้การเปรียบเทียบแบบไบนารี (ซึ่งเปรียบเทียบไบต์แทนอักขระ) การนอร์มัลไลซ์เซชั่นแบ่งอักขระเดี่ยวออกเป็นส่วนต่าง ๆ ซึ่งรวมถึงการขยายสำหรับอักขระเช่น " Æ " (ดังที่ระบุไว้ข้างต้นสำหรับการเปรียบเทียบของ SQL Server)
- การดำเนินการเปรียบเทียบในรุ่นนี้จะมีตัวอักษรต่ออักขระตามความไวแต่ละตัว คีย์การเรียงลำดับสำหรับสตริงจะถูกกำหนดโดยการใช้องค์ประกอบที่เหมาะสมของแต่ละอาร์เรย์เรียงตัวอักษรของค่าตามความไวที่ "ไว" ค่าคีย์การเรียงลำดับจะถูกจัดเรียงโดยความไวหลักทั้งหมดของอักขระแต่ละตัว (อักขระพื้นฐาน) ตามด้วยความไวแสงรองทั้งหมด (น้ำหนักกำกับน้ำหนัก) ตามด้วยน้ำหนักตัวพิมพ์ของแต่ละอักขระและอื่น ๆ
- การเรียงลำดับจะดำเนินการตามคีย์การเรียงลำดับที่คำนวณได้ ด้วยความไวแต่ละอย่างที่จัดกลุ่มไว้ด้วยกันคุณจะได้รับการเรียงลำดับที่แตกต่างจากการเปรียบเทียบ SQL Server ที่เทียบเท่ากันเมื่อเปรียบเทียบสตริงของอักขระหลายตัวและมีการเน้นเสียงที่เกี่ยวข้องและการเปรียบเทียบนั้นมีความอ่อนไหวต่อสำเนียง ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่)
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการเรียงลำดับนี้ในที่สุดฉันจะเผยแพร่โพสต์ที่แสดงค่าคีย์การเรียงลำดับวิธีการคำนวณความแตกต่างระหว่างการเรียง SQL Server และ Windows เป็นต้น แต่สำหรับตอนนี้โปรดดูคำตอบของฉัน: Accent Sensitive Sort ( โปรดทราบว่าคำตอบอื่น ๆ สำหรับคำถามนั้นเป็นคำอธิบายที่ดีของอัลกอริทึม Unicode อย่างเป็นทางการ แต่ SQL Server ใช้การกำหนดเองแทนแม้ว่าจะคล้ายกันอัลกอริทึมและแม้แต่ตารางน้ำหนักแบบกำหนดเอง)
ความไวแสงทั้งหมดสามารถปรับได้ในการจัดเรียงเหล่านี้: "case", "accent", "width", "kana type" และ "select selector" (เริ่มใน SQL Server 2017 และสำหรับ Collation ญี่ปุ่นเท่านั้น) นอกจากนี้การเปรียบเทียบเหล่านี้บางส่วน (เมื่อใช้กับข้อมูล Unicode) สนับสนุนอักขระเพิ่มเติม (เริ่มต้นใน SQL Server 2012) วิธีการนี้ใช้กับทั้งสองNVARCHAR และ VARCHARข้อมูล (แม้แต่ข้อมูลที่ไม่ใช่ Unicode) มันใช้กับข้อมูลที่ไม่ใช่ Unicode VARCHARโดยการแปลงค่าเป็น Unicode ภายในก่อนจากนั้นจึงใช้กฎการเรียงลำดับ / การเปรียบเทียบ
โปรดทราบ:
- ไม่มีการเปรียบเทียบค่าเริ่มต้นสากลสำหรับ SQL Server มีค่าเริ่มต้นการติดตั้งซึ่งแตกต่างกันไปตามการตั้งค่าภาษา / ภาษาปัจจุบันของระบบปฏิบัติการ ณ เวลาที่ทำการติดตั้ง (ซึ่งน่าเสียดาย
SQL_Latin1_General_CP1_CI_ASสำหรับระบบภาษาอังกฤษของสหรัฐอเมริกาดังนั้นโปรดลงคะแนนสำหรับคำแนะนำนี้ ) สิ่งนี้สามารถเปลี่ยนแปลงได้ระหว่างการติดตั้ง การเปรียบเทียบระดับอินสแตนซ์นี้จากนั้นตั้งค่าการเรียงสำหรับ[model]ฐานข้อมูลซึ่งเป็นเทมเพลตที่ใช้เมื่อสร้างฐานข้อมูลใหม่ แต่การเปรียบเทียบสามารถเปลี่ยนแปลงได้เมื่อดำเนินการCREATE DATABASEโดยการระบุCOLLATEข้อ การเปรียบเทียบระดับฐานข้อมูลนี้ใช้สำหรับตัวแปรและตัวอักษรสตริงเช่นเดียวกับค่าเริ่มต้นสำหรับคอลัมน์ใหม่ (และเปลี่ยนแปลง!) เมื่อCOLLATEไม่ได้ระบุอนุประโยค (ซึ่งเป็นกรณีสำหรับรหัสตัวอย่างในคำถาม)
- สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ Collations / encodings / Unicode โปรดไปที่: Collations Info