แนวทางปฏิบัติที่ดีที่สุดสำหรับความยาวคอลัมน์ SQL varchar [ปิด]


290

ทุกครั้งที่มีการตั้งค่าตาราง SQL ใหม่หรือเพิ่มใหม่varcharคอลัมน์ตารางที่มีอยู่ผมสงสัยว่าสิ่งหนึ่งที่: lengthสิ่งที่เป็นค่าที่ดีที่สุดสำหรับ

ดังนั้นให้บอกว่าคุณมีคอลัมน์ที่เรียกว่าประเภทname varcharดังนั้นคุณต้องเลือกความยาว ฉันไม่สามารถนึกชื่อได้> 20 ตัวอักษร แต่คุณจะไม่มีทางรู้ แต่แทนที่จะใช้ 20 ฉันจะปัดเศษขึ้นเป็นเลข 2 ^ n ถัดไปเสมอ ในกรณีนี้ฉันจะเลือก 32 เป็นความยาว ฉันทำอย่างนั้นเพราะจากมุมมองของนักวิทยาศาสตร์คอมพิวเตอร์ตัวเลข 2 ^ n ดูเหมือนevenฉันมากกว่าตัวเลขอื่นและฉันแค่สมมติว่าสถาปัตยกรรมด้านล่างสามารถจัดการตัวเลขเหล่านั้นได้ดีกว่าคนอื่นเล็กน้อย

ในทางกลับกันเซิร์ฟเวอร์ MSSQL ตัวอย่างเช่นตั้งค่าความยาวเริ่มต้นเป็น 50 เมื่อคุณเลือกที่จะสร้างคอลัมน์ varchar นั่นทำให้ฉันคิดถึงมัน ทำไมต้อง 50 มันเป็นเพียงตัวเลขสุ่มหรือตามความยาวคอลัมน์เฉลี่ยหรืออะไร

นอกจากนี้ยังอาจเป็น - หรืออาจเป็น - ที่การใช้งานเซิร์ฟเวอร์ SQL ที่แตกต่างกัน (เช่น MySQL, MSSQL, Postgres, ... ) มีค่าความยาวคอลัมน์ที่ดีที่สุดแตกต่างกัน

คำตอบ:


238

ไม่มี DBMS ที่ฉันรู้ว่ามี "การเพิ่มประสิทธิภาพ" ใด ๆ ที่จะทำให้ a ที่VARCHARมี2^nความยาวทำงานได้ดีกว่าหนึ่งที่มีmaxความยาวที่ไม่ใช่พลังของ 2

ฉันคิดว่าเวอร์ชันก่อนหน้าของ SQL Server นั้นใช้งานได้จริง VARCHARกับมีความยาว 255 แตกต่างจากที่มีความยาวสูงสุดที่สูงกว่า ฉันไม่รู้ว่านี่เป็นกรณีนี้หรือไม่

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

คุณควรดูmaxความยาวที่ระบุสำหรับVARCHARคอลัมน์เป็นข้อ จำกัด (หรือกฎทางธุรกิจ) แทนที่จะเป็นเรื่องทางเทคนิค / ทางกายภาพ

สำหรับ PostgreSQL การตั้งค่าที่ดีที่สุดคือการใช้งานtextโดยไม่จำกัดความยาวและCHECK CONSTRAINTจำนวนอักขระที่ จำกัด ให้กับธุรกิจของคุณ

หากความต้องการนั้นเปลี่ยนแปลงไปการเปลี่ยนแปลงข้อ จำกัด การตรวจสอบนั้นเร็วกว่าการเปลี่ยนแปลงตาราง (เนื่องจากตารางไม่จำเป็นต้องเขียนใหม่)

เช่นเดียวกับที่สามารถนำมาใช้สำหรับ Oracle และอื่น ๆ - ใน Oracle มันจะVARCHAR(4000)แทนtextแม้ว่า

ฉันไม่รู้ว่ามีความแตกต่างของหน่วยเก็บข้อมูลจริงหรือไม่ระหว่างVARCHAR(max)และVARCHAR(500)ใน SQL Server แต่เห็นได้ชัดว่ามีผลกระทบต่อประสิทธิภาพเมื่อใช้เมื่อเทียบกับvarchar(max)varchar(8000)

ดูลิงค์นี้ (โพสต์โดย Erwin Brandstetter เป็นความคิดเห็น)

แก้ไข 2013-09-22

เกี่ยวกับความคิดเห็นของ bigown:

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

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

สำหรับ MySQL คู่มือบอกว่า " ในกรณีส่วนใหญ่ALTER TABLEทำสำเนาชั่วคราวของตารางต้นฉบับ " และการทดสอบของฉันเองยืนยันว่า: การรันALTER TABLEบนตารางที่มี 1.2 ล้านแถว (เช่นเดียวกับในการทดสอบของฉันกับ Postgres) เพื่อเพิ่มขนาดของคอลัมน์ใช้เวลา 1.5 นาที ใน MySQL อย่างไรก็ตามคุณไม่สามารถใช้ "วิธีแก้ไข" เพื่อใช้ข้อ จำกัด การตรวจสอบเพื่อ จำกัด จำนวนอักขระในคอลัมน์

สำหรับ SQL Server ฉันไม่พบคำสั่งที่ชัดเจนเกี่ยวกับเรื่องนี้ แต่เวลาดำเนินการเพื่อเพิ่มขนาดของvarcharคอลัมน์ (อีกตาราง 1.2 ล้านแถวจากด้านบน) บ่งชี้ว่าไม่มีการเขียนซ้ำเกิดขึ้น

แก้ไข 2017-01-24

ดูเหมือนว่าฉันผิด (อย่างน้อยบางส่วน) เกี่ยวกับ SQL Server ดูคำตอบนี้จากแอรอนเบอร์ทรานด์ที่แสดงให้เห็นว่าความยาวที่ประกาศnvarcharหรือvarcharคอลัมน์นั้นสร้างความแตกต่างอย่างมากสำหรับประสิทธิภาพ


34
ที่จริงแล้วมีความแตกต่างระหว่าง VARCHAR (255) และ VARCHAR (500) แม้ว่าคุณจะใส่อักขระ 1 ตัวในคอลัมน์ดังกล่าว ค่าที่ต่อท้ายแถวจะเป็นจำนวนเต็มที่เก็บความยาวที่แท้จริงของข้อมูลที่เก็บไว้ ในกรณีของ VARCHAR (255) มันจะเป็นจำนวนเต็ม 1 ไบต์ ในกรณีของ VARCHAR (500) มันจะเป็น 2 ไบต์ มันแตกต่างกันเล็กน้อย แต่ก็ควรระวังไว้ ฉันไม่มีข้อมูลใด ๆ ที่ส่งผลกระทบต่อประสิทธิภาพการทำงาน แต่ฉันคิดว่ามันเล็กมากจนไม่คุ้มกับการค้นคว้า
NB

1
@NB: นั่นคือสิ่งที่ฉันอ้างถึงสำหรับค่า "magic" 255 ของ SQL Server ขอขอบคุณสำหรับการชี้แจง.
a_horse_with_no_name

4
@NB คุณหมายถึง RDBMS ใด? เซิร์ฟเวอร์ SQL มีผลกระทบต่อประสิทธิภาพ [N] VARCHAR (สูงสุด) ทำงานช้ากว่า [N] VARCHAR (n) เล็กน้อย ฉันเพิ่งถูกส่งต่อไปยังไซต์นี้ เช่นเดียวกันไม่เป็นความจริงสำหรับ PostgreSQL สำหรับทุกสิ่งที่ฉันรู้
Erwin Brandstetter

@ErwinBrandstetter: ขอบคุณสำหรับลิงค์ ดูเหมือนว่าvarchar(max)อาจเป็นมากกว่าของ OracleCLOB
a_horse_with_no_name

1
เปลี่ยนความยาว varchar ไม่ได้เขียนตาราง เพียงแค่ตรวจสอบความยาวข้อ จำกัด เทียบกับตารางทั้งหมดเหมือนกับ CHECK CONSTRAINT หากคุณเพิ่มความยาวไม่ต้องทำอะไรแทรกเพียงครั้งต่อไปหรือการอัปเดตจะยอมรับความยาวที่ใหญ่กว่า หากคุณลดความยาวและแถวทั้งหมดผ่านข้อ จำกัด เล็ก ๆ ใหม่ Pg จะไม่ดำเนินการใด ๆ เพิ่มเติมนอกเหนือจากที่จะอนุญาตให้ส่วนแทรกหรืออัพเดตถัดไปเขียนเฉพาะความยาวใหม่
Maniero

70

VARCHAR(255)และVARCHAR(2)ใช้เวลาตรงกับจำนวนเดียวกันของพื้นที่บนดิสก์! เหตุผลเดียวที่จะ จำกัด มันคือถ้าคุณมีความต้องการที่เฉพาะเจาะจงสำหรับมันให้เล็กลง มิฉะนั้นทำให้พวกเขาทั้งหมด 255

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

ดู: ขนาด varchar ที่เหมาะสมสำหรับ MySQL คืออะไร?


7
ทำไมไม่ให้พวกเขาทั้งหมดVARCHAR(MAX)? พื้นที่ไม่ใช่สิ่งที่ควรพิจารณาเมื่อสร้างแบบจำลองฐานข้อมูล โดเมนที่คุณกำลังสร้างแบบจำลองควรขับเคลื่อนประเภทข้อมูลและขนาด
Oded

6
@Oded VARCHAR(MAX)ไม่เหมือนกับvarchar(255)หรือvarchar(65535)- varchar max เป็นประเภทtextข้อมูล และถึงจุดของคุณ - ถ้าเขารู้ว่า "โดเมนที่เขาเป็นแบบจำลอง" เขาจะไม่ถามคำถามนี้ เห็นได้ชัดว่าเขาไม่รู้ว่าข้อมูลของเขาจะใหญ่แค่ไหนและฉันก็มั่นใจกับเขาว่าการทำให้มันเต็มขนาดนั้นไม่ได้เจ็บปวดอะไรเลย
Ariel

4
@Ariel: มีปัญหาและข้อ จำกัด เกี่ยวกับดัชนีที่ต้องพิจารณาด้วย คุณไม่สามารถมีดัชนีเมื่อทั้งสี่คอลัมน์(a,b,c,d) VARCHAR(255)
ypercubeᵀᴹ

@ypercube นั้นเป็นจริงถ้าคอลัมน์ของคุณต้องการดัชนีคุณต้องระวังขนาดให้มากขึ้น แต่คอลัมน์ส่วนใหญ่ไม่ต้องการดัชนีดังนั้นเวลาส่วนใหญ่ที่คุณไม่จำเป็นต้องกังวล
Ariel

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

54

เมื่อใดก็ตามที่ฉันตั้งค่าตาราง SQL ใหม่ฉันรู้สึกเหมือนกันประมาณ 2 ^ n มากกว่า "แม้" ... แต่เพื่อสรุปคำตอบที่นี่ไม่มีผลกระทบอย่างมีนัยสำคัญต่อพื้นที่เก็บข้อมูลเพียงแค่กำหนด varchar (2 ^ n) หรือแม้กระทั่ง varchar (MAX)

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

อีกสิ่งที่ควรพิจารณาจาก Bill Karwin :

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

โดยทั่วไปเพียงแค่มาพร้อมกับข้อ จำกัด ทางธุรกิจที่เหมาะสมและข้อผิดพลาดในขนาดที่ใหญ่ขึ้นเล็กน้อย @onedaywhen เมื่อชี้ให้เห็นชื่อครอบครัวในสหราชอาณาจักรมักจะอยู่ระหว่าง 1-35 ตัวอักษร หากคุณตัดสินใจที่จะทำให้เป็น varchar (64) คุณจะไม่ทำร้ายอะไรเลย ... เว้นแต่คุณจะเก็บชื่อสกุลของผู้ชายคนนี้ที่มีความยาวไม่เกิน 666 ตัวอักษร ในกรณีนั้นอาจ varchar (1028) เหมาะสมกว่า

และในกรณีที่เป็นประโยชน์ต่อไปนี้เป็นสิ่งที่ varchar 2 ^ 5 ถึง 2 ^ 10 อาจดูเหมือนถ้าเต็มไปด้วย:

varchar(32)     Lorem ipsum dolor sit amet amet.

varchar(64)     Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie

varchar(128)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas

varchar(256)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt

varchar(512)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie

varchar(1024)   Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie
                dapibus leo lobortis eleifend. Vivamus vitae diam turpis. Vivamu
                nec tristique magna, vel tincidunt diam. Maecenas elementum semi
                quam. In ut est porttitor, sagittis nulla id, fermentum turpist.
                Curabitur pretium nibh a imperdiet cursus. Sed at vulputate este
                proin fermentum pretium justo, ac malesuada eros et Pellentesque
                vulputate hendrerit molestie. Aenean imperdiet a enim at finibus
                fusce ut ullamcorper risus, a cursus massa. Nunc non dapibus vel
                Lorem ipsum dolor sit amet, consectetur Praesent ut ultrices sit

31

ค่าที่ดีที่สุดคือค่าที่เหมาะสมกับข้อมูลตามที่กำหนดไว้ในโดเมนพื้นฐาน

สำหรับบางโดเมนVARCHAR(10)เหมาะสำหรับNameแอตทริบิวต์สำหรับโดเมนอื่นVARCHAR(255)อาจเป็นตัวเลือกที่ดีที่สุด


15

การเพิ่มคำตอบของ a_horse_with_no_name อาจทำให้คุณสนใจสิ่งต่อไปนี้ ...

มันไม่ได้สร้างความแตกต่างใด ๆ ไม่ว่าคุณจะประกาศคอลัมน์เป็น VARCHAR (100) หรือ VACHAR (500)

-- try to create a table with max varchar length
drop table if exists foo;
create table foo(name varchar(65535) not null)engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length - 2 bytes for the length
drop table if exists foo;
create table foo(name varchar(65533) not null)engine=innodb;

Executed Successfully

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65533))engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65532))engine=innodb;

Executed Successfully

อย่าลืมไบต์ความยาวและไบต์ nullable ดังนั้น:

name varchar(100) not null จะเป็น 1 ไบต์ (ความยาว) + สูงสุด 100 ตัวอักษร (ละติน 1)

name varchar(500) not null จะเป็น 2 ไบต์ (ความยาว) + สูงสุด 500 ตัวอักษร (ละติน 1)

name varchar(65533) not null จะเป็น 2 ไบต์ (ความยาว) + สูงสุด 65533 ตัวอักษร (ละติน 1)

name varchar(65532) จะเป็น 2 ไบต์ (ความยาว) + สูงสุด 65532 ตัวอักษร (ละติน 1) + 1 ไบต์ที่ว่าง

หวังว่าจะช่วย :)


คุณกำลังใช้งาน MySQL และคำถามเกี่ยวกับ MSSQL
Bogdan Mart

6

ตรวจสอบกับผู้เชี่ยวชาญด้านโดเมนธุรกิจของคุณเสมอ หากเป็นเช่นนั้นให้มองหามาตรฐานอุตสาหกรรม ตัวอย่างเช่นหากโดเมนที่มีปัญหาคือชื่อสกุลของบุคคลธรรมดา (นามสกุล) สำหรับธุรกิจในสหราชอาณาจักรฉันจะไปที่แคตตาล็อกมาตรฐานข้อมูล Govtalk ของสหราชอาณาจักรสำหรับข้อมูลบุคคลและค้นพบว่าชื่อครอบครัวจะอยู่ระหว่าง 1 ถึง 35 ตัวอักษร .


3

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


-2

ในแง่ที่ถูกต้องแม้ว่าสิ่งใดก็ตามที่ต่ำกว่า 2 ^ 8 ตัวอักษรจะยังคงลงทะเบียนเป็นไบต์ของข้อมูล

หากคุณคำนึงถึงตัวละครฐานที่ทิ้งอะไรไว้ด้วย VARCHAR <255 ว่าเป็นการสิ้นเปลืองเนื้อที่ในจำนวนเดียวกัน

255 เป็นคำจำกัดความพื้นฐานที่ดีเว้นแต่คุณต้องการลดการป้อนข้อมูลมากเกินไปโดยเฉพาะ


" แม้ว่าสิ่งใดก็ตามที่ต่ำกว่า 2 ^ 8 ตัวอักษรจะยังคงลงทะเบียนเป็นข้อมูลไบต์ " - ผิด ฐานข้อมูลจะจัดเก็บอักขระได้มากเท่าที่ระบุไว้ในประเภท VARCHAR ไม่มีช่องว่าง "ลงทะเบียน" ถูกสงวนไว้หรือเริ่มต้นเมื่อประกาศคอลัมน์
a_horse_with_no_name
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.