ฉันลังเลที่จะเพิ่มอีกคำตอบที่นี่เนื่องจากมีอยู่ไม่กี่อย่าง แต่ต้องมีบางจุดที่ยังไม่ได้ทำหรือไม่ได้ทำอย่างชัดเจน
แม่: Do ไม่NVARCHAR
เคยใช้ นั่นเป็นทัศนคติที่อันตรายและมักมีค่าใช้จ่ายสูง และไม่ควรพูดว่า " ไม่ใช้เคอร์เซอร์" เพราะบางครั้งวิธีที่มีประสิทธิภาพมากที่สุดในการแก้ปัญหาเฉพาะและการทำงานร่วมกันแบบWHILE
วนรอบมักจะช้ากว่าเคอร์เซอร์ที่ทำอย่างถูกต้อง
ครั้งเดียวที่คุณควรใช้คำว่า "เสมอ" คือเมื่อแนะนำให้ "ทำสิ่งที่ดีที่สุดสำหรับสถานการณ์เสมอ" ได้รับซึ่งมักจะยากที่จะกำหนดโดยเฉพาะอย่างยิ่งเมื่อพยายามที่จะรักษาสมดุลกำไรระยะสั้นในการพัฒนา (ผู้จัดการ: "เราต้องการคุณสมบัตินี้ - ซึ่งคุณไม่เคยรู้มาก่อนจนกระทั่งตอนนี้ - เมื่อสัปดาห์ที่แล้ว!") ด้วยความยาว ค่าใช้จ่ายในการบำรุงรักษาระยะยาว (ผู้จัดการที่กดดันทีมในตอนแรกเพื่อทำโครงการ 3 เดือนในระยะเวลา 3 สัปดาห์: "ทำไมเราถึงมีปัญหาด้านประสิทธิภาพเหล่านี้เราจะทำ X ที่ไม่มีความยืดหยุ่นได้อย่างไร? การวิ่งหนึ่งหรือสองเพื่อแก้ไขปัญหานี้เราสามารถทำอะไรได้ภายในหนึ่งสัปดาห์เพื่อให้เราสามารถกลับไปที่รายการที่เราจัดลำดับความสำคัญได้และเราต้องใช้เวลามากขึ้นในการออกแบบดังนั้นสิ่งนี้จะไม่เกิดขึ้น! ")
ที่สอง:คำตอบของ @ gbn สัมผัสกับประเด็นสำคัญที่ควรพิจารณาเมื่อตัดสินใจสร้างแบบจำลองข้อมูลบางอย่างเมื่อเส้นทางไม่ชัดเจน 100% แต่ยังมีสิ่งที่ต้องพิจารณาอีกมาก:
- ขนาดของไฟล์บันทึกธุรกรรม
- เวลาที่ใช้ในการทำซ้ำ (ถ้าใช้การจำลองแบบ)
- เวลาที่ใช้กับ ETL (ถ้า ETLing)
- เวลาที่ใช้ในการจัดส่งบันทึกไปยังระบบระยะไกลและเรียกคืน (ถ้าใช้ Log Shipping)
- ขนาดของการสำรองข้อมูล
- ระยะเวลาที่ใช้ในการสำรองข้อมูลให้เสร็จสมบูรณ์
- ระยะเวลาที่ใช้ในการทำการกู้คืน (ซึ่งอาจมีความสำคัญในบางวัน ;-)
- ขนาดที่จำเป็นสำหรับ tempdb
- ประสิทธิภาพของทริกเกอร์ (สำหรับแทรกและลบตารางที่เก็บไว้ใน tempdb)
- ประสิทธิภาพของการกำหนดเวอร์ชันของแถว (หากใช้ SNAPSHOT ISOLATION เนื่องจากที่เก็บรุ่นอยู่ใน tempdb)
- ความสามารถในการรับพื้นที่ดิสก์ใหม่เมื่อ CFO กล่าวว่าพวกเขาเพิ่งใช้จ่าย $ 1 ล้านใน SAN ปีที่แล้วดังนั้นพวกเขาจะไม่อนุญาตอีก $ 250k สำหรับการจัดเก็บเพิ่มเติม
- ระยะเวลาที่ใช้ในการดำเนินการ INSERT และ UPDATE
- ระยะเวลาที่ใช้ในการบำรุงรักษาดัชนี
- ฯลฯ ฯลฯ ฯลฯ
การสูญเสียพื้นที่มีผลกระทบน้ำตกขนาดใหญ่ในระบบทั้งหมด ฉันเขียนบทความที่มีรายละเอียดชัดเจนในหัวข้อนี้: Disk is Cheap! ORLY? (ต้องลงทะเบียนฟรีขออภัยฉันไม่ได้ควบคุมนโยบายนั้น)
ประการที่สาม:ในขณะที่คำตอบบางคำเน้นที่ "นี่เป็นแอพเล็ก ๆ " อย่างไม่ถูกต้องและบางคนก็แนะนำให้ "ใช้สิ่งที่เหมาะสม" อย่างถูกต้อง แต่ไม่มีคำตอบใดที่ให้คำแนะนำที่แท้จริงให้กับ OP รายละเอียดที่สำคัญ นี่คือหน้าเว็บสำหรับโรงเรียนของพวกเขาหรือไม่ ที่ดี! ดังนั้นเราสามารถแนะนำให้:
- เขตข้อมูลสำหรับชื่อนักศึกษาและ / หรือคณะอาจเป็น
NVARCHAR
เพราะเมื่อเวลาผ่านไปมีแนวโน้มว่าชื่อจากวัฒนธรรมอื่น ๆ จะปรากฏขึ้นในสถานที่เหล่านั้น
- แต่สำหรับที่อยู่และชื่อเมือง? วัตถุประสงค์ของแอพไม่ได้ระบุไว้ (จะเป็นประโยชน์) แต่สมมติว่ามีการบันทึกที่อยู่ (ถ้ามี) เกี่ยวข้องกับพื้นที่ทางภูมิศาสตร์ที่เฉพาะเจาะจง (เช่นภาษา / วัฒนธรรมเดียว) จากนั้นใช้
VARCHAR
กับหน้ารหัสที่เหมาะสม (ซึ่ง ถูกกำหนดจากการจัดเรียงของฟิลด์)
- หากการจัดเก็บรหัสรัฐและ / หรือประเทศ ISO (ไม่จำเป็นต้องจัดเก็บ
INT
/ TINYINT
เนื่องจากรหัส ISO นั้นมีความยาวคงที่มนุษย์สามารถอ่านได้และเป็นมาตรฐาน :) ใช้CHAR(2)
สำหรับรหัสตัวอักษรสองตัวและCHAR(3)
หากใช้รหัสตัวอักษร 3 ตัว Latin1_General_100_BIN2
และพิจารณาใช้การเปรียบเทียบไบนารีเช่น
- หากการจัดเก็บรหัสไปรษณีย์ (เช่นรหัสไปรษณีย์) ให้ใช้
VARCHAR
เนื่องจากเป็นมาตรฐานสากลที่จะไม่ใช้จดหมายใด ๆ นอก AZ และใช่ยังคงใช้งานVARCHAR
ได้แม้ว่าจะจัดเก็บรหัสไปรษณีย์ของสหรัฐฯเท่านั้นและไม่ใช่ INT เนื่องจากรหัสไปรษณีย์ไม่ใช่ตัวเลขพวกเขาเป็นสตริงและบางคนมีผู้นำ "0" Latin1_General_100_BIN2
และพิจารณาใช้การเปรียบเทียบไบนารีเช่น
- หากการจัดเก็บที่อยู่อีเมลและ / หรือ URL ให้ใช้
NVARCHAR
เนื่องจากทั้งคู่สามารถมีอักขระ Unicode ได้แล้ว
- และอื่น ๆ ....
ข้อที่สี่:ตอนนี้คุณมีNVARCHAR
ข้อมูลเพิ่มขึ้นเป็นสองเท่าของพื้นที่ที่เกินกว่าที่จำเป็นสำหรับข้อมูลที่เข้ากันได้ดีVARCHAR
("พอดีอย่างดี" = ไม่กลายเป็น "?") และอย่างใดราวกับว่าใช้เวทมนตร์แอปพลิเคชันก็เติบโตขึ้น และตอนนี้มีหลายล้านระเบียนในฟิลด์เหล่านี้อย่างน้อยหนึ่งที่แถวส่วนใหญ่เป็น ASCII มาตรฐาน แต่บางส่วนมีอักขระ Unicode ดังนั้นคุณต้องเก็บไว้NVARCHAR
พิจารณาต่อไปนี้:
ถ้าคุณใช้ SQL Server 2008 - 2016 RTM และอยู่ใน Enterprise Edition หรือถ้าใช้ SQL Server 2016 SP1 (ซึ่งทำให้การบีบอัดข้อมูลพร้อมใช้งานในทุกรุ่น) หรือใหม่กว่าคุณสามารถเปิดใช้งานการบีบอัดข้อมูลได้ การบีบอัดข้อมูลสามารถ (แต่จะไม่ "เสมอ") บีบอัดข้อมูล Unicode ในNCHAR
และNVARCHAR
ฟิลด์ ปัจจัยที่กำหนดคือ:
NCHAR(1 - 4000)
และNVARCHAR(1 - 4000)
ใช้Standard Compression Scheme สำหรับ Unicodeแต่จะเริ่มใน SQL Server 2008 R2 เท่านั้นและเฉพาะสำหรับข้อมูล ROW ไม่ใช่ OVERFLOW! สิ่งนี้ดูเหมือนจะดีกว่าอัลกอริทึมการบีบอัด ROW / PAGE ปกติ
NVARCHAR(MAX)
และXML
(และฉันเดาด้วยVARBINARY(MAX)
, TEXT
และNTEXT
) ข้อมูลที่มีอยู่ในแถว (ไม่ได้ปิดแถวในลอบหรือล้นหน้า) อย่างน้อยสามารถบีบอัดหน้า แต่ไม่แถวบีบอัด แน่นอนการบีบอัด PAGE ขึ้นอยู่กับขนาดของค่าในแถว: ฉันทดสอบด้วย VARCHAR (MAX) และเห็นว่าแถว 6000 ตัวอักษร / ไบต์จะไม่บีบอัด แต่แถว 4000 ตัวอักษร / ไบต์ไม่ได้
- ข้อมูล ROW ใด ๆ LOB หรือ OVERLOW = ไม่มีการบีบอัดข้อมูลสำหรับคุณ!
ถ้าใช้ SQL Server 2005 หรือ 2008-2016 RTM และไม่เกี่ยวกับ Enterprise Edition คุณสามารถมีสองช่องหนึ่งและเป็นหนึ่งในVARCHAR
NVARCHAR
ตัวอย่างเช่นสมมติว่าคุณกำลังจัดเก็บ URL ซึ่งส่วนใหญ่เป็นอักขระ ASCII พื้นฐานทั้งหมด (ค่า 0 - 127) และอาจเหมาะสมVARCHAR
แต่บางครั้งก็มีอักขระ Unicode สคีมาของคุณสามารถมี 3 ฟิลด์ต่อไปนี้:
...
URLa VARCHAR(2048) NULL,
URLu NVARCHAR(2048) NULL,
URL AS (ISNULL(CONVERT(NVARCHAR([URLa])), [URLu])),
CONSTRAINT [CK_TableName_OneUrlMax] CHECK (
([URLa] IS NOT NULL OR [URLu] IS NOT NULL)
AND ([URLa] IS NULL OR [URLu] IS NULL))
);
ในรุ่นนี้คุณเลือกเฉพาะจาก[URL]
คอลัมน์ที่คำนวณ สำหรับการแทรกและอัปเดตคุณจะต้องกำหนดว่าจะใช้ฟิลด์ใดโดยดูว่าการแปลงเปลี่ยนค่าที่เข้ามาซึ่งต้องเป็นNVARCHAR
ประเภทใด:
INSERT INTO TableName (..., URLa, URLu)
VALUES (...,
IIF (CONVERT(VARCHAR(2048), @URL) = @URL, @URL, NULL),
IIF (CONVERT(VARCHAR(2048), @URL) <> @URL, NULL, @URL)
);
คุณสามารถ GZIP ค่าที่เข้ามาVARBINARY(MAX)
แล้วเปิดเครื่องรูดที่ทางออก:
- สำหรับ SQL Server 2005 - 2014: คุณสามารถใช้ SQLCLR SQL # (ไลบรารี SQLCLR ที่ฉันเขียน) มาพร้อมกับUtil_GZipและ Util_GUnzipในรุ่นฟรี
- สำหรับ SQL Server 2016 และใหม่กว่า: คุณสามารถใช้ฟังก์ชันในตัว
COMPRESS
และDECOMPRESS
ฟังก์ชันซึ่งก็คือ GZip
หากใช้ SQL Server 2017 หรือใหม่กว่าคุณสามารถสร้างตารางเป็นดัชนีคอลัมน์แบบกลุ่มได้
แม้ว่านี่จะไม่ใช่ตัวเลือกที่ทำงานได้ แต่ SQL Server 2019 แนะนำการสนับสนุนดั้งเดิมสำหรับ UTF-8 in VARCHAR
/ CHAR
datatypes ขณะนี้มีข้อบกพร่องมากเกินไปสำหรับมันที่จะใช้ แต่ถ้าพวกเขาได้รับการแก้ไขแล้วนี่คือตัวเลือกสำหรับบางสถานการณ์ โปรดดูโพสต์ของฉัน " Native UTF-8 รองรับใน SQL Server 2019: Savior หรือ False Prophet? " สำหรับการวิเคราะห์โดยละเอียดเกี่ยวกับคุณสมบัติใหม่นี้