มีข้อเสียใด ๆ ในการใช้ nvarchar (MAX) เสมอหรือไม่?


342

ใน SQL Server 2005 มีข้อเสียใด ๆ ในการสร้างฟิลด์อักขระทั้งหมด nvarchar (MAX) แทนที่จะระบุความยาวอย่างชัดเจนเช่น nvarchar (255) หรือไม่ (นอกเหนือจากความชัดเจนที่คุณไม่สามารถจำกัดความยาวของฟิลด์ที่ระดับฐานข้อมูล)


1
ฉัน jsut ไม่เข้าใจว่าทำไมคุณต้องการให้ใครบางคนป้อนชื่อของตัวละครมากกว่า 8000 ตัว
DForck42

2
ตรรกะเดียวกันสามารถใช้กับภาษาการเขียนโปรแกรม ทำไมไม่กลับไปใช้ VB6 รุ่นเก่าสำหรับข้อมูลทั้งหมดของเรา? ฉันไม่คิดว่าการตรวจสอบและถ่วงดุลในสถานที่มากกว่าหนึ่งแห่งนั้นไม่ดีอย่างแน่นอน
Matt Spradley

1
ตรวจสอบสิ่งนี้: stackoverflow.com/questions/2009694/…
Akira Yamamoto

10
การอัปเดตของคุณควรเป็นคำตอบของคำถามนี้
โยฮั

คำตอบในคำถามถูกย้ายไปยังคำตอบที่เหมาะสมเนื่องจากผู้เขียนต้นฉบับไม่ได้ทำ stackoverflow.com/a/35177895/10245ฉันตัวเลข 7 ปีเป็นเวลาพอ :-)
ทิมอาเบล

คำตอบ:


153

คำถามเดียวกันถูกถามในฟอรัม MSDN:

จากโพสต์ต้นฉบับ (มีข้อมูลเพิ่มเติม):

เมื่อคุณจัดเก็บข้อมูลไปยังคอลัมน์ VARCHAR (N) ค่าจะถูกจัดเก็บในลักษณะเดียวกัน แต่เมื่อคุณเก็บไว้ในคอลัมน์ VARCHAR (MAX) ด้านหลังหน้าจอข้อมูลจะถูกจัดการเป็นค่า TEXT ดังนั้นจึงจำเป็นต้องมีการประมวลผลเพิ่มเติมเมื่อจัดการกับค่า VARCHAR (MAX) (เฉพาะในกรณีที่ขนาดเกิน 8000)

VARCHAR (MAX) หรือ NVARCHAR (MAX) ถือเป็น 'ประเภทค่าขนาดใหญ่' ประเภทค่าขนาดใหญ่มักจะเก็บไว้ที่ 'ออกจากแถว' หมายความว่าแถวข้อมูลจะมีตัวชี้ไปยังตำแหน่งอื่นที่เก็บ 'ค่ามาก' ...


2
ดังนั้นคำถามควรเป็นเช่นไรมีความแตกต่างระหว่างการใช้ N / VARCHAR (MAX) และ N / TEXT หรือไม่
ต้อง

18
หากฉันจำได้ถูกต้องพวกเขาจะไม่ถูกจัดเก็บไว้นอกแถวหากขนาดเกิน 8k หรือไม่
Sam Schutte

79
ฉันอ่านคำตอบว่า "ไม่ไม่มีข้อเสียในการใช้N/VARCHAR(MAX)" เพราะมีการประมวลผลเพิ่มเติม "เฉพาะในกรณีที่มีขนาดเกิน 8000" ดังนั้นคุณต้องเสียค่าใช้จ่ายเมื่อจำเป็นเท่านั้นและฐานข้อมูลของคุณน้อยกว่าที่ จำกัด ฉันอ่านผิดหรือเปล่า? ดูเหมือนว่าคุณจะต้องการN/VARCHAR(MAX)มากกว่าN/VARCHAR(1-8000)...
Kent Boogaart

1
ลิงก์ที่ตายแล้วด้านบน - ลิงก์ที่ใช้งานได้สำหรับคำถามบน MSDN คือsocial.msdn.microsoft.com/Forums/en-US/sqlgetstarted/thread/?hl=th
Jagd

68
น่าเสียดายที่คำตอบนี้มีปัญหามากมาย มันทำให้ 8k เขตแดนดูเหมือนจำนวนมายากลที่ไม่เป็นความจริงคุ้มค่าที่ได้รับการผลักดันให้ออกจากแถวขึ้นอยู่กับปัจจัยอาจมากขึ้นรวมทั้งsp_tableoptions: msdn.microsoft.com/en-us/library/ms173530.aspx VARCHAR (255) ประเภทนี้ยังสามารถผลัก b ออกจากแถว 'ค่าใช้จ่าย' ที่กล่าวถึงอาจจะเหมือนกันสำหรับ MAX และ 255 มันเปรียบเทียบประเภท MAX กับประเภทข้อความเมื่อพวกเขาแตกต่างกันตามที่ได้รับ (API ที่แตกต่างกันโดยสิ้นเชิงในการจัดการ การจัดเก็บข้อมูลที่แตกต่างกัน ฯลฯ ) ไม่สามารถพูดถึงความแตกต่างที่เกิดขึ้นจริง: ไม่มีดัชนีไม่มีการดำเนินการออนไลน์ในประเภท MAX
Remus Rusanu

50

มันเป็นคำถามที่ยุติธรรมและเขาก็แยกแยะจากสิ่งที่ชัดเจน ...

ข้อเสียอาจรวมถึง:

การเพิ่มประสิทธิภาพ Query optimizer ใช้ขนาดฟิลด์เพื่อกำหนดแผน exectution ที่มีประสิทธิภาพสูงสุด

"1. การเว้นช่องว่างในการขยายและหน้าของฐานข้อมูลมีความยืดหยุ่นดังนั้นเมื่อเพิ่มข้อมูลลงในฟิลด์โดยใช้การอัปเดตฐานข้อมูลของคุณจะต้องสร้างตัวชี้หากข้อมูลใหม่ยาวกว่าที่แทรกไว้ก่อนหน้านี้ กลายเป็นส่วนย่อย = ประสิทธิภาพลดลงในเกือบทุกอย่างตั้งแต่ดัชนีไปจนถึงลบอัปเดตและส่วนแทรก " http://sqlblogcasts.com/blogs/simons/archive/2006/02/28/Why-use-anything-but-varchar_2800_max_2900_.aspx

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

มีบทความที่ดีอยู่ที่นี่: http://searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1098157,00.html


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

การบูรณาการโดยฐานข้อมูลเป็นสิ่งที่ไร้สาระที่สุดที่ฉันรู้ ถ้ามันเป็นเพียงการนำเข้าที่ทำเมื่อคุณสามารถตรวจสอบข้อมูลก่อนโดยฟังก์ชั่น LEN
Maxim

30

จากลิงก์ที่ให้ไว้ในคำตอบที่ยอมรับปรากฏว่า:

  1. 100 ตัวอักษรที่เก็บอยู่ในnvarchar(MAX)เขตข้อมูลจะถูกจัดเก็บไม่แตกต่างจาก 100 ตัวอักษรในnvarchar(100)เขตข้อมูล - ข้อมูลจะถูกจัดเก็บแบบอินไลน์และคุณจะไม่ได้มีค่าใช้จ่ายในการอ่านและเขียนข้อมูล 'ออกจากแถว' ดังนั้นไม่ต้องกังวล

  2. หากขนาดใหญ่กว่า 4,000 ข้อมูลจะถูกเก็บไว้ 'ออกจากแถว' โดยอัตโนมัติซึ่งเป็นสิ่งที่คุณต้องการ ดังนั้นไม่ต้องกังวลกับทั้งสองอย่าง

อย่างไรก็ตาม ...

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

สรุป:

หากคุณต้องการชนิดของ "ความยาวสตริงสากล" nvarchar(4000)ตลอดทั้งฐานข้อมูลทั้งหมดของคุณซึ่งสามารถจัดทำดัชนีและที่จะไม่เสียพื้นที่และการเข้าถึงเวลานั้นคุณสามารถใช้


1
FYI นี้เป็นการแก้ไขเพิ่มให้กับคำถามเดิมที่ควรได้รับการโพสต์เป็นคำตอบ
ทิมอาเบล

1
ขอบคุณสำหรับฉันนี่คือคำตอบสุดท้าย ฉันถามตัวเองเหมือนกัน - ทำไมไม่ใช้nvarchar(max)ตลอดเวลาเหมือนstringใน C #? - แต่ประเด็นที่ 3) (ปัญหาดัชนี) กำลังให้คำตอบ
ตำรวจ SQL

1
เพิ่มการแก้ไข ในฐานะที่เป็น "ความยาวสายอักขระสากล" คุณสามารถใช้งานได้nvarchar(4000)
SQL Police

@SQLGeorge ดูคำตอบที่ยอดเยี่ยมนี้โดยMartin Smithเกี่ยวกับผลกระทบต่อประสิทธิภาพการค้นหาของการประกาศคอลัมน์ที่กว้างกว่าที่เคยเป็น
billinkc

@billinkc ขอบคุณนั่นเป็นบทความที่ยอดเยี่ยม ตกลงดังนั้นขนาดย่อมมีผลต่อการทะลุทะลวง ฉันจะแก้ไขคำตอบอีกครั้ง
ตำรวจ SQL

28

บางครั้งคุณต้องการให้ชนิดข้อมูลบังคับใช้ข้อมูลบางอย่างในนั้น

พูดเช่นคุณมีคอลัมน์ที่ไม่ควรยาวเกิน 20 ตัว หากคุณกำหนดคอลัมน์นั้นเป็น VARCHAR (MAX) แอปพลิเคชันปลอมตัวบางตัวสามารถแทรกสตริงยาวลงไปในนั้นและคุณจะไม่มีทางรู้หรือมีวิธีป้องกันใด ๆ

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


9
ฉันเห็นด้วยกับสิ่งนี้และความคิดเห็นอื่น ๆ แต่ฉันก็ยังยืนยันว่านี่เป็นความรับผิดชอบของชั้นธุรกิจ เมื่อถึงระดับฐานข้อมูลก็ควรจะทักทายและเก็บค่าไว้ไม่ว่าจะนานแค่ไหนก็ตาม ฉันคิดว่าสิ่งที่เล่นจริงที่นี่คือฉันคิดว่าประมาณ 90% ของเวลาที่นักพัฒนาระบุ varchar (255) ความตั้งใจของเขาไม่ใช่อักขระ 255 จริง ๆ แต่มีค่าความยาวปานกลางที่ไม่ระบุ และเนื่องจากการแลกเปลี่ยนระหว่างค่าที่มากเกินสมควรในฐานข้อมูลของฉันกับข้อยกเว้นที่ไม่คาดคิดฉันจะเอาค่าที่มีขนาดใหญ่
395 Chris

4
หากพวกเขากำลังระบุ VARCHAR (255) เพื่อระบุความยาวที่ไม่ทราบสาเหตุนั่นเป็นความผิดของพวกเขาที่ไม่ได้ทำการค้นคว้าสิ่งที่ออกแบบอย่างเหมาะสม การแก้ปัญหาสำหรับนักพัฒนาในการทำงานของพวกเขาไม่ได้สำหรับฐานข้อมูลเพื่อให้ค่าที่ไม่สมเหตุสมผล
Tom H

10
ไม่เป็นประโยชน์กับผู้เขียน เขายกเว้นคำถามนี้อย่างชัดเจนว่าคุณได้ให้คำตอบ
usr

6
@ Chris B Behrens: ฉันไม่เห็นด้วย สกีมาฐานข้อมูลเป็นส่วนหนึ่งของตรรกะทางธุรกิจ ตัวเลือกของตารางความสัมพันธ์ฟิลด์และประเภทข้อมูลเป็นตรรกะทางธุรกิจทั้งหมดและเป็นสิ่งที่คุ้มค่าหากใช้ RDBMS เพื่อบังคับใช้กฎของตรรกะทางธุรกิจนี้ ด้วยเหตุผลเดียวมันเป็นเรื่องยากมากที่มีระดับแอปพลิเคชันระดับเดียวเท่านั้นที่เข้าถึงฐานข้อมูล ตัวอย่างเช่นคุณอาจมีการนำเข้าข้อมูลและเครื่องมือดึงข้อมูลที่ข้ามชั้นธุรกิจหลักซึ่งหมายความว่าคุณต้องการให้ฐานข้อมูลบังคับใช้กฎจริงๆ
Vince Bowdren

1
หากคุณไม่ต้องการหรือต้องการให้มีการจัดเก็บสายอักขระยาว ๆ แน่นอนว่ามันจะเป็นการดีกว่าที่จะใช้ความรู้สึกกับข้อมูล เช่นถ้าการจัดเก็บเขตข้อมูล PostCode คุณจะอนุญาตให้บางคนใส่ตัวอักษรเป็นร้อยหรือพันตัวอักษรเมื่อควรมีขนาดไม่เกิน 10 คำพูด - ขนาดสูงสุดควรได้รับการตรวจสอบความถูกต้องทุกระดับลูกค้าชั้นธุรกิจและฐานข้อมูล หากใช้วิธีการของ Model First เช่นกับ C # และ Entity Framework คุณสามารถกำหนดขนาดสูงสุดให้กับโมเดลและนำไปใช้กับฐานข้อมูลตรรกะทางธุรกิจและการตรวจสอบความถูกต้องของไคลเอ็นต์ (ด้วยการชอบการตรวจสอบ jquery) ใช้เฉพาะ nvarchar (สูงสุด) หากจำเป็นจริงๆ
Peter Kerr

21

ฉันตรวจสอบบางบทความและค้นหาสคริปต์ทดสอบที่มีประโยชน์จาก: http://www.sqlservercentral.com/Forums/Topic1480639-1292-1.aspx จากนั้นเปลี่ยนเป็นรูปแบบเปรียบเทียบระหว่าง NVARCHAR (10) กับ NVARCHAR (4000) กับ NVARCHAR (MAX) ) และฉันไม่พบความแตกต่างความเร็วเมื่อใช้ตัวเลขที่ระบุ แต่เมื่อใช้ MAX คุณสามารถทดสอบด้วยตัวเอง หวังว่านี่จะช่วยได้

SET NOCOUNT ON;

--===== Test Variable Assignment 1,000,000 times using NVARCHAR(10)
DECLARE @SomeString NVARCHAR(10),
        @StartTime DATETIME;
--=====         
 SELECT @startTime = GETDATE();
 SELECT TOP 1000000
        @SomeString = 'ABC'
   FROM master.sys.all_columns ac1,
        master.sys.all_columns ac2;
 SELECT testTime='10', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(4000)
DECLARE @SomeString NVARCHAR(4000),
        @StartTime DATETIME;
 SELECT @startTime = GETDATE();
 SELECT TOP 1000000
        @SomeString = 'ABC'
   FROM master.sys.all_columns ac1,
        master.sys.all_columns ac2;
 SELECT testTime='4000', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(MAX)
DECLARE @SomeString NVARCHAR(MAX),
        @StartTime DATETIME;
 SELECT @startTime = GETDATE();
 SELECT TOP 1000000
        @SomeString = 'ABC'
   FROM master.sys.all_columns ac1,
        master.sys.all_columns ac2;
 SELECT testTime='MAX', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO

4
นั่นดูน่าสนใจ. ในกล่องของฉันดูเหมือนว่า MAX หนึ่งจะช้ากว่า 4x
stucampbell

4
ผลลัพธ์ใหม่บน SQL Server 2012: 10 ช้ากว่า 4k สองเท่าและสูงสุดคือ 5.5 เท่าช้ากว่า 4k
cassandrad

1
เวลาส่วนใหญ่คือการส่งข้อมูลโดยนัยจาก varchar ถึง nvarchar (สูงสุด) ลองอันนี้: DECLARE \ @SomeString NVARCHAR (สูงสุด), \ @abc NVARCHAR (สูงสุด) = N'ABC ', \ @StartTime DATETIME; SELECT @startTime = GETDATE (); เลือกสูงสุด 1000000 \ @SomeString = \ @abc จาก master.sys.all_columns ac1, master.sys.all_columns ac2; SELECT testTime = 'MAX', Duration = DATEDIFF (ms, \ @ StartTime, GETDATE ()); ต้องแทรก \ before ตัวแปรเพื่อให้โพสต์
Kvasi

4
SQL Server 2014 บน SSD: 150, 156, 716 (10, 4000, MAX)
Maxim

2
ขอบคุณที่เพิ่มจำนวนจริงลงในการสนทนานี้ เรามักจะลืมว่าการสร้างกรณีทดสอบเป็นวิธีที่รวดเร็วที่สุดในการทำความเข้าใจ
David C

13

คิดว่ามันเป็นเพียงระดับความปลอดภัยอื่น คุณสามารถออกแบบตารางของคุณโดยไม่ต้องมีความสัมพันธ์กับกุญแจต่างประเทศ - ใช้ได้อย่างสมบูรณ์แบบ - และรับรองการมีอยู่ของหน่วยงานที่เกี่ยวข้องในชั้นธุรกิจ อย่างไรก็ตามคีย์ต่างประเทศถือเป็นแนวปฏิบัติในการออกแบบที่ดีเพราะมันเพิ่มระดับข้อ จำกัด อีกระดับในกรณีที่มีบางสิ่งเกิดขึ้นในชั้นธุรกิจ ไปกันสำหรับข้อ จำกัด ขนาดของฟิลด์และไม่ได้ใช้ varchar MAX


8

เหตุผลที่จะไม่ใช้เขตข้อมูลสูงสุดหรือเขตข้อมูลข้อความคือคุณไม่สามารถสร้างดัชนีออนไลน์ใหม่ได้เช่นสร้างใหม่ด้วย ONLINE = ON แม้ใช้ SQL Server Enterprise Edition


1
มีข้อ จำกัด เดียวกันนี้สำหรับประเภทเขตข้อมูล TEXT ดังนั้นคุณควรใช้ VARCHAR (MAX) แทน TEXT
Will Shaver

เราไม่สามารถสร้างดัชนีคลัสเตอร์ได้เนื่องจากสิ่งนี้ มันทำให้เรามีพื้นที่ดิสก์เหลือเฟือจนกว่าเราจะสามารถแยกคอลัมน์ออกเป็นตารางของตัวเอง (เราไม่สามารถที่จะล็อคโต๊ะนานกว่า 7 วินาที)
Choco Smith

4

ปัญหาเดียวที่ฉันพบคือเราพัฒนาแอปพลิเคชันของเราบน SQL Server 2005 และในกรณีเดียวเราต้องสนับสนุน SQL Server 2000 ฉันเพิ่งเรียนรู้วิธียากที่ SQL Server 2000 ไม่ชอบตัวเลือก MAX สำหรับ varchar หรือ nvarchar


2
ดังนั้นทำไมไม่เพียงพัฒนาตัวหารร่วมที่ต่ำที่สุด?
binki

4

ความคิดที่ไม่ดีเมื่อคุณรู้ว่าสนามจะอยู่ในช่วงที่กำหนด - 5 ถึง 10 ตัวอักษรตัวอย่างเช่น ฉันคิดว่าฉันจะใช้งานได้สูงสุดถ้าฉันไม่แน่ใจว่าความยาวจะเป็นเท่าไหร่ ตัวอย่างเช่นหมายเลขโทรศัพท์จะไม่เกินจำนวนอักขระที่กำหนด

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

ฉันเข้าใจประเด็นของคุณแล้ว - มีบางสาขาที่ฉันควรพิจารณาใช้ varchar (สูงสุด)

น่าสนใจที่เอกสาร MSDNสรุปแล้วค่อนข้างดี:

ใช้ varchar เมื่อขนาดของรายการข้อมูลคอลัมน์แตกต่างกันมาก ใช้ varchar (สูงสุด) เมื่อขนาดของรายการข้อมูลคอลัมน์แตกต่างกันมากและขนาดอาจเกิน 8,000 ไบต์

มีการอภิปรายที่น่าสนใจเกี่ยวกับปัญหาที่นี่


2
สำหรับสิ่งต่าง ๆ เช่นหมายเลขโทรศัพท์ฉันจะเห็นด้วยกับการใช้ฟิลด์ตัวอักษรแทน varchar ตราบใดที่คุณยังคงรักษามาตรฐานในพื้นที่เก็บข้อมูลของคุณและคุณไม่ต้องกังวลเกี่ยวกับหมายเลขโทรศัพท์จากประเทศต่าง ๆ คุณไม่ควรจำเป็นต้องใส่เขตข้อมูลตัวแปรสำหรับหมายเลขโทรศัพท์ (10 โดยไม่มีการจัดรูปแบบ) หรือรหัสไปรษณีย์ (5) หรือ 9-10 ถ้าคุณเพิ่มตัวเลขสี่หลักสุดท้าย) เป็นต้น
TheTXI

ฉันอ้างถึงหมายเลขโทรศัพท์ที่มีความยาวแตกต่างกัน บางทีฉันควรตอบคำถามนี้ อะไรก็ตามที่มีความยาวคงที่ฉันจะใช้ช่องถ่าน
RichardOD

หรือบางทีฉันควรพูดในความคิดเห็นของฉัน nchar หรือถ่าน :-)
RichardOD

2
จำนวนตัวอักษรในหมายเลขโทรศัพท์นั้นเป็นความต้องการทางธุรกิจ หากคุณจำเป็นต้องจัดเก็บรหัสมาตรฐานสากลพร้อมกับหมายเลขนั้นอาจเป็นมากกว่า 10 หรือบางส่วนของโลกอาจมีหมายเลขโทรศัพท์มากกว่า 10 หลัก ลองนึกภาพกรณีของการเปลี่ยน IPV4 เป็น IPV6 ไม่มีใครแย้งว่าเราต้องการมากกว่า 12 หลักในวันที่เก่าแก่ของ IPV4 มันอาจไม่ดีถ้า IPV6 แพร่หลาย นี่เป็นอีกครั้งที่การเปลี่ยนแปลงกฎธุรกิจในช่วงระยะเวลาหนึ่ง ตามที่กล่าวว่าการเปลี่ยนแปลงเป็นสิ่งเดียวที่คงที่เราสามารถคาดหวัง :)
pencilslate

2
ระมัดระวังเกี่ยวกับการสมมติว่าคุณรู้จำนวนตัวอักษรในฟิลด์หมายเลขโทรศัพท์หรือตัวละครประเภทใด เว้นแต่ระบบจะใช้ข้อมูลนั้นในการโทรออกจริง (ในกรณีที่คุณต้องเข้มงวดเกี่ยวกับรูปแบบ) จากนั้นผู้ใช้อาจใส่สตริงที่มีความยาวอย่างไม่คาดคิดเช่น "0123 456 78910 เพื่อขอการขยาย 45 และโอนไปยังเจมส์"
Vince Bowdren

4

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

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


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

3

ปัญหาหนึ่งคือถ้าคุณต้องทำงานกับ SQL Server หลายรุ่น MAX จะไม่ทำงานเสมอไป ดังนั้นหากคุณกำลังทำงานกับ DB รุ่นเก่าหรือสถานการณ์อื่น ๆ ที่เกี่ยวข้องกับหลาย ๆ รุ่นคุณควรระวังให้ดี


ฉันคิดว่าสมมติฐานที่ไม่ได้พูดในส่วนของ OP คือการที่เขาจัดการกับอินสแตนซ์ปี 2005 ทั้งหมดและแอปของเขาไม่จำเป็นต้องทำงานกับเวอร์ชัน 2000 (หรือ, ต่ำกว่า) ฉันเห็นด้วยกับคุณโดยสิ้นเชิงหากมีความต้องการที่จะสนับสนุนรุ่นเก่ากว่า!
John Rudy

John Rudy: ฉันจะจินตนาการว่าเป็นกรณีนี้ฉันเพิ่งรู้ว่าฉันวิ่งเข้าไปในอุปสรรคที่ตัวเองเมื่อฉันไม่คิดว่าฉันจะไป
TheTXI

จริงๆแล้วนี่เป็นปัญหาที่แพร่หลายที่ยังคงมีสิ่งที่ทันสมัยเนื่องจาก SQL CE 4 ซึ่งไม่สนับสนุนประเภทคอลัมน์ MAX เพื่อให้การทำงานร่วมกันเป็นเรื่องยุ่งยาก
JohnC

3

ดังที่ได้กล่าวไว้ข้างต้นมันเป็นข้อเสียเปรียบระหว่างการจัดเก็บและประสิทธิภาพ อย่างน้อยก็ในกรณีส่วนใหญ่

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


2

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

2) สิ่งนี้หมายความว่าเกี่ยวกับประสิทธิภาพ?

บน SQL Server 2005 ฉันสอบถามข้อมูล 13,000 แถวจากตารางที่มี 15 คอลัมน์ nvarchar (สูงสุด) ฉันหมดเวลาการค้นหาซ้ำแล้วเปลี่ยนคอลัมน์เป็น nvarchar (255) หรือน้อยกว่า

แบบสอบถามก่อนที่จะเพิ่มประสิทธิภาพเฉลี่ยที่ 2.0858 วินาที แบบสอบถามหลังการเปลี่ยนแปลงส่งคืนค่าเฉลี่ย 1.90 วินาที นั่นคือประมาณ 184 มิลลิวินาทีในการปรับปรุงแบบสอบถามแบบเลือกพื้นฐาน นั่นคือการปรับปรุง 8.8%

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


1

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


1

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


1

หากข้อมูลทั้งหมดในแถว (สำหรับคอลัมน์ทั้งหมด) จะไม่ใช้อักขระ 8000 หรือน้อยกว่าอย่างสมเหตุสมผลการออกแบบที่ชั้นข้อมูลควรบังคับใช้สิ่งนี้

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


1

การทดสอบของฉันแสดงให้เห็นว่ามีความแตกต่างเมื่อเลือก

CREATE TABLE t4000 (a NVARCHAR(4000) NULL);

CREATE TABLE tmax (a NVARCHAR(MAX) NULL);

DECLARE @abc4 NVARCHAR(4000) = N'ABC';

INSERT INTO t4000
SELECT TOP 1000000 @abc4
    FROM
    master.sys.all_columns ac1,
    master.sys.all_columns ac2;

DECLARE @abc NVARCHAR(MAX) = N'ABC';

INSERT INTO tmax
SELECT TOP 1000000 @abc
    FROM
    master.sys.all_columns ac1,
    master.sys.all_columns ac2;

SET STATISTICS TIME ON;
SET STATISTICS IO ON;

SELECT * FROM dbo.t4000;
SELECT * FROM dbo.tmax;

0

ลิงก์ที่น่าสนใจ: เหตุใดจึงใช้ VARCHAR เมื่อคุณสามารถใช้ TEXT ได้

มันเกี่ยวกับ PostgreSQL และ MySQL ดังนั้นการวิเคราะห์ประสิทธิภาพจึงแตกต่างกัน แต่ตรรกะสำหรับ "explicitness" ยังคงมีอยู่: เหตุใดจึงบังคับให้คุณต้องกังวลเกี่ยวกับบางสิ่งที่เกี่ยวข้องกับเวลาเล็กน้อย หากคุณบันทึกที่อยู่อีเมลไว้ในตัวแปรคุณจะต้องใช้ 'สตริง' ไม่ใช่ 'สตริงที่ จำกัด ที่ 80 ตัวอักษร'


1
เป็นการคล้ายกันที่คุณไม่ควรตรวจสอบข้อ จำกัด เพื่อให้แน่ใจว่าอายุของบุคคลนั้นไม่ได้เป็นจำนวนลบ
Jonathan Allen

ฉันเห็นความแตกต่างระหว่างความถูกต้องของข้อมูลและการเพิ่มประสิทธิภาพ
orip

0

ข้อเสียเปรียบหลักที่ฉันเห็นคือสมมติว่าคุณมีสิ่งนี้:

อันไหนให้ข้อมูลมากที่สุดเกี่ยวกับข้อมูลที่จำเป็นสำหรับ UI?

นี้

            CREATE TABLE [dbo].[BusData](
                [ID] [int] IDENTITY(1,1) NOT NULL,
                [RecordId] [nvarchar](MAX) NULL,
                [CompanyName] [nvarchar](MAX) NOT NULL,
                [FirstName] [nvarchar](MAX) NOT NULL,
                [LastName] [nvarchar](MAX) NOT NULL,
                [ADDRESS] [nvarchar](MAX) NOT NULL,
                [CITY] [nvarchar](MAX) NOT NULL,
                [County] [nvarchar](MAX) NOT NULL,
                [STATE] [nvarchar](MAX) NOT NULL,
                [ZIP] [nvarchar](MAX) NOT NULL,
                [PHONE] [nvarchar](MAX) NOT NULL,
                [COUNTRY] [nvarchar](MAX) NOT NULL,
                [NPA] [nvarchar](MAX) NULL,
                [NXX] [nvarchar](MAX) NULL,
                [XXXX] [nvarchar](MAX) NULL,
                [CurrentRecord] [nvarchar](MAX) NULL,
                [TotalCount] [nvarchar](MAX) NULL,
                [Status] [int] NOT NULL,
                [ChangeDate] [datetime] NOT NULL
            ) ON [PRIMARY]

หรือนี่

            CREATE TABLE [dbo].[BusData](
                [ID] [int] IDENTITY(1,1) NOT NULL,
                [RecordId] [nvarchar](50) NULL,
                [CompanyName] [nvarchar](50) NOT NULL,
                [FirstName] [nvarchar](50) NOT NULL,
                [LastName] [nvarchar](50) NOT NULL,
                [ADDRESS] [nvarchar](50) NOT NULL,
                [CITY] [nvarchar](50) NOT NULL,
                [County] [nvarchar](50) NOT NULL,
                [STATE] [nvarchar](2) NOT NULL,
                [ZIP] [nvarchar](16) NOT NULL,
                [PHONE] [nvarchar](18) NOT NULL,
                [COUNTRY] [nvarchar](50) NOT NULL,
                [NPA] [nvarchar](3) NULL,
                [NXX] [nvarchar](3) NULL,
                [XXXX] [nvarchar](4) NULL,
                [CurrentRecord] [nvarchar](50) NULL,
                [TotalCount] [nvarchar](50) NULL,
                [Status] [int] NOT NULL,
                [ChangeDate] [datetime] NOT NULL
            ) ON [PRIMARY]

3
ฉันต้องการตรรกะทางธุรกิจที่บอกฉันว่าชื่อ บริษัท สามารถมีอักขระได้สูงสุด 50 ตัวแทนที่จะใช้ตารางฐานข้อมูลสำหรับข้อมูลนั้น
Khan

ฉันเห็นด้วยกับเจฟ ฉันไม่คิดว่าร้านค้าติดตาเป็นสถานที่ที่เหมาะสมในการกำหนดกฎเกณฑ์ทางธุรกิจของคุณ และในสถาปัตยกรรมแบบเลเยอร์ UI ของคุณจะไม่รู้ด้วยซ้ำถึงความคงทนของเลเยอร์
stucampbell

ยกเว้นกรณีที่คุณกำลังใช้ค่าที่ จำกัด เฉพาะขนาดเช่นรหัส ISO สำหรับประเทศ
Ben

2
สิ่งที่เกี่ยวข้องกับการกำหนดตาราง คุณยังสามารถมีตรรกะทางธุรกิจ ฉันคิดว่าประเด็นของคุณไม่มีความเกี่ยวข้องกับการออกแบบตาราง หากคุณยังต้องการออกแบบคำจำกัดความบางอย่างในเลเยอร์ธุรกิจของคุณ แม้ว่าสิ่งที่จะทำให้รู้สึกมากขึ้นคือการใช้ proc ที่เก็บไว้ในชั้นธุรกิจ ไม่ได้กำหนดตาราง ??
carlos martini

1
ดูเหมือนว่าจะไม่เป็นที่นิยม แต่ฉันเห็นด้วยกับคาร์ลอสถ้า db ตั้งค่าขนาดสูงสุดคุณจะรู้สึกสบายใจในทุกเลเยอร์ที่คุณสร้างขึ้นมาจากสิ่งที่คุณควรทำ สิ่งนี้มีความสำคัญอย่างยิ่งหากคุณมีหลายระบบที่เขียนไปยังฐานข้อมูลของคุณ
Tim Abell

0

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

ซึ่งทำให้ฉันคิดเกี่ยวกับการจัดตำแหน่งโครงสร้างข้อมูลใน C และการตระหนักถึงการจัดตำแหน่งโดยทั่วไปถือว่าเป็นสิ่งที่ดี (TM) ความคิดที่คล้ายกันบริบทที่แตกต่าง

หน้า MSDN สำหรับหน้าและขอบเขต

หน้า MSDN สำหรับData Row-Overflow


0

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

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

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


-1

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


5
-1 สตริงที่มีความยาว 100 ที่เก็บไว้ในnvarchar(max)คอลัมน์จะไม่ใช้พื้นที่ดิสก์มากกว่าที่อยู่ในnvarchar(100)คอลัมน์
Martin Smith

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

-2

มันจะทำให้การออกแบบหน้าจอยากขึ้นเนื่องจากคุณจะไม่สามารถคาดการณ์ได้ว่าการควบคุมของคุณควรกว้างขนาดไหน

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