MySQL: หลายตารางหรือหนึ่งตารางที่มีหลายคอลัมน์?


127

นี่จึงเป็นคำถามเกี่ยวกับการออกแบบมากกว่า

ฉันมีคีย์หลักหนึ่งคีย์ (เช่น ID ผู้ใช้) และฉันมีข้อมูลมากมายที่เกี่ยวข้องกับผู้ใช้รายนั้น

ฉันควรแบ่งตารางหลายตารางเป็นหมวดหมู่ตามข้อมูลหรือควรมีเพียงตารางเดียวที่มีหลายคอลัมน์

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

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

ฉันค่อนข้างใหม่กับการออกแบบฐานข้อมูลดังนั้นแนวทางใดดีกว่ากันและข้อดีข้อเสียคืออะไร

วิธีการทำแบบธรรมดาคืออะไร?


เพื่อความชัดเจนโปรดแก้ไขฉันหากฉันผิด แต่ฉันคิดว่า "หลายตาราง" สามารถเข้าใจได้ว่าเป็น link / Associative table: en.wikipedia.org/wiki/Associative_entity
cellepo

1
ฐานข้อมูลนี้จำเป็นสำหรับวัตถุประสงค์ในการวิเคราะห์หรือสำหรับการประมวลผลการดำเนินงาน / ธุรกรรมหรือไม่?
Alexander

คำตอบ:


113

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

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

คุณอาจพบว่าบทความ Wikipedia เกี่ยวกับการทำให้เป็นมาตรฐานฐานข้อมูลนั้นน่าสนใจเนื่องจากมีการกล่าวถึงสาเหตุของสิ่งนี้ในเชิงลึก:

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

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


ขอบคุณสำหรับคำตอบหลังจากอ่านจบฉันคิดว่าสิ่งที่ฉันพูดถึงคือสถานการณ์ข้อมูลแบบตัวต่อตัวเมื่อผู้ใช้มีคอลัมน์แบบตัวต่อตัวจำนวนมาก
Xavier_Ex

@Xavier_Ex - ใช่ถ้ามีเพียงคอลัมน์เดียวต่อผู้ใช้ตารางผู้ใช้ขนาดใหญ่เพียงตารางเดียวจะทำงานได้ง่ายขึ้น (และง่ายกว่ามากสำหรับเครื่องมือ DB ในการปรับให้เหมาะสม)
Brendan Long

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

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

1
เมื่อเร็ว ๆ นี้ฉันประสบกับปัญหาเดียวกันนี้เนื่องจากตาราง MySQL InnoDB มีขีดจำกัดความยาวที่ค่อนข้างเล็ก (~ 8000 ไบต์) ในตารางปัญหาของฉัน (ข้อมูลจากแบบประกันที่มีความยาวมากมากกว่า 100 คอลัมน์) เรามีคอลัมน์ varchar หลายคอลัมน์ UTF8 ทั้งหมด ดังนั้นเราจึงเติมขีด จำกัด ~ 8000 ไบต์ได้อย่างง่ายดายและได้รับ "ข้อผิดพลาด 139 จากเครื่องมือจัดเก็บข้อมูล" ตลอดเวลา เราเลยต้องแบ่งโต๊ะ (เราทดสอบด้วยรูปแบบ Barracuda ที่ใหม่กว่าและทำงานได้โดยไม่ต้องแยก แต่เซิร์ฟเวอร์ของลูกค้าของเรายังคงใช้ MySQL 5.0)
MV.

12

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

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


1
อ่าเสียงที่แตกต่าง! ซึ่งเป็นสิ่งที่ดีเสมอ ขอบคุณสำหรับข้อมูล! ฉันจะตรวจสอบให้แน่ใจว่าฉันรู้เรื่องนั้นเมื่อฉันทำโต๊ะของฉัน ...
Xavier_Ex

4

ฉันมีตัวอย่างที่ดี ฐานข้อมูลที่เป็นมาตรฐานมากเกินไปพร้อมชุดความสัมพันธ์ต่อไปนี้:

people -> rel_p2staff -> staff

และ

people -> rel_p2prosp -> prospects

ในกรณีที่บุคคลมีรายชื่อและรายละเอียดบุคคลเจ้าหน้าที่มีเพียงรายละเอียดบันทึกพนักงานผู้มีแนวโน้มจะเป็นลูกค้ามีเพียงรายละเอียดผู้มีโอกาสเป็นลูกค้าและตาราง rel เป็นตารางความสัมพันธ์ที่มีคีย์ต่างประเทศจากบุคคลที่เชื่อมโยงกับพนักงานและผู้มีโอกาสเป็นลูกค้า

การออกแบบประเภทนี้ใช้กับฐานข้อมูลทั้งหมด

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

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

การแก้ปัญหาจะต้องมีความสัมพันธ์โดยตรงสำหรับpeople -> staffและpeople -> prospect


สนใจที่จะทราบว่าการสร้างใหม่เป็นอย่างไร? คุณลงเอยด้วยการออกแบบสิ่งที่คล้ายกับการสืบทอดตารางเดียวที่คุณมีtypeความเป็นstaffหรือเป็นprospectหรือไม่?
Coderama

1
ไปกับผู้ที่เกี่ยวข้องโดยตรง -> พนักงานและผู้คน -> ผู้มีโอกาสเป็นลูกค้าทำงานได้อย่างมีเสน่ห์ใช้งานง่ายรวดเร็วในการสอบถาม
Vlad

4

เมื่อเจอสิ่งนี้และในฐานะคนที่เคยใช้ MySQL เป็นจำนวนมากและเปลี่ยนมาใช้ Postgres เมื่อเร็ว ๆ นี้ข้อดีอย่างหนึ่งคือคุณสามารถเพิ่มวัตถุ JSON ลงในฟิลด์ใน Postgres ได้

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


สิ่งที่เกี่ยวกับประสิทธิภาพของเขาเมื่อใช้วัตถุ json ในขณะที่ค้นหา?
dagalti

1
@dagalti ประสิทธิภาพดีสำหรับแอปพลิเคชันที่ฉันใช้ ฉันยังไม่ได้ทำการเปรียบเทียบของตัวเอง แต่อาจมีประโยชน์กับคุณ: arangodb.com/2018/02/…
moinhaque

3

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

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

การออกแบบจุดด้อยยากขึ้นข้อความค้นหาจะซับซ้อนขึ้นเล็กน้อย

แต่มีหลายกรณีที่โต๊ะแบนขนาดใหญ่จะเหมาะสมดังนั้นคุณต้องดูสถานการณ์ของคุณเพื่อตัดสินใจ


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

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

1

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


1
"ใช้ตารางขนาดใหญ่หากคุณมีบันทึกจำนวนมาก .. " แต่ Facebook, Google ไม่ได้เก็บข้อมูลผู้ใช้ไว้ในตารางเดียวโดยแยกออกเป็นหลายตาราง
Yami Odymel

0

วิธีการทั่วไปในการทำเช่นนี้คือการใช้ตารางที่แตกต่างกันเช่นเดียวกับสคีมาดาวหรือสคีมาเกล็ดหิมะ Howeevr ฉันจะใช้กลยุทธ์นี้เป็นสองเท่า ฉันเชื่อในทฤษฎีที่ว่าข้อมูลควรมีอยู่ในที่เดียวเท่านั้นสำหรับสคีมาที่ฉันกล่าวถึงจะทำงานได้ดี อย่างไรก็ตามฉันยังเชื่อด้วยว่าสำหรับเอ็นจิ้นการรายงานและชุด BI การใช้แนวทางคอลัมน์จะเป็นประโยชน์อย่างมากเนื่องจากเป็นการสนับสนุนความต้องการในการรายงานมากกว่า แนวทางคอลัมน์เช่นเดียวกับ infobright.org มีประสิทธิภาพและการบีบอัดที่เพิ่มขึ้นอย่างมากซึ่งทำให้การใช้ทั้งสองวิธีมีประโยชน์อย่างเหลือเชื่อ บริษัท จำนวนมากเริ่มตระหนักว่าการมีสถาปัตยกรรมฐานข้อมูลเพียงตัวเดียวในองค์กรนั้นไม่สามารถรองรับความต้องการได้ทั้งหมด บริษัท จำนวนมากกำลังใช้ทั้งแนวคิดของการมีสถาปัตยกรรมฐานข้อมูลมากกว่าหนึ่งแห่ง


ขอบคุณสำหรับข้อมูล แต่ขออภัยฉันไม่ค่อยเข้าใจคำตอบของคุณ ... ฉันจะค้นหาสองสคีมาที่คุณกล่าวถึงก่อน ...
Xavier_Ex

-4

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

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