แนวปฏิบัติที่ดีที่สุดในปัจจุบันเกี่ยวกับการปรับขนาด varchar ใน SQL Server คืออะไร


12

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

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

ที่เก็บข้อมูล
หลังจากอ่านเกี่ยวกับวิธีการทำงานของหน่วยเก็บข้อมูลแบบ in-row และ out-of-row และโปรดทราบว่าการจัดเก็บข้อมูลจริงนั้น จำกัด อยู่ที่ข้อมูลจริงฉันคิดว่าตัวเลือกของ n นั้นมีพื้นที่เก็บข้อมูลน้อยมากหรือไม่มีเลย ทำให้แน่ใจว่ามันใหญ่พอที่จะเก็บทุกอย่างไว้ได้) แม้แต่การใช้ varchar (สูงสุด) ก็ไม่ควรมีผลกระทบใด ๆ ต่อการจัดเก็บ เป้าหมายอาจ จำกัด ขนาดที่แท้จริงของแต่ละแถวข้อมูลไว้ที่ ~ 8000 ไบต์หากเป็นไปได้ นั่นเป็นการอ่านที่ถูกต้องในสิ่งต่าง ๆ หรือไม่?

บริบท
ข้อมูลลูกค้าบางส่วนของเรามีความผันผวนเล็กน้อยดังนั้นโดยทั่วไปเราจะสร้างคอลัมน์ให้กว้างกว่าที่พวกเขาต้องการเพียงเล็กน้อยโดยพูดให้ใหญ่ขึ้น 15-20% สำหรับคอลัมน์เหล่านั้น ฉันสงสัยว่ามีสิ่งอื่นที่ต้องพิจารณาเป็นพิเศษหรือไม่ ตัวอย่างเช่นบางคนที่ฉันทำงานด้วยบอกให้ฉันใช้ขนาด 2 ^ n - 1 ขนาด (ฉันไม่พบหลักฐานว่าเป็นเรื่องที่ ....

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

คำถามคือเท่าไหร่และมีแนวทางทางเทคนิคหรือไม่


MongoDB ใช้การจัดสรรดิสก์ 2 ^ n สำหรับเอกสาร SQL Server ไม่ได้ใช้กลยุทธ์นี้
Michael Green

คำตอบ:


19

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

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

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

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

เป้าหมายอาจ จำกัด ขนาดที่แท้จริงของแต่ละแถวข้อมูลไว้ที่ ~ 8000 ไบต์หากเป็นไปได้

ฉันไม่แน่ใจว่าสิ่งที่คุณได้รับที่นี่ SQL Server จะ จำกัด คุณไว้ที่ 8000 ไบต์เท่านั้น ใช้ประเภทลอบ - VARCHAR(MAX), NVARCHAR(MAX), VARBINARY(MAX), XMLและเลิกTEXT, NTEXTและIMAGEประเภท - ให้สำหรับการไปเกินกว่าที่เริ่มต้นการ จำกัด ขนาดของหน้า แต่ที่เป็นเพียง แต่เนื่องจากการวางตัวชี้ (16 หรือมากกว่าไบต์ขึ้นอยู่กับชนิดและขึ้นอยู่กับ ขนาดของค่าที่ถูกเก็บไว้นอกแถวเมื่อใช้MAXชนิด) ขีด จำกัด ทางกายภาพที่แท้จริงของหน้าข้อมูลไม่เปลี่ยนแปลง

เป้าหมายของคุณควรใช้พื้นที่ทางกายภาพน้อยที่สุดเพื่อจัดเก็บสิ่งที่แอพ / ธุรกิจจำเป็นต้องจัดเก็บโดยไม่ทำลายหรือตัดทอนเช่นค่าที่ไม่สมบูรณ์สูญเสียความหมายหรือทำให้เกิดปัญหาดาวน์สตรีม หากคุณต้องการเก็บสิ่งของไว้ที่ 12,000 ตัวให้ใช้VARCHAR(MAX)เพราะนั่นคือสิ่งที่จำเป็น หากคุณกำลังจัดเก็บหมายเลขโทรศัพท์หรือรหัส zip / ไปรษณีย์แล้วมันจะฉลาดที่จะใช้และขาดความรับผิดชอบกับการใช้งานVARCHAR(100)VARCHAR(MAX)

ข้อมูลลูกค้าของเราบางส่วนมีความผันผวนเล็กน้อยดังนั้นโดยทั่วไปเราจะสร้างคอลัมน์ให้กว้างกว่าที่พวกเขาต้องการเพียงเล็กน้อยโดยพูดให้ใหญ่ขึ้น 15-20% สำหรับคอลัมน์เหล่านั้น ฉันสงสัยว่ามีข้อพิจารณาพิเศษอื่นใดอีกหรือไม่

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

แต่ในการที่จะสนับสนุนผู้สนับสนุนของปีศาจชั่วครู่หนึ่ง: ค่า "มากกว่า 15-20% ที่ต้องการ" จะไม่เป็นค่าที่ต้องการจริงได้อย่างไร? สมมติว่ามีการสนทนาเกี่ยวกับการเพิ่มคอลัมน์ใหม่และมีคนแนะนำตัวอักษร 50 ตัวจากนั้นมีคนอื่นพูดว่า "ก็ดีอีก 20% คือ 60 ดังนั้นลองทำ 60 เพราะใครบางคนอาจมี 60 คน" ถ้ามันเป็นความจริงที่ว่าลูกค้าอาจมี 60, 60 คือและเป็นเสมอค่าที่จำเป็นจริงและ 50 ผิดตลอดเวลา

แน่นอนว่ามันจะช่วยได้หากมีสิ่งบ่งชี้บางอย่างเกี่ยวกับแหล่งที่มาของข้อมูลเพราะ:

  1. ถ้าคุณสร้าง "URL" 1024 และบางคนต้องการ 1,060 ก็จำเป็นต้องเป็น 1,060 (ในทำนองเดียวกันถ้าคุณสร้าง URL VARCHARและรับเรื่องร้องเรียนว่ามันกำลังทำให้อักขระ Unicode ซึ่งได้รับอนุญาตในชื่อโดเมนตอนนี้ต้องเป็นNVARCHAR) แต่
  2. ถ้ามีคนต้องการเพิ่ม 1,000 ตัวอักษรลงในช่องแสดงความคิดเห็นที่ จำกัด ตัวอักษร 500 ตัวก็ยังคงต้องมีเพียง500 คนเท่านั้นที่สามารถแสดงความคิดเห็นน้อยลง (ความท้าทายอย่างมากสำหรับฉัน ;-) แต่ProductSKUควรใหญ่พอที่จะพอดีกับทุกคน ของ SKU ของลูกค้า

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

คุณกำลังทำมากของสมมติฐานที่นี่ แน่นอนว่าบางสาขาอาจใหญ่ขึ้น แต่แล้วอีกครั้งพวกเขาอาจจะไม่ หรือบางคนอาจเล็กลง บางคนสามารถเปลี่ยนจากการไม่ใช่ Unicode เป็น Unicode (เมื่อพวกเขารู้ว่าโลกกำลังเล็กลงและไม่สามารถสันนิษฐานได้ว่านามสกุลจะมีตัวอักษรภาษาอังกฤษพื้นฐาน ASCII / US เท่านั้น) หรือพวกเขาสามารถหยุดส่งข้อมูลได้ หรือพวกเขาสามารถเพิ่มอย่างน้อยหนึ่งฟิลด์ในอนาคต การรวมกันของสิ่งนี้และสิ่งอื่น ๆ เหตุใดจึงเน้นเฉพาะVARCHARคอลัมน์ เกิดอะไรขึ้นถ้าพวกเขากำลังส่งINTค่าและในปีหรือสองปีพวกเขาถึงค่าสูงสุดและเริ่มส่งBIGINT? จะเกิดอะไรขึ้นถ้าพวกเขามีฟิลด์ "สถานะ" ที่มีค่า 0 - 5 คุณกำลังจะสันนิษฐานINTซึ่งเป็น "เบาะ" ตามที่ช่วยให้การเจริญเติบโต แต่ควรจะเป็นTINYINTอย่างไร

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

ดังนั้นแนวทางคือ:

  1. อย่าเสียเวลาและพลังงานในการพยายามตอบคำถามที่ไม่สามารถตอบได้
  2. ให้มุ่งเน้นไปที่การรับข้อมูลให้มากที่สุดเท่าที่จะเป็นไปได้เกี่ยวกับข้อมูลที่แท้จริงของลูกค้าของคุณและไปกับสิ่งนั้น (เช่นการตัดสินใจโดยใช้ข้อมูล ;-)

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


1
ฉันเห็นด้วยกับโซโลมอน @ Aristotle2600 - อย่างไรก็ตามคุณอาจต้องการดูคำตอบของฉันเกี่ยวกับความแตกต่างระหว่าง a varchar(255)และ a varchar(256)สำหรับการพิจารณาเพิ่มเติม
Max Vernon

ขอบคุณฉันรู้สึกว่ามันจะเป็นแบบนี้และ "ใช้เฉพาะสิ่งที่คุณต้องการ" เป็นเพียงแนวทางการจัดการทรัพยากรที่ดีรอบด้าน แต่ข้อมูลลูกค้าของเราบางส่วนมีความผันผวนเล็กน้อยดังนั้นโดยทั่วไปเราจะสร้างคอลัมน์ให้กว้างกว่าที่พวกเขาต้องการเพียงเล็กน้อยโดยพูดให้ใหญ่ขึ้น 15-20% สำหรับคอลัมน์เหล่านั้น ฉันสงสัยว่ามีสิ่งอื่นที่ต้องพิจารณาเป็นพิเศษหรือไม่ ตัวอย่างเช่นบางคนที่ฉันทำงานด้วยบอกให้ฉันใช้ขนาด 2 ^ n - 1 ขนาด (ฉันไม่พบหลักฐานว่าเป็นเรื่องที่ .... แต่ดูเหมือนจะไม่มีอะไรอื่นนอกจากให้เล็กที่สุดเท่าที่จะทำได้
aristotle2600

1
@ aristotle2600 ไม่แน่ใจว่าจะใช้ "2 ^ n - 1" แต่ฉันยังต้องถาม: มันเป็นไปได้ในทางทฤษฎีหรือไม่ที่จะทำบางสิ่งที่ใหญ่กว่าที่จำเป็นต้องเป็น? ขนาดที่ใหญ่ขึ้น 15-20% จะไม่เป็นขนาดที่จะต้องไม่แตกใช่มั้ย ;-) ฉันแน่ใจว่ามันจะช่วยได้ถ้าคุณมีความชัดเจนมากขึ้นในแหล่งข้อมูลเพราะก) ถ้าคุณสร้าง "URL" 1024 และมีคนต้องการ 1,060 แล้วก็ต้องเป็น 1,060 แต่ข) ถ้ามีคนต้องการเพิ่ม 1,000 chars ไปยังช่องแสดงความคิดเห็น 500 ข้อ จำกัด char จากนั้นก็ยังต้องการเพียง500 คนสามารถป้อนความคิดเห็นน้อยลง แต่ SKU ผลิตภัณฑ์ควรใหญ่กว่าพอ
โซโลมอน Rutzky

@ aristotle2600 ฉันเพิ่งเพิ่มความคิดเห็นของคุณที่นี่ลงในคำถามเนื่องจากพวกเขาให้บริบทที่ดี ฉันยังเพิ่มสิ่งที่ส่วนท้ายของคำตอบของฉัน :)
โซโลมอน Rutzky

ขอบคุณมากสำหรับคำตอบของคุณ! ใช่ชื่อและที่อยู่จะผันผวน เท่าที่ความขัดแย้งเพิ่มขึ้น 20% ฉันเห็นสิ่งที่คุณหมายถึง แต่ฉันกำลังพูดถึงการสร้างตารางเริ่มต้น ลูกค้าจะบอกเราว่าพวกเขากำลังจะเริ่มส่งตารางใหม่ให้เราและส่งข้อมูลตัวอย่าง (หรือชุดข้อมูลการผลิตแรก) ซึ่งเราดูและสร้างตารางในตอนท้ายเพื่อเก็บข้อมูล เราต้องการสร้างตารางในตอนท้ายเพื่อจัดการการนำเข้าในอนาคตรวมถึงสิ่งที่อยู่ในตัวอย่าง แต่มีบางแถวที่ถูกผูกไว้เพื่อให้ยาวขึ้นดังนั้นเราจึงอัดเป็นแถว คำถามคือเท่าไหร่และมีแนวทางทางเทคนิคหรือไม่
aristotle2600
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.