จัดเก็บชุดคู่คีย์ - ค่าอย่างมีประสิทธิภาพด้วยคีย์ที่แตกต่างกัน


9

ฉันรับแอปพลิเคชันที่เชื่อมโยงกิจกรรมหลายประเภทกับไซต์ มีประเภทกิจกรรมที่แตกต่างกันประมาณ 100 ประเภทและแต่ละประเภทมีชุดของฟิลด์ 3-10 ที่แตกต่างกัน อย่างไรก็ตามกิจกรรมทั้งหมดมีฟิลด์วันที่อย่างน้อยหนึ่งวัน (อาจเป็นการรวมกันของวันที่วันที่เริ่มต้นวันที่สิ้นสุดวันที่เริ่มต้นที่กำหนด ฯลฯ ) และเขตข้อมูลบุคคลที่รับผิดชอบหนึ่งรายการ ฟิลด์อื่นทั้งหมดนั้นแตกต่างกันอย่างมากและฟิลด์วันที่เริ่มต้นไม่จำเป็นต้องเรียกว่า "วันที่เริ่มต้น"

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

ป้อนคำอธิบายรูปภาพที่นี่

แต่ละกิจกรรมมี ActivityField หลายรายการ แต่ละไซต์มีหลายกิจกรรมและตาราง SiteActivityData จะเก็บ KVP สำหรับแต่ละ SiteActivity

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

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

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

ป้อนคำอธิบายรูปภาพที่นี่

ตารางกิจกรรมจะมี XSD สำหรับแต่ละกิจกรรมโดยไม่จำเป็นต้องใช้ตารางกิจกรรมของฟิลด์ SiteActivity จะมี XML คีย์ - ค่าดังนั้นแต่ละกิจกรรมสำหรับไซต์จะอยู่ในแถวเดียว

กิจกรรมจะมีลักษณะเช่นนี้ (แต่ฉันยังไม่ได้ทำให้มันสมบูรณ์):

<SomeActivityType>
  <SomeDateField type="StartDate">2000-01-01</SomeDateField>
  <AnotherDateField type="EndDate">2011-01-01</AnotherDateField>
  <EmployeeId type="ResponsiblePerson">1234</EmployeeId>
  <SomeTextField>blah blah</SomeTextField>
  ...

ข้อดี:

  • XSD จะตรวจสอบ XML จับข้อผิดพลาดเช่นการใส่สตริงในฟิลด์ตัวเลขที่ระดับฐานข้อมูลบางอย่างที่เป็นไปไม่ได้ด้วยสคีมาเก่าที่เก็บทุกอย่างใน varchar
  • ชุดระเบียนของ KVP ที่ใช้ในการสร้างเว็บฟอร์มสามารถทำซ้ำได้อย่างง่ายดายโดยใช้ select ... from ActivityXML.nodes('/SomeActivityType/*') as T(r)
  • แบบสอบถามย่อย xpath ของ XML สามารถใช้ในการสร้างชุดผลลัพธ์ที่มีคอลัมน์สำหรับวันที่เริ่มต้น, วันที่สิ้นสุด ฯลฯ โดยไม่ต้องใช้เดือยเช่น select ActivityXML.value('.[@type=StartDate]', 'datetime') as StartDate, ActivityXML.value('.[@type=EndDate]', 'datetime') as EndDate from SiteActivity where...

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

คำถามเพิ่มเติม: ถ้าฉันกำหนดแท็กว่ามีชนิดข้อมูลวันที่ใน XSD โดยใช้xs:dateSQL Server จะทำดัชนีเป็นค่าวันที่หรือไม่ ฉันกังวลว่าถ้าฉันค้นหาตามวันที่จะต้องใช้สตริงวันที่เป็นค่าวันที่และสร้างโอกาสในการใช้ดัชนี


ข้อมูลสำหรับรายงานต้องเป็นข้อมูลล่าสุดอย่างไร รายงานจะกระทบการผลิตหรือไม่
James Anderson

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

มีการทับซ้อนกันในฟิลด์เท่าไหร่ สิบสาขาครอบคลุม 100 ประเภทย่อยทั้งหมดหรือมีประมาณ 500 เขตข้อมูลที่แตกต่างกันทั้งหมดหรือไม่
จอนแห่งการค้าขายทั้งหมด

มี 72 ฟิลด์และ 75 ประเภทกิจกรรม 30 เขตข้อมูลถูกใช้โดยกิจกรรมเดียวเท่านั้นส่วนที่เหลือส่วนใหญ่จะใช้ 5-10 กิจกรรม มีเขตข้อมูลจำนวนหนึ่งที่ใช้ในกิจกรรมที่แตกต่างกัน ~ 30 กิจกรรม ส่วนใหญ่แล้วจะไม่มีอะไรธรรมดาสามัญในการทำกิจกรรม
Paul Abbott

คำตอบ:


7

ดังนั้นสิ่งที่ฉันกำลังมองหาคือวิธีเก็บกิจกรรมจำนวนมากที่แทบไม่มีฟิลด์เหมือนกันในแบบที่ทำให้การรายงานง่ายขึ้น

ตัวแทนไม่เพียงพอที่จะแสดงความคิดเห็นก่อนดังนั้นที่นี่เราไปกัน!

หากวัตถุประสงค์หลักคือการรายงานและคุณมี DW (แม้ว่ามันจะไม่ใช่แบบแผนดาว) ฉันขอแนะนำให้คุณลองใส่มันลงในแบบแผนดาว ประโยชน์คือการสืบค้นที่รวดเร็วและง่าย ข้อเสียคือ ETL แต่คุณกำลังพิจารณาที่จะย้ายข้อมูลไปยังการออกแบบใหม่และ ETL ไปยังสคีมานั้นน่าจะง่ายต่อการสร้างและบำรุงรักษามากกว่าโซลูชัน XML wrapper (และ SSIS รวมอยู่ในการอนุญาต SQL Server ของคุณ) ยิ่งไปกว่านั้นมันเริ่มต้นกระบวนการของการออกแบบการรายงาน / การวิเคราะห์

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

DimActivity- ฉันคาดเดาว่ามีรูปแบบเป็นสิ่งที่ช่วยให้คุณสามารถแบ่งสิ่งเหล่านี้ออกเป็นคอลัมน์ที่มีการแชร์อย่างน้อยได้ ถ้าเป็นเช่นนั้นคุณอาจมีสาม? ห้า? มิติสำหรับคลาสของกิจกรรม ที่เลวร้ายที่สุดคุณมีคอลัมน์ที่สอดคล้องกันสองสามชื่อเช่นชื่อกิจกรรมคุณสามารถกรองและคุณจะออกจากส่วนหัวทั่วไปเช่น "Attribute1" เป็นต้นสำหรับรายละเอียดแบบสุ่มที่เหลืออยู่

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

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

CREATE TABLE [DIM].[Site]
(
 SiteSK INT NOT NULL IDENTITY PRIMARY KEY
,SiteNK INT NOT NULL --source system key
,SiteName VARCHAR(500) NOT NULL
)

DimDate- แอตทริบิวต์วันที่ สร้าง "สมาร์ทคีย์" แทนรหัสประจำตัว ซึ่งหมายความว่าคุณสามารถพิมพ์จำนวนเต็มที่มีความหมายซึ่งเกี่ยวข้องกับวันที่ของแบบสอบถามเช่น WHERE DateSK = 20150708 มีสคริปต์ฟรีจำนวนมากที่โหลด DimDate และส่วนใหญ่จะรวมสมาร์ทคีย์นี้ ( หนึ่งตัวเลือก )

DimEmployee - XML ​​ของคุณรวมถึงสิ่งนี้หากเป็นการเปลี่ยนแปลงทั่วไปมากขึ้นสำหรับ DimPerson และเติมแอตทริบิวต์ของบุคคลที่เกี่ยวข้องตามที่มีอยู่และเกี่ยวข้องกับการรายงาน

และความจริงของคุณคือ:

FactActivitySite
DimSiteSK - FK to DimSite
DimActivitySK - FK to DimActivity
DimEmployee - FK to DimEmployee
DimDateSK - FK to DimDate

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

ขยายวันที่ที่เป็นจริงของคุณไปยังสิ่งที่คุณต้องการ: StartDateSK, EndDateSK, ScheduledStartDateSK.

มิติข้อมูลทั้งหมดควรมีแถวที่ไม่รู้จักโดยทั่วไปจะมี hardcoded -1 SK เมื่อคุณโหลดข้อเท็จจริงและกิจกรรมไม่มีวันที่ใด ๆ ที่รวมไว้มันก็ควรโหลด -1

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

ป้อนคำอธิบายรูปภาพที่นี่

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


(คำถามจาก wesdev): @Dave คุณใช้เครื่องมือ ERD อะไร?
ypercubeᵀᴹ

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