Tech

Postgres: 'ข้อความ' ไร้ขอบเขตและกลับมาอีกครั้ง

การเปิดเผยที่สำคัญอย่างหนึ่งสำหรับผู้ใช้ใหม่เกือบทุกคนใน Postgres คือไม่มีข้อได้เปรียบทางเทคนิคในการระบุคอลัมน์เป็น varchar(n) เมื่อเทียบกับการใช้ข้อความที่ไม่มีขอบเขต . ไม่เพียงแต่ประเภท text ที่ให้ไว้เพื่อความสะดวก (ไม่ได้อยู่ในมาตรฐาน SQL) แต่ใช้เปรียบเทียบกับประเภทอักขระที่มีข้อจำกัด เช่น char และ varchar ไม่มีการปรับประสิทธิภาพ จากเอกสาร Postgres เกี่ยวกับประเภทอักขระ (และโปรดทราบว่า การแปรผันของอักขระ เป็นสิ่งเดียวกับ varchar ):

ไม่มีความแตกต่างด้านประสิทธิภาพในสามประเภทนี้ นอกเหนือจากพื้นที่จัดเก็บที่เพิ่มขึ้นเมื่อใช้ประเภทที่มีช่องว่างภายใน และรอบ CPU พิเศษอีกสองสามรอบเพื่อตรวจสอบความยาวเมื่อจัดเก็บในคอลัมน์ที่จำกัดความยาว แม้ว่า character(n) จะมีข้อได้เปรียบด้านประสิทธิภาพในระบบฐานข้อมูลอื่น แต่ PostgreSQL ไม่มีข้อได้เปรียบดังกล่าว อันที่จริงแล้ว character(n) มักจะช้าที่สุดในสามตัวเนื่องจากค่าใช้จ่ายในการจัดเก็บเพิ่มเติม ในสถานการณ์ส่วนใหญ่ text หรือ ควรใช้อักขระที่แตกต่างกัน แทน สำหรับพวกเราหลายๆ คน การดำเนินการนี้ถือเป็นการสร้างภาระอย่างมาก เนื่องจากเราคุ้นเคยกับการจำกัดความยาวแบบไมโครในระบบอื่นๆ หลังจากทำงานในระบบ MySQL และ Oracle ขนาดใหญ่ ฉันมีนิสัยที่ไม่เพียงแต่คิดว่าจะเพิ่มคอลัมน์ใด แต่ยังต้องใช้เวลานานเท่าใดด้วย – นี่ควรเป็น varchar(50) หรือ varchar(100)? 500? (หรือไม่มีเลย?) ด้วย Postgres คุณเพียงแค่หยุดกังวลและตบ ข้อความ กับทุกสิ่ง มันเป็นอิสระ ฉันได้เปลี่ยนจุดยืนของฉันไปบ้างแล้ว และเพื่ออธิบายว่าทำไม ฉันจะต้องพาคุณกลับไปที่ Stripe ประมาณปี 2018 S3ripe อยู่มาวันหนึ่งเราตื่นขึ้นมาอย่างหยาบคายว่าเราไม่ได้ตรวจสอบการจำกัดความยาวในช่องข้อความใน API ของ Stripe ไม่ใช่แค่เพียงไม่กี่คนเท่านั้นที่ไม่ได้รับการตรวจสอบ แต่ในทางปฏิบัติแล้วแทบไม่มีเลย แม้ว่ากรอบงาน API จะอนุญาตให้มีความยาวสูงสุด แต่ก็ไม่มีใครคิดที่จะกำหนดค่าเริ่มต้นที่สมเหตุสมผลให้กับมัน และแน่นอนว่าพารามิเตอร์ส่วนใหญ่ (ซึ่งมีอยู่หลายพันตัว ณ จุดนี้) ไม่ได้ตั้งค่าไว้ ตราบใดที่ผู้ส่งไม่ได้ทำลายข้อจำกัดใดๆ เกี่ยวกับขนาดเพย์โหลดของคำขอ พวกเขาก็สามารถส่งสิ่งที่พวกเขาต้องการในสาขาใดก็ได้ที่พวกเขาต้องการ API ยินดีที่จะส่งต่อและยืนยันกับ Mongo ตลอดไป ฉันจำไม่ได้ว่าเราสังเกตเห็นได้อย่างไร แต่พอจะพูดว่าเราทำก็ต่อเมื่อมันกลายเป็นปัญหาเท่านั้น ผู้ใช้บางคนส่งเพย์โหลดจำนวนมากมาให้เรา และทำให้ผู้ปฏิบัติงาน HTTP ขัดข้อง เชื่อมโยงทรัพยากรฐานข้อมูล หรือสิ่งที่แย่พอๆ กัน เท่าที่มีปัญหาในการคำนวณ การตรวจสอบความยาวของสตริงไม่ใช่สิ่งที่ถือว่ายากเป็นพิเศษ ดังนั้นเราจึงมุ่งมั่นที่จะดำเนินการแก้ไข แต่ไม่เร็วนัก นี่ไม่ใช่วันแรกของบริษัทอีกต่อไป เรามีผู้ใช้จำนวนนับไม่ถ้วนแล้ว กำลังดำเนินการกับคำขอนับล้านรายการ และนั่นหมายถึงการขยายที่เราคาดหวังได้ว่ามีผู้ใช้จำนวนมากที่รวมสตริงขนาดใหญ่ เราไม่เคยมีกฎเกณฑ์เกี่ยวกับความยาวมาก่อน และหากไม่มีข้อจำกัดที่เข้มงวด เมื่อมีผู้ใช้เพียงพอและมีเวลาเพียงพอ ในที่สุดบางคน (หรือหลายคนที่เหมือนเดิม) ก็เริ่มส่งสตริงที่ยาว การแนะนำค่าสูงสุดในทันใดจะทำให้การผสานรวมเหล่านั้นหยุดชะงักและสร้างผู้ใช้ที่ไม่มีความสุขจำนวนมาก Stripe ให้ความสำคัญกับความเข้ากันได้แบบย้อนหลังอย่างมาก และจะไม่ทำอย่างนั้นโดยตั้งใจ ด้วยความกลัวในสิ่งที่ฉันกำลังจะพบ ฉันจึงดำเนินการทดลองในการผลิตที่จะสร้างสถิติเกี่ยวกับความยาวของฟิลด์ข้อความ รวมถึงขอบเขตบนและการแจกแจง และรอหนึ่งวันเพื่อรวบรวมข้อมูล มันแย่กว่าที่เราคิดเสียอีก – เรามีผู้ใช้อย่างน้อยหลายร้อยคน (และบางทีอาจเป็นพันๆ คน หน่วยความจำของฉันก็แย่) ที่ส่งข้อความจำนวนมาก ที่แย่ไปกว่านั้น ผู้ใช้เหล่านี้เป็นผู้ใช้ที่ถูกต้องตามกฎหมายทั้งหมด ซึ่งเป็นผู้ใช้ที่ถูกต้องตามกฎหมายซึ่งด้วยเหตุผลใดก็ตามที่ตัดสินใจสร้างรูปแบบการผสานรวมที่แปลกใหม่ในช่วงหลายปีที่ผ่านมา พวกเขากำลังทำบางอย่างเช่นส่งแคตตาล็อกผลิตภัณฑ์ทั้งหมดมาให้เรา หรือ JSON blob ขนาดใหญ่เพื่อจัดเก็บ และเป็นส่วนหนึ่งของโฟลว์การรวมตามปกติ บางครั้งเรามีส่วนร่วมในแคมเปญเผยแพร่ประชาสัมพันธ์เพื่อให้ผู้ใช้เปลี่ยนแปลงบางสิ่ง แต่เป็นงานจำนวนมหาศาล และเราต้องเสนอไทม์ไลน์การเลิกใช้งานที่กว้างขวางเมื่อเราดำเนินการ ด้วยธรรมชาติของปัญหานี้และจำนวนผู้ใช้ที่เกี่ยวข้อง จึงไม่คุ้มค่ากับความพยายาม ความฝันของฉันที่จะจำกัดเขตข้อมูลส่วนใหญ่ เช่น ลูกค้าหรือชื่อแผนกับสิ่งที่สมเหตุสมผล เช่น “เพียง” 200 อักขระนั้นไม่ใช่ผู้เริ่มต้นทั้งหมด แต่เราดำเนินการตามตัวเลขและได้ข้อสรุปที่เหมาะสมที่สุดซึ่งจะทำให้จำนวนผู้ใช้สูงสุดไม่ได้รับผลกระทบในขณะที่ยังคงจำกัดขอบเขตฟิลด์ข้อความให้เป็นสิ่งที่ไม่บ้าทั้งหมด (จำนวนที่เลือกคือ 5,000 ตามที่ดูได้ใน ข้อมูลจำเพาะ OpenAPI สาธารณะ ) และแม้แต่ขีดจำกัดใหม่แบบเสรีก็ยาวเกินไปสำหรับผู้ใช้สองสามรายที่ส่งเพย์โหลดขนาดยักษ์มาให้เรา ดังนั้นเราจึงกำหนดให้พวกเขาได้รับการยกเว้น ให้ฉันทบทวนกฎของไฮรัมโดยสังเขป:

ด้วยจำนวนผู้ใช้ API ที่เพียงพอ ไม่สำคัญว่าคุณสัญญาอะไรในสัญญา: พฤติกรรมที่สังเกตได้ทั้งหมดของระบบของคุณจะขึ้นอยู่กับใครบางคน

ไม่ค่อยมีการพูดคำที่แท้จริง

varchars ถือว่า ~harm ~helpful

เริ่มตำแหน่งใหม่ ของฉันในเดือนเมษายน สิ่งหนึ่งที่ฉันตรวจสอบก่อนคือเรากำลังตรวจสอบความยาวของสตริงที่เราเป็นอยู่หรือไม่ ผ่านไปยังฐานข้อมูล ไม่. ปรากฎว่านี่เป็นความผิดพลาดที่ง่ายมาก

  • นี่เป็นข้อเสียของภูมิปัญญา Postgres ทั่วไปของ “เพียงใช้ text” ปกติก็ใช้ได้ แต่มีรอยแยกที่ขอบที่มองเห็นยากขึ้น ฉันกลับไปเป็นนิสัยในการทำฟิลด์ข้อความส่วนใหญ่ varchar อีกครั้ง แต่ฉันก็ยังไม่ชอบการจัดการความยาวอักขระแบบไมโคร หรือหลังจากนั้นไม่นานทุกคอลัมน์ varchar จะมีความยาวที่แตกต่างกันซึ่งดูเหมือนว่าจะสุ่มเลือก ดังนั้นฉันจึงผลักดันให้เราใช้ลำดับความสำคัญร่วมกัน “ชั้น”. ตัวอย่างเช่น:
    • varchar(200) สำหรับสตริงที่มีความยาวน้อยกว่า เช่น ชื่อ ที่อยู่ ที่อยู่อีเมล ฯลฯ
    • varchar(2000) สำหรับบล็อกข้อความที่ยาวกว่าเช่นคำอธิบาย
    • varchar(20000) สำหรับ บล็อกข้อความยาวมาก แนวคิดคือการเลือก
        liberal ตัวเลขที่ยาวพอที่จะ เก็บข้อมูลกึ่งถูกต้องใดๆ หวังว่าคุณจะไม่ถึงขีดสูงสุดเหล่านี้จริง ๆ – พวกมันอยู่ที่นั่นเพื่อเป็นแบ็คสต็อปเพื่อป้องกันข้อมูลที่ผิดพลาดอย่างร้ายแรง ฉันจะไม่แม้แต่จะสนับสนุนให้ใช้ตัวเลขที่ฉันได้กล่าวไว้ข้างต้น ถ้าคุณลองทำเช่นนี้ ให้ลองเลือกตัวเลขของคุณเองตามสิ่งที่เหมาะกับคุณ การมีข้อ จำกัด ในฐานข้อมูลไม่ได้หมายความว่าคุณไม่ควร ด้วย ตรวจสอบขีด จำกัด ในรหัส โปรแกรมส่วนใหญ่ไม่ได้เขียนขึ้นเพื่อจัดการกับความล้มเหลวของข้อจำกัดของฐานข้อมูลได้อย่างสวยงาม ดังนั้นเพื่อประโยชน์ของผู้ใช้ของคุณ ให้ใส่กรอบการจัดการข้อผิดพลาดมาตรฐานและข้อความแสดงข้อผิดพลาดเชิงพรรณนาในกรณีที่สิ่งนี้เคยเกิดขึ้น อีกครั้ง ฐานข้อมูลคือแบ็คสต็อป – มีชั้นการป้องกันสุดท้ายเมื่อส่วนอื่นๆ ล้มเหลว

      ประเภทบังคับและการดำเนินงาน

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

    • การผ่อนคลาย นี่ไม่ใช่ ปัญหามากเกินไปอีกต่อไป จาก เอกสาร Postgres บน ALTER TABLE :

      การเพิ่มคอลัมน์ที่มีความผันผวน DEFAULT หรือการเปลี่ยนประเภทของคอลัมน์ที่มีอยู่จะทำให้ทั้งตารางและดัชนีของตารางต้องถูกเขียนใหม่ เป็นข้อยกเว้น เมื่อเปลี่ยนประเภทของคอลัมน์ที่มีอยู่ หากอนุประโยค USING ไม่เปลี่ยนเนื้อหาของคอลัมน์และประเภทเก่าเป็นไบนารีที่บังคับได้สำหรับประเภทใหม่หรือโดเมนที่ไม่มีข้อจำกัดเหนือ ชนิดใหม่ ไม่จำเป็นต้องเขียนตารางใหม่ แต่ดัชนีใด ๆ ในคอลัมน์ที่ได้รับผลกระทบจะต้องถูกสร้างขึ้นใหม่ สังเกตถ้อยคำของ “unconstrained domain” A varchar(200) เป็นโดเมนที่ไม่มีข้อจำกัดเหนือ varchar(100) เพราะมันยาวกว่าอย่างเคร่งครัด Postgres สามารถผ่อนคลายข้อจำกัดโดยไม่ต้องล็อกตารางเพื่อทำการสแกน การย้อนกลับไปทางอื่นไม่ง่าย แต่คุณไม่ควรทำอย่างนั้น โดเมน SQL อีกแนวคิดหนึ่งที่ฉันได้ทดลองด้วยคือการเข้ารหัสชุดระดับข้อความมาตรฐานเป็นโดเมน ซึ่งกำหนดประเภทข้อมูลใหม่พร้อมข้อจำกัดเพิ่มเติม:

      สร้างโดเมน text_standard AS varchar(200) COLLATE "C";  สร้างโดเมน text_long AS varchar(2000) COLLATE "C";  สร้างโดเมน text_huge AS varchar(20000) COLLATE "C";  

      โดเมนสามารถใช้ตามข้อตกลงในคำจำกัดความของตาราง:

      # สร้างตาราง mytext (มาตรฐาน text_standard, ยาว text_long, text_huge ใหญ่);  # d+ ตาราง mytext "public.mytext" คอลัมน์ |  พิมพ์ |  การเปรียบเทียบ |  Nullable |  ค่าเริ่มต้น |  การจัดเก็บ |  สถิติเป้าหมาย |  คำอธิบาย -------------------------------+-----------+---------- +---------+----------+--------------+------------- มาตรฐาน |  text_standard |  |  |  |  ขยาย |  |  ยาว |  text_long |  |  |  |  ขยาย |  |  ใหญ่ |  text_huge |  |  |  |  ขยาย |  |  

      สิ่งเดียวที่ฉันไม่ชอบเกี่ยวกับการตั้งค่านี้คือมันค่อนข้างทำให้สับสนว่าคอลัมน์เหล่านั้นคืออะไร เพราะไม่ใช่ประเภททั่วไปอีกต่อไป เป็นเรื่องง่ายมากที่จะให้ Postgres มอบคำจำกัดความโดเมนให้กับคุณด้วย dD: # dD รายการโดเมน Schema | ชื่อ | พิมพ์ | การเปรียบเทียบ | Nullable | ค่าเริ่มต้น | ตรวจสอบ ------------------------------------+----------------------- ---+-----------+----------+---------+------ สาธารณะ | text_huge | ตัวละครที่แตกต่างกัน(20000) | ค | | | สาธารณะ | text_long | ตัวละครที่แตกต่างกัน(2000) | ค | | | สาธารณะ | text_standard | ตัวละครที่แตกต่างกัน(200) | ค | | | แต่ … แทบไม่มีใครรู้วิธีที่จะทำสิ่งนั้นจากหัวของพวกเขา

      คุณธรรมในเชิงลึก

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

      ที่ตีพิมพ์ 10 กันยายน 2564ที่ตั้ง ซานฟรานซิสโกบทความ Postgres: ‘ข้อความ’ ไร้ขอบเขตและกลับมาอีกครั้ง พบฉันบน Twitter ได้ที่ @brandur

      .. ฉันทำผิดพลาดหรือไม่? โปรดพิจารณา ส่งคำขอดึง .

      • Trang chủ
      • Business
      • Foods
      • Life Style
      • Tech
      • กลยุทธ์การตลาดดิจิทัล (Digital marketing)

  • Back to top button