ไม่มีวิธีที่ดีที่สุดในการจัดเก็บข้อมูลอนุกรมเวลาและมันขึ้นอยู่กับปัจจัยหลายอย่าง อย่างไรก็ตามฉันจะมุ่งเน้นไปที่สองปัจจัยหลักโดยมี:
(1) โครงการนี้ร้ายแรงเพียงใดที่สมควรได้รับความพยายามของคุณในการเพิ่มประสิทธิภาพสคีมา
(2) สิ่งที่เป็นรูปแบบการเข้าถึงการค้นหาของคุณจริงๆจะเป็นอย่างไร
ด้วยคำถามเหล่านั้นในใจเราจะพูดถึงตัวเลือกสคีมาสองสามตัว
โต๊ะแบน
ตัวเลือกในการใช้งานตารางแบนนั้นมีประโยชน์มากสำหรับคำถาม(1)ซึ่งหากนี่ไม่ใช่โครงการที่จริงจังหรือโครงการขนาดใหญ่คุณจะพบว่ามันง่ายกว่าที่จะไม่คิดมากเกี่ยวกับสคีมาและ เพียงใช้โต๊ะแบนเนื่องจาก:
CREATE flat_table(
trip_id integer,
tstamp timestamptz,
speed float,
distance float,
temperature float,
,...);
มีหลายกรณีที่ฉันจะแนะนำหลักสูตรนี้เฉพาะในกรณีที่เป็นโครงการเล็ก ๆ ที่ไม่รับประกันเวลาของคุณมาก
ขนาดและข้อเท็จจริง
ดังนั้นหากคุณได้ลบล้างสิ่งกีดขวางของคำถาม(1)และคุณต้องการสคีมาประสิทธิภาพมากขึ้นนี่เป็นหนึ่งในตัวเลือกแรกที่ต้องพิจารณา มันมีบางบรรทัดฐานพื้นฐาน normailization แต่แยกปริมาณ 'มิติ' จากปริมาณ 'ความจริง' วัด
โดยพื้นฐานแล้วคุณจะต้องการตารางเพื่อบันทึกข้อมูลเกี่ยวกับการเดินทาง
CREATE trips(
trip_id integer,
other_info text);
และตารางสำหรับบันทึกการประทับเวลา
CREATE tstamps(
tstamp_id integer,
tstamp timestamptz);
และในที่สุดข้อเท็จจริงทั้งหมดที่คุณวัดได้มีการอ้างอิงคีย์ต่างประเทศไปยังตารางมิติ (นั่นคือmeas_facts(trip_id)
การอ้างอิงtrips(trip_id)
และmeas_facts(tstamp_id)
การอ้างอิงtstamps(tstamp_id)
)
CREATE meas_facts(
trip_id integer,
tstamp_id integer,
speed float,
distance float,
temperature float,
,...);
สิ่งนี้อาจดูเหมือนจะไม่เป็นประโยชน์ในตอนแรก แต่ถ้าคุณมีตัวอย่างของการเดินทางหลายพันครั้งพร้อมกันพวกเขาอาจจะทำการตรวจวัดครั้งเดียวต่อวินาทีในวินาที ในกรณีดังกล่าวคุณจะต้องบันทึกการประทับเวลาใหม่ทุกครั้งสำหรับการเดินทางแต่ละครั้งแทนที่จะใช้เพียงรายการเดียวในtstamps
ตาราง
ใช้กรณี: กรณีนี้จะดีถ้ามีการเดินทางพร้อมกันหลายครั้งที่คุณกำลังบันทึกข้อมูลและคุณไม่รังเกียจที่จะเข้าถึงการวัดทุกประเภทด้วยกัน
เนื่องจาก Postgres อ่านตามแถวทุกครั้งที่คุณต้องการตัวอย่างเช่นการspeed
วัดในช่วงเวลาที่กำหนดคุณจะต้องอ่านทั้งแถวจากmeas_facts
ตารางซึ่งจะทำให้แบบสอบถามช้าลงอย่างแน่นอนแม้ว่าชุดข้อมูลที่คุณกำลังทำงานอยู่นั้นเป็นอย่างไร ไม่ใหญ่เกินไปจากนั้นคุณจะไม่สังเกตเห็นความแตกต่าง
แบ่งข้อเท็จจริงที่วัดได้ของคุณ
หากต้องการขยายส่วนสุดท้ายอีกเล็กน้อยคุณสามารถแยกการวัดของคุณออกเป็นตารางแยกต่างหากตัวอย่างเช่นฉันจะแสดงตารางสำหรับความเร็วและระยะทาง:
CREATE speed_facts(
trip_id integer,
tstamp_id integer,
speed float);
และ
CREATE distance_facts(
trip_id integer,
tstamp_id integer,
distance float);
แน่นอนคุณสามารถดูว่าสิ่งนี้อาจขยายไปยังการวัดอื่น ๆ
ใช้กรณี:ดังนั้นสิ่งนี้จะไม่ทำให้คุณมีความเร็วเพิ่มขึ้นอย่างมากสำหรับการค้นหาอาจเป็นเพียงการเพิ่มความเร็วเชิงเส้นเมื่อคุณทำการสอบถามเกี่ยวกับการวัดประเภทหนึ่ง เนื่องจากเมื่อคุณต้องการค้นหาข้อมูลเกี่ยวกับความเร็วคุณจะต้องอ่านเฉพาะแถวจากspeed_facts
ตารางแทนที่จะเป็นข้อมูลพิเศษที่ไม่จำเป็นทั้งหมดที่จะปรากฏในแถวของmeas_facts
ตาราง
ดังนั้นคุณต้องอ่านข้อมูลขนาดใหญ่จำนวนมากเกี่ยวกับประเภทการวัดเดียวเท่านั้นคุณจะได้รับประโยชน์ ด้วยกรณีที่คุณนำเสนอข้อมูล 10 ชั่วโมงในช่วงเวลาหนึ่งวินาทีคุณจะอ่านได้ 36,000 แถวดังนั้นคุณจะไม่ได้รับประโยชน์อย่างมากจากการทำเช่นนี้ อย่างไรก็ตามหากคุณต้องดูข้อมูลการวัดความเร็วสำหรับ 5,000 เที่ยวที่ใช้เวลาประมาณ 10 ชั่วโมงตอนนี้คุณกำลังอ่าน 180 ล้านแถว การเพิ่มความเร็วเชิงเส้นสำหรับแบบสอบถามดังกล่าวอาจให้ประโยชน์บางอย่างตราบใดที่คุณต้องการเข้าถึงประเภทการวัดครั้งละหนึ่งหรือสองครั้งเท่านั้น
อาร์เรย์ / HStore / & TOAST
คุณอาจไม่ต้องกังวลกับส่วนนี้ แต่ฉันรู้กรณีที่มันสำคัญ หากคุณจำเป็นต้องเข้าถึงขนาดใหญ่ปริมาณของข้อมูลอนุกรมเวลาและคุณรู้ว่าคุณต้องเข้าถึงทั้งหมดของมันในบล็อกขนาดใหญ่หนึ่งคุณสามารถใช้โครงสร้างซึ่งจะทำให้การใช้งานของตาราง TOASTซึ่งเป็นหลักเก็บข้อมูลของคุณในขนาดใหญ่ที่ถูกบีบอัด กลุ่ม สิ่งนี้นำไปสู่การเข้าถึงข้อมูลได้รวดเร็วยิ่งขึ้นตราบใดที่เป้าหมายของคุณคือการเข้าถึงข้อมูลทั้งหมด
ตัวอย่างการใช้งานอาจเป็น
CREATE uber_table(
trip_id integer,
tstart timestamptz,
speed float[],
distance float[],
temperature float[],
,...);
ในตารางนี้tstart
จะเก็บการประทับเวลาสำหรับรายการแรกในอาร์เรย์และแต่ละรายการที่ตามมาจะเป็นค่าของการอ่านสำหรับวินาทีถัดไป สิ่งนี้ต้องการให้คุณจัดการการประทับเวลาที่เกี่ยวข้องสำหรับแต่ละค่าอาร์เรย์ในชิ้นส่วนของแอพพลิเคชั่นซอฟต์แวร์
ความเป็นไปได้อีกอย่างก็คือ
CREATE uber_table(
trip_id integer,
speed hstore,
distance hstore,
temperature hstore,
,...);
โดยที่คุณเพิ่มค่าการวัดของคุณเป็นคู่ (คีย์, ค่า) ของ (การประทับเวลา, การวัด)
กรณีการใช้งาน:นี่เป็นการนำไปปฏิบัติอาจดีกว่าปล่อยให้คนที่คุ้นเคยกับ PostgreSQL และถ้าคุณแน่ใจเกี่ยวกับรูปแบบการเข้าถึงของคุณซึ่งจำเป็นต้องใช้รูปแบบการเข้าถึงจำนวนมาก
สรุปผลการวิจัย?
ว้าวนี่นานกว่าที่ฉันคาดไว้ขออภัย :)
โดยพื้นฐานแล้วมีตัวเลือกมากมาย แต่คุณอาจได้รับผลตอบแทนที่ใหญ่ที่สุดสำหรับเจ้าชู้ของคุณโดยใช้ตัวเลือกที่สองหรือสาม
ป.ล. :คำถามแรกของคุณบอกเป็นนัยว่าคุณจะโหลดข้อมูลจำนวนมากหลังจากรวบรวมข้อมูลทั้งหมดแล้ว หากคุณกำลังสตรีมข้อมูลไปยังอินสแตนซ์ PostgreSQL ของคุณคุณจะต้องดำเนินการเพิ่มเติมเพื่อจัดการทั้งปริมาณข้อมูลและปริมาณงานแบบสอบถาม แต่เราจะปล่อยให้เป็นเช่นนั้นอีกครั้ง ;)