Type-2 Slowly Changing Dimension (SCD) คือ?

ในโลก Data Warehouse หลายๆ คนอาจจะเคยได้ยินคำว่า Slowly Changing Dimension (SCD) กันมาบ้างเนอะ แล้วมันคืออะไรล่ะ? มันคือการจัดเก็บข้อมูลที่มีการเปลี่ยนแปลงไปเรื่อยๆ และที่เค้าบอกว่า slow เนี่ย เค้าหมายถึงข้อมูลที่เป็น dimension เนอะ เช่น ชื่อคน เพศ หรือ ชื่อ product อะไรแบบนี้ที่ไม่ได้มีการเปลี่ยนแปลงบ่อย ซึ่งโดยปกติแล้วข้อมูล dimension ก็จะเป็นประมาณนั้นอยู่แล้ว (แต่ถ้ามีการเปลี่ยนแปลงเร็วจริงๆ ลองดู Rapidly Changing Dimension เพิ่มนะ)

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

id status updated_at
1 pending 2019-01-01

แล้วพอสถานะเปลี่ยน ข้อมูลก็จะกลายเป็นแบบนี้

id status updated_at
1 shipped 2019-01-02

ทีนี้มันก็มีปัญหาอยู่ว่าถ้าเราต้องการที่จะวิเคราะห์ช่วงระยะเวลาระหว่างจากสถานะ pending ไปเป็น shipped เนี่ย เราไม่สามารถที่จะรู้ได้เลย หรือถ้าเราต้องการที่จะดูว่าก่อนสถานะเป็น shipped เนี่ย มันเคยเป็นสถานะอะไรมาก่อน?

ตรงนี้แหละครับที่เราสามารถเอา SCD มาใช้ได้ โดยที่นิยมใช้ๆ กันก็คือ Type-2 อธิบายง่ายๆ มันก็คือการเพิ่มข้อมูลมาอีก 1 แถวโดยที่ยังเก็บข้อมูลเก่าไว้

จากตัวอย่างข้อมูลด้านบน เราก็จะสามารถเก็บข้อมูลได้เป็นแบบนี้

id status updated_at from to
1 pending 2019-01-01 2019-01-01 2019-01-02
1 shipped 2019-01-02 2019-01-02 null

ซึ่งเราก็อาจจะมีฟิดล์ from กับ to เอาไว้บอกสักหน่อยว่าค่าๆ นี้เริ่มตั้งแต่เมื่อไหร่ และถึงเมื่อไหร่ถึงจะเปลี่ยนไปเป็นค่าใหม่ ก็เป็นอันเรียบร้อย… เรื่อง Type-2 SCD ก็ประมาณนี้แหละ :smile:

จริงๆ เรื่องนี้เราสามารถพูดคุยตกลงกับทางสายพัฒนา software ได้เลยนะ หาทางออกร่วมกันว่าแบบไหนจะดีที่สุดสำหรับพวกเรา ตั้งแต่ในระดับ app เราสามารถเก็บ history ไว้ได้หรือเปล่า? ถ้าไม่ได้ แล้วเราสามารถทำเป็น change event มาได้ไหม? แล้วถ้าไม่ได้ โอเคเราสามารถเอามาทำ Type-2 SCD ก็พอจะตอบโจทย์การวิเคราะห์ข้อมูลไหม? บลาๆ

ฮ่าๆ ถ้าถามผมเนี่ย ผมไม่มีคำตอบที่ดีที่สุดให้นะครับ อันนี้อยู่ที่บริบทการคุยกันภายในทีมของแต่ละองค์กรเลย ทุกทางเลือกมี technical debt หมด อยู่ที่เราจะจัดการมันอย่างไร :wink:

Ref: Snapshots | dbt Docs

7 Likes

อันนี้ดีมาก ผมเคยทำระบบที่เป็น pub/sub หลายปีมาแล้ว เคยเจอปัญหาว่า worker มัน failed แล้วมันไม่หยิบของไป processing เลย ซึ่งตอนแรกไม่ได้ design แบบนี้ ข้อมูลช่วงที่ worker failed คือทำ manual ใหม่หมดเลย

แต่พอใช้ท่าเก็บข้อมูลแบบข้างบน ตอนนั้นคือพอเกิดปัญหาอีกรอบ เราสามารถ re-execute worker ให้มันกลับมาทำต่อจากจุดที่เรารู้ว่ามัน failed ได้เลย เพราะ state ของข้อมูลมัน trace ไปได้หมดเลย

ข้อเสียเดียวที่ผมนึกออกตอนนั้นคือตัว change log อันนี้มันบวมมาก ตอนทำโปรเจ็คนั้นแล้วต้องคอยเคลียร์ทุกๆ เดือน แต่ถ้าเป็นสมัยนี้ของพวกนี้น่าจะเก็บลง Data lake ได้สบายๆ แล้วครับ

2 Likes

เพิ่งรู้ว่ามันมีชื่อเรียกวิธีการทำอะไรแบบนี้ด้วย ขอบคุณมากเลยค่า

1 Like

อ่านเพิ่มเติมเกี่ยวกับ Slowly Changing Dimensions ได้ที่บทความนี้เลย อธิบายไว้ดีงาม

เผื่อใครอยากจะทำ SCD Type 2 ใน Spark

https://towardsdatascience.com/slowly-changing-dimension-type-2-in-spark-7d5865ac915b

จากประสบการณ์ พบว่า อย่าอัดค่าทับใน prod db โดยไม่ทำ log/trail ทิ้งไว้
เพราะถ้าอัดทับ มันจะย้อนอดีตไม่ได้ :rofl:
แล้วมันจะมีแน่ๆ ที่คนอยากรู้ ว่า ใช้เวลาเท่าไหร่ในแต่ละช่วง แล้วบาง use case จะงอกมาตอนหลังๆ แต่ operation db เขาใช้งานกันจริงไปเรียบร้อยแล้ว…

เพราะฉะนั้น เก็บของดิบไว้ให้ครบๆ แล้วจะสบายสำหรับงานในอนาคต :laughing:

1 Like

เห็นด้วยอย่างรุนแรงครับ ฮ่า ๆ