รหัสข้อผิดพลาด 1117 มีจำนวนคอลัมน์มากเกินไป MySQL จำกัด คอลัมน์บนโต๊ะ


37

ฉันมีตารางที่มี 1,699 คอลัมน์และเมื่อฉันพยายามแทรกคอลัมน์อื่น ๆ ที่ฉันได้รับ

รหัสข้อผิดพลาด: 1117 มีคอลัมน์มากเกินไป

ในตารางนี้ฉันมีเพียง 1,000 แถว สำหรับฉันสิ่งที่สำคัญที่สุดคือจำนวนคอลัมน์ มีข้อ จำกัด ใด ๆ บนโต๊ะหรือไม่? ฉันต้องการสร้างคอลัมน์ 2,000 คอลัมน์ เป็นไปได้ไหม


21
เจ้านายที่ดีสิ่งที่ห่า สิ่งนี้มีกลิ่นเหมือนการออกแบบฐานข้อมูลที่แย่มาก หรือบางทีคุณกำลังใช้เครื่องมือที่ผิดสำหรับงาน บางทีคุณควรดูฐานข้อมูลการทำให้เป็นมาตรฐาน
Zoredache

12
หมุนจอภาพของคุณ 90 องศา ยิ่งไปกว่านั้น MySQL (หรือ RDBMS อื่น ๆ เกือบทั้งหมด) ไม่ได้ออกแบบมาสำหรับคอลัมน์จำนวนมาก

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

6
จำนวนโต๊ะสูงสุด ... โอ้โห! คุณอาจต้องการเพียงสองสามโต๊ะ อย่าพิจารณาสร้าง 2000 ตารางแทนคอลัมน์ 2000!

2
ได้โปรดได้โปรดอ่านเกี่ยวกับการปรับสภาพฐานข้อมูล !

คำตอบ:


35

เหตุใดคุณต้องสร้างตารางที่มีคอลัมน์จำนวน 20 คอลัมน์นับประสา 2,000 รายการ

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

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

ในวันก่อนหน้าของฉันในฐานะนักพัฒนาฉันทำงานที่ บริษัท ย้อนกลับไปในปี 1995 โดยที่ DB2 เป็น RDBMS หลัก บริษัท มีตารางเดียวที่มี 270 คอลัมน์ดัชนีหลายสิบและมีปัญหาด้านประสิทธิภาพในการเรียกข้อมูล พวกเขาติดต่อ IBM และให้ที่ปรึกษาตรวจสอบสถาปัตยกรรมของระบบรวมถึงตารางเสาหินอันนี้ บริษัท ได้รับแจ้งว่า "ถ้าคุณไม่ทำมาตรฐานนี้ในอีก 2 ปีข้างหน้า DB2 จะล้มเหลวในการสืบค้นที่กำลังดำเนินการขั้นที่ 2 (แบบสอบถามใด ๆ ที่ต้องการเรียงลำดับในคอลัมน์ที่ไม่ได้จัดทำดัชนี)" เรื่องนี้ได้รับการบอกกล่าวกับ บริษัท หลายล้านล้านดอลลาร์เพื่อทำให้ตารางคอลัมน์ปกติเป็น 270 ยิ่งมีตารางคอลัมน์ 2000 เท่าไหร่

ในแง่ของ mysql คุณจะต้องชดเชยการออกแบบที่ไม่ดีดังกล่าวโดยการตั้งค่าตัวเลือกที่เทียบเท่ากับการประมวลผล DB2 Stage2 ในกรณีนี้ตัวเลือกเหล่านั้นจะเป็น

ทวีการตั้งค่าเหล่านี้เพื่อชดเชยการมีอยู่หลายสิบคอลัมน์นับร้อยนับพันทำงานได้ดีถ้าคุณมี RAM TB

ปัญหานี้ทวีคูณในเชิงเรขาคณิตหากคุณใช้ InnoDB เนื่องจากคุณจะต้องจัดการกับMVCC (การควบคุมการเกิดพร้อมกันหลายอย่าง)ที่พยายามปกป้องคอลัมน์จำนวนมากด้วยการเลือก SELECT, UPDATE และ DELETE ผ่านการแยกธุรกรรม

สรุปผลการศึกษา

ไม่มีการทดแทนหรือช่วยเหลือวงดนตรีที่สามารถชดเชยการออกแบบที่ไม่ดีได้ ได้โปรดเถิดเพื่ออนาคตของคุณที่มีสติ


1
ฉันสามารถจินตนาการได้ว่า บริษัท จะทำอย่างไรเมื่อบอกเรื่องนี้ พวกเขาเพิ่ม svn hooks หรือสร้าง "แนวทางปฏิบัติที่ดีที่สุดของ DB" เพื่อขอให้นักพัฒนาไม่จัดเรียงคอลัมน์ที่ไม่ได้จัดทำดัชนีไว้ใน SQL แต่พวกเขาทำการเรียงลำดับภายในแอปพลิเคชันโดยใช้อัลกอริทึมการเรียงลำดับข้อมูลขนาดใหญ่ของตนเอง
Gqqnbig

25

ฉันมีปัญหาในการจินตนาการอะไรก็ตามที่แบบจำลองข้อมูลสามารถมีคอลัมน์ 2,000 คอลัมน์ในตารางปกติได้อย่างถูกต้อง

ฉันเดาว่าคุณอาจจะทำอะไรบางอย่าง "กรอกในช่องว่าง" schema denormalised ที่คุณจริง ๆ แล้วเก็บข้อมูลประเภทต่าง ๆ ทั้งหมดในตารางเดียวและแทนที่จะแบ่งข้อมูลออกเป็นตารางแยกต่างหากและสร้างความสัมพันธ์ คุณมีสาขาต่าง ๆ ที่บันทึกข้อมูลประเภท "" ที่จัดเก็บไว้ในแถวที่กำหนดและ 90% ของเขตข้อมูลของคุณเป็น NULL ถึงแม้ว่าจะต้องการได้ 2,000 คอลัมน์ ...

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

CREATE TABLE master (
    id INT PRIMARY KEY AUTO_INCREMENT,
    <fields that really do relate to the
    master records on a 1-to-1 basis>
);

CREATE TABLE sensor_readings (
    id INT PRIMARY KEY AUTO_INCREMENT,
    master_id INT NOT NULL,   -- The id of the record in the
                              -- master table this field belongs to
    sensor_id INT NOT NULL,
    value VARCHAR(255)
);

CREATE TABLE sensors (
    id INT PRIMARY KEY AUTO_INCREMENT,
    <fields relating to sensors>
);

จากนั้นจะได้รับทั้งหมดของรายการเซ็นเซอร์ที่เกี่ยวข้องกับการรับ "ต้นแบบ" SELECT sensor_id,value FROM sensor_readings WHERE master_id=<some master ID>บันทึกคุณสามารถเพียงแค่ หากคุณต้องการรับข้อมูลสำหรับบันทึกในmasterตารางพร้อมกับข้อมูลเซ็นเซอร์ทั้งหมดสำหรับบันทึกนั้นคุณสามารถใช้การเข้าร่วม:

SELECT master.*,sensor_readings.sensor_id,sensor_readings.value
FROM master INNER JOIN sensor_readings on master.id=sensor_readings.master_id
WHERE master.id=<some ID>

ถ้าหากคุณต้องการรายละเอียดของเซ็นเซอร์แต่ละตัว


18

มันเป็นระบบการวัดที่มีเซ็นเซอร์ 2,000 ตัว

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

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

ตามที่คนอื่นแนะนำคุณสามารถหลีกเลี่ยงข้อ จำกัด นี้ได้โดยให้ตารางลูกมีid, sensor_id, sensor_valueหรือมากกว่านั้นง่ายๆคุณสามารถสร้างตารางที่สองเพื่อให้มีเพียงคอลัมน์ที่ไม่พอดีกับคอลัมน์แรก (และใช้ PK เดียวกัน)


1
นี่เป็นเรื่องจริง เมื่อจัดการข้อมูลและ SQL ที่เกี่ยวข้องด้วยความระมัดระวังคำตอบของคุณโดดเด่นยิ่งขึ้น !!!
RolandoMySQLDBA

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

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

2
@ แจ็คดักลาส: ถึงแม้ว่าสมมติฐานทั้งหมดของคุณเป็นจริง (ซึ่งฉันสงสัยอย่างมาก) การจัดเก็บค่าเซ็นเซอร์แต่ละค่าในคอลัมน์ของตัวเองจะทำให้เกิดปัญหาในระยะยาว สิ่งที่เกี่ยวกับการค้นหาเช่น "สิ่งที่เป็นค่าเฉลี่ยสำหรับเซ็นเซอร์ 10 ถึง 50 และ 25 ถึง 100 ระหว่างเมื่อวานและวันนี้"? หรือ "เซ็นเซอร์ตัวใดมีค่าการอ่านสูงสุดในวันจันทร์หน้า" ลองเขียนแบบสอบถามสำหรับสิ่งนี้ด้วย 2000 คอลัมน์ การใช้ตารางที่ทำให้เป็นมาตรฐานจะแก้ปัญหาได้มากกว่าในระยะยาวกว่าวิธีแก้ปัญหาคอลัมน์ 2000
a_horse_with_no_name

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

15

MySQL 5.0 จำนวนคอลัมน์ จำกัด (เน้นเพิ่ม):

มีขีด จำกัด ที่ยากคือ 4096 คอลัมน์ต่อตารางแต่ค่าสูงสุดที่มีประสิทธิภาพอาจน้อยกว่าสำหรับตารางที่กำหนด ขีด จำกัด ที่แน่นอนขึ้นอยู่กับปัจจัยหลายประการ

  • ทุกตาราง (ไม่ว่าจะเป็นเอ็นจิ้นการจัดเก็บข้อมูลใด) จะมีขนาดแถวสูงสุด 65,535 ไบต์ เอ็นจิ้นการจัดเก็บอาจวางข้อ จำกัด เพิ่มเติมในขีด จำกัด นี้ลดขนาดแถวที่มีประสิทธิภาพสูงสุด

    ขนาดแถวสูงสุด จำกัด จำนวน (และขนาดที่เป็นไปได้) ของคอลัมน์เนื่องจากความยาวทั้งหมดของคอลัมน์ทั้งหมดต้องไม่เกินขนาดนี้

...

เอนจินการเก็บข้อมูลส่วนบุคคลอาจกำหนดข้อ จำกัด เพิ่มเติมที่ จำกัด จำนวนคอลัมน์ตาราง ตัวอย่าง:

  • InnoDB อนุญาตให้มีได้มากถึง 1,000 คอลัมน์

7

ก่อนอื่นให้ลุกเป็นไฟมากขึ้นและเป็นทางออกที่แท้จริง ...

ฉันเห็นด้วยกับเปลวไฟที่คุณโยนไปแล้ว

ฉันไม่เห็นด้วยกับการนอร์มัลไลซ์คีย์ - ค่า แบบสอบถามจบลงด้วยความน่ากลัว; ประสิทธิภาพยิ่งแย่ลง

วิธีการหนึ่งที่ 'ง่าย' เพื่อหลีกเลี่ยงปัญหาที่เกิดขึ้นทันที (จำกัด จำนวนคอลัมน์) คือ 'แบ่งพาร์ติชันในแนวตั้ง' ของข้อมูล มีพูด 5 ตารางที่มี 400 คอลัมน์ในแต่ละ พวกเขาทั้งหมดจะมีคีย์หลักเดียวกันยกเว้นอาจเป็น AUTO_INCREMENT

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

คุณกำลังจัดทำดัชนีค่าใด ๆ หรือไม่? คุณต้องการค้นหาจากพวกเขาหรือไม่? คุณอาจค้นหาใน datetime หรือไม่

หากคุณต้องการทำดัชนีคอลัมน์จำนวนมาก - ถ่อ

หากคุณต้องการทำดัชนีให้ใส่ไว้ในตารางหลัก

นี่คือทางออกที่แท้จริง (ถ้ามี) ...

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

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


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

@ BoB3K - ย่อหน้าใหญ่ของฉันบอกว่าจะทำอย่างไรให้ข้อมูลที่มีอยู่เกี่ยวกับปัญหาตามที่ระบุไว้ JSONหลีกเลี่ยง "คอลัมน์มากเกินไป"; การจัดทำดัชนีคอลัมน์ที่เลือกจะช่วยในเรื่องประสิทธิภาพ
Rick James

3

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

มีเวลาและสถานที่สำหรับการออกแบบนี้ อย่างแน่นอน การทำให้เป็นมาตรฐานไม่ใช่วิธีแก้ปัญหาสำหรับทุกปัญหา


ขอบคุณสำหรับความคิดเห็น หากต้องการวิเคราะห์ด้วยภาพแม้แต่ภาพสีขนาดเล็ก ๆ ที่มีขนาด 16x16 พิกเซลต้องใช้จำนวนเต็ม 16 * 16 * 3 ระหว่าง 0 ถึง 255 (ตัวเลข 3 ตัวเพื่ออธิบายสีในรูปแบบหนึ่งใน 16x16 พิกเซลโดยใช้สี RGB) นั่นคือ 768 คอลัมน์สำหรับข้อมูลซึ่งจะต้องเพิ่มคีย์
VictorZurkowski
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.