มีข้อดีกว่า varchar (500) มากกว่า varchar (8000) หรือไม่?


91

ฉันได้อ่านเรื่องนี้ในฟอรัม MSDN และที่นี่ก็ยังไม่ชัดเจน ฉันคิดว่าถูกต้อง: Varchar (สูงสุด) จะถูกจัดเก็บเป็นประเภทข้อมูลข้อความดังนั้นจึงมีข้อเสีย สมมติว่าฟิลด์ของคุณมีความยาวน้อยกว่า 8000 อักขระได้อย่างน่าเชื่อถือ เช่นเดียวกับเขตข้อมูล BusinessName ในตารางฐานข้อมูลของฉัน ในความเป็นจริงชื่อธุรกิจมักจะต่ำกว่า (ดึงตัวเลขออกจากหมวก) 500 อักขระ ดูเหมือนว่าช่อง varchar จำนวนมากที่ฉันวิ่งข้ามจะลดลงภายใต้จำนวนอักขระ 8k

ฉันควรทำให้ฟิลด์นั้นเป็น varchar (500) แทน varchar (8000) หรือไม่? จากสิ่งที่ฉันเข้าใจเกี่ยวกับ SQL ไม่มีความแตกต่างระหว่างสองสิ่งนี้ ดังนั้นเพื่อให้ชีวิตง่ายขึ้นฉันต้องการกำหนดฟิลด์ varchar ทั้งหมดของฉันเป็น varchar (8000) มีข้อบกพร่องหรือไม่?

ที่เกี่ยวข้อง: ขนาดของคอลัมน์ varchar (ฉันไม่รู้สึกว่าคนนี้ตอบคำถามของฉัน)


6
ลองนึกภาพว่าพยายามใส่ชื่อธุรกิจที่มีความยาว 500 ตัวอักษรบนนามบัตร ... :)
OMG Ponies

2
@OMG Ponies: ทุกครั้งที่ฉันเห็นชื่อผู้ใช้ของคุณฉันหัวเราะเบา ๆ ตอนนี้คุณกำลังพูดอะไรอยู่? (ล้อเล่นนะ)
jcollum

4
@jcollum: SpaceMan Spiff จะได้รับการโหวตของฉันเสมอ นั่นไม่เป็นความจริง - ใด ๆคาลวินและฮอบส์จะทำ แต่โดยเฉพาะอย่างยิ่งคนที่แกะสลักหิมะ หรือไทรันโนซอรัสบิน F-14 แต่ฉันพูดนอกเรื่อง ...
OMG Ponies

คำตอบ:


21

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


3
เข้าท่า ... สำหรับสิ่งที่มีความยาวสูงสุดตามธรรมชาติ แต่คุณจะทำอย่างไรเมื่อความยาวสูงสุดไม่ชัดเจน? เช่นชื่อธุรกิจ
jcollum

2
สำหรับบางอย่างเช่นนั้นถ้าฉันไม่คาดการณ์วิธีการคาดการณ์ว่าขนาดอาจเป็นเท่าใดฉันมักจะใช้ varchar (8000) หรือ varchar (สูงสุด) ขึ้นอยู่กับประเภทของข้อมูล
BBlake

4
ดูเหมือนว่าสิ่งนี้จะสร้างความแตกต่างในประสิทธิภาพแม้ในปี 2017: dba.stackexchange.com/a/162117/1822
a_horse_with_no_name

2
คำตอบอื่น ๆ ที่ผ่านมาแสดงให้เห็นว่ามีมีค่าใช้จ่าย: มันมีผลต่อการเพิ่มประสิทธิภาพตรรกะคำตอบที่มาร์ตินสมิ ธและยังพิจารณาปัญหา 8K ขนาดแถวทั้งหมดที่กล่าวถึงโดยGBNและโอลิเวอร์
ToolmakerSteve

124

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

สิ่งนี้ครอบคลุมโดย SQL Kiwi ที่นี่

ขนาดที่แท้จริงของข้อมูลที่จัดเก็บนั้นไม่มีสาระสำคัญ - เป็นขนาดที่เป็นไปได้ที่มีความสำคัญ

ในทำนองเดียวกันหากใช้ตารางที่ปรับแต่งหน่วยความจำตั้งแต่ปี 2559 เป็นไปได้ที่จะใช้คอลัมน์ LOB หรือการรวมกันของความกว้างของคอลัมน์ที่อาจเกินขีด จำกัด การไหลเวียน แต่มีโทษ

คอลัมน์ (สูงสุด) จะถูกจัดเก็บไว้นอกแถวเสมอ สำหรับคอลัมน์อื่น ๆ ถ้าขนาดแถวข้อมูลในข้อกำหนดของตารางสามารถเกิน 8,060 ไบต์ SQL Server จะผลักคอลัมน์ที่มีความยาวตัวแปรที่ใหญ่ที่สุดออกจากแถว อีกครั้งไม่ได้ขึ้นอยู่กับจำนวนข้อมูลที่คุณจัดเก็บไว้ที่นั่น

ซึ่งอาจส่งผลเสียอย่างมากต่อการใช้หน่วยความจำและประสิทธิภาพ

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

ย้อนกลับไปในกลไกของ SQL Server เองในกรณีที่คล้ายกันคือเมื่อคำนวณการให้หน่วยความจำเพื่อจัดสรรสำหรับSORTการดำเนินการ SQL Server จะถือว่าvarchar(x)คอลัมน์จะใช้x/2ไบต์โดยเฉลี่ย

ถ้าของคุณมากที่สุดvarcharคอลัมน์ฟูลเลอร์กว่าที่ว่านี้สามารถนำไปสู่การดำเนินงานที่จะทะลักsorttempdb

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

สิ่งนี้กล่าวถึงในส่วนที่ 2 ของ SQL Workshops Webcast 1 ซึ่งสามารถดาวน์โหลดได้จากที่นี่หรือดูด้านล่าง

use tempdb;

CREATE TABLE T(
id INT IDENTITY(1,1) PRIMARY KEY,
number int,
name8000 VARCHAR(8000),
name500 VARCHAR(500))

INSERT INTO  T 
(number,name8000,name500)
SELECT number, name, name /*<--Same contents in both cols*/
FROM master..spt_values

SELECT id,name500
FROM T
ORDER BY number

ภาพหน้าจอ

SELECT id,name8000
FROM T
ORDER BY number

ภาพหน้าจอ


1
ดังนั้นถ้าค่าเกือบทั้งหมดของฉันคือ 3 หรือ 4 ตัวอักษรไม่สามารถเกิน 4 ตัวอักษรได้และฉันต้องการหลีกเลี่ยง ความกว้างต้องไม่เกิน 4 ตัวอักษร คุณคิดอย่างไร?
AK

12
@AlexKuznetsov - สำหรับสถานการณ์นั้นฉันจะประกาศพวกเขาchar(4)เนื่องจากมีค่าใช้จ่าย 2 ไบต์ต่อคอลัมน์ตัวแปร
Martin Smith

9

นอกเหนือจากแนวทางปฏิบัติที่ดีที่สุด (คำตอบของ BBlake)

  • คุณได้รับคำเตือนเกี่ยวกับขนาดแถวสูงสุด (8060) ไบต์และความกว้างดัชนี (900 ไบต์) พร้อม DDL
  • DML จะตายหากคุณเกินขีด จำกัด เหล่านี้
  • ANSI PADDING ON เป็นค่าเริ่มต้นเพื่อให้คุณสามารถจัดเก็บช่องว่างทั้งหมดได้

38
เพียงชี้แจงเกี่ยวกับ ANSI PADDING ON: เมื่อใช้nvarcharและvarcharชนิดเท่านั้นซึ่งหมายความว่าช่องว่างต่อท้ายจะถูกเก็บไว้เมื่อแทรก - ไม่ว่าค่าที่มีเบาะที่มีช่องว่างขนาดของคอลัมน์ในขณะที่และchar nchar
Ben M

9

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

  • คอลัมน์ทั้งหมดที่คุณใช้ในINDEX - ต้องไม่เกิน 900 ไบต์
  • คอลัมน์ทั้งหมดในคำสั่ง ORDER BYต้องไม่เกิน 8060 ไบต์ นี่เป็นเรื่องยากที่จะเข้าใจเนื่องจากใช้กับบางคอลัมน์เท่านั้น ดูSQL 2008 R2 ขนาดแถวเกินขีด จำกัดสำหรับรายละเอียด)
  • หากขนาดของแถวทั้งหมดเกิน 8060 ไบต์คุณจะได้รับ " page spill " สำหรับแถวนั้น สิ่งนี้อาจส่งผลต่อประสิทธิภาพ (เพจเป็นหน่วยการจัดสรรใน SQLServer และได้รับการแก้ไขที่ 8000 ไบต์ + ค่าใช้จ่ายบางส่วนการเกินนี้จะไม่รุนแรง แต่เป็นที่สังเกตได้และคุณควรพยายามหลีกเลี่ยงหากทำได้อย่างง่ายดาย)
  • โครงสร้างข้อมูลภายในอื่น ๆ อีกมากมายบัฟเฟอร์และสุดท้ายไม่ท้ายสุดตัวแปรของคุณเองและตัวแปรตารางล้วนต้องสะท้อนขนาดเหล่านี้ ด้วยขนาดที่มากเกินไปการจัดสรรหน่วยความจำที่มากเกินไปอาจส่งผลต่อประสิทธิภาพ

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

ในตัวอย่างชื่อธุรกิจของคุณให้นึกถึงตำแหน่งที่คุณจะแสดง มีพื้นที่ 500 ตัวอักษรจริงหรือ ?? ถ้าไม่เป็นเช่นนั้นก็มีจุดเล็ก ๆ น้อย ๆ ในการจัดเก็บ http://en.wikipedia.org/wiki/List_of_companies_of_the_United_Statesแสดงรายชื่อ บริษัท บางแห่งและสูงสุดคือประมาณ 50 อักขระ ฉันจะใช้ 100 สำหรับคอลัมน์สูงสุด อาจจะมากกว่าเช่น 80


2

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

แม้ว่า varchar จะไม่ได้จองพื้นที่ในฐานข้อมูลสำหรับพื้นที่ที่ไม่ได้ใช้งาน แต่ฉันจำได้ว่าเวอร์ชันของ SQL Server มี snit เกี่ยวกับแถวฐานข้อมูลที่กว้างกว่าจำนวนไบต์ (จำจำนวนที่แน่นอนไม่ได้) และทิ้งไป ข้อมูลใด ๆ ที่ไม่พอดี จำนวนไบต์เหล่านั้นถูกสงวนไว้สำหรับสิ่งที่อยู่ภายใน SQL Server


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

1
@jcollum: ในตัวอย่างของคุณ 500 ดูเหมือนจะไม่เหมาะสมกับชื่อธุรกิจ
Otis

1
@BBlake: ไม่ว่าจะมีค่าใช้จ่ายในการจัดเก็บเท่าใดหาก SQL Server ยังคงมีข้อ จำกัด ด้านขนาดแถวมากกว่าก็ไม่สำคัญว่าคุณจะมีพื้นที่เก็บข้อมูลเท่าใด คุณสามารถจัดเก็บทุกอย่างใน textblobs แต่มีการดำเนินการ SQL บางอย่างที่คุณไม่สามารถทำได้บน blob ที่คุณสามารถทำได้บน varchar
Otis

2
@Otis: ประเด็นของฉันคือ: ไม่มีข้อ จำกัด ที่แท้จริงเกี่ยวกับขนาดของชื่อธุรกิจ เว้นแต่จะมีกฎหมายบางแห่ง ดังนั้นในกรณีนี้ฉันจะสร้างฟิลด์วาร์ชาร์ (8000) และเรียกมันว่าวัน ความคิดของฉันเป็นแบบนี้: ข้อ จำกัด จริงหรือ? varchar (x) ไม่มีข้อ จำกัด จริงหรือ? วาร์ชาร์ (8000)
jcollum

24
ฉันคิดว่า 30 ตัวอักษรเหมาะกับชื่อเมืองจนกระทั่งฉันได้เห็น El Pueblo de Nuestra Señora la Reina de los Ángeles del Río de Porciúncula
StuartLC
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.