วิธีที่ดีที่สุดในการจัดเก็บหน่วยในฐานข้อมูล


21

ฉันได้รับมรดกฐานข้อมูลขนาดใหญ่ (SQLServer) ที่มีหลายร้อยคอลัมน์ที่แสดงจำนวนเงินของสิ่งใดสิ่งหนึ่ง หน่วยสำหรับค่าเหล่านี้ (เช่น "แกลลอน", "นิ้ว" และอื่น ๆ ) จะถูกเก็บไว้ในฟิลด์ MS_Description ของ Extended Properties ฉันสงสัยว่ามีวิธีที่ดีกว่าในการจัดเก็บข้อมูลนี้ ฉันคิดว่ามันเป็นเรื่องปกติสำหรับวัตถุประสงค์ในการจัดทำเอกสาร แต่มันยากที่จะทำการคำนวณการแปลงหน่วยที่แข็งแกร่งโดยใช้ข้อมูลนี้ ณ จุดนี้ฉันยังไม่พร้อมที่จะทำการเปลี่ยนแปลง แต่ถ้าฉันได้รับโอกาสทำเช่นนั้นแนวทางปฏิบัติที่ดีที่สุดที่แนะนำในเรื่องนี้คืออะไร? ตัวเลือกซึ่งอยู่ด้านบนของหัวของฉันอาจรวมถึง:

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

UPDATE:หลังจากอ่านคำตอบของ @Todd Everett แล้วมีวิธีแก้ไขที่เป็นไปได้เกิดขึ้นกับฉันดังนั้นฉันจะดำเนินการต่อและตอบคำถามของฉันเอง (ดูด้านล่าง)


แนวปฏิบัติที่ดีที่สุดคือการมีระบบการวัดเดียวที่ใช้อย่างกว้างขวางและสม่ำเสมอตลอดการใช้งาน SI จะเป็นระบบของทางเลือก ค่าในระบบอื่นจะถูกแปลงระหว่างการโหลดหรือในเลเยอร์การนำเสนอซึ่งผู้ใช้แต่ละคนสามารถเลือกชุดที่ต้องการได้
Michael Green

คำตอบ:


12

เมื่อคุณพูดถึงหลายร้อยคอลัมน์ฉันจะพิจารณาการออกแบบ EAV ในขณะที่ Joe Celko เตือนเรื่องนี้ฉันคิดว่ามันอาจจะใช้ได้ในกรณีที่คุณใช้งาน ดูเหมือนว่า "จำนวน" ทั้งหมดของคุณเป็นตัวเลขดังนั้นคุณจะหลีกเลี่ยงปัญหาการคัดเลือกนักแสดงที่โจอธิบายและจำเป็นต้องทำให้ทุก ๆ "ค่า" เป็นสตริง มันจะทำงานได้ดียิ่งขึ้นถ้าจำนวนทั้งหมดเป็นจำนวนเต็ม แต่สามารถทำงานได้เช่นกันหากบางส่วนเป็นทศนิยม ให้หน่วยวัดคุณสามารถไปอีกขั้นหนึ่งและใช้รูปแบบสไตล์ "ข้อมูลสากล" ตามบทความนี้โดย David Hay และยังระบุไว้ในหนังสือของเขาData Model Patterns: Conventions of Thought. รุ่นนี้มีข้อได้เปรียบเพิ่มเติมในการกำหนดว่า "จำนวน" ใดที่ใช้กับ "สิ่ง" หากคุณต้องการ อีกหนึ่งขั้นตอนที่แสดงในหนังสือหน้า 162 เป็นตารางหน่วยการวัดหน่วยวัดที่คุณสามารถใช้เพื่อแปลงหน่วยหน่วยวัดต่างๆ นี่คือตัวอย่าง:

UOM Conversion              

UOM From    UOM To        Cal Step  Operator Factor Constant
Kilograms   Pounds        1         *        2.2
Celsius     Fahrenheit    1         *        1.8
Celsius     Fahrenheit    2         +               32

นี่บอกว่าการแปลงจาก Kg เป็น Lb ขั้นตอนแรกคือการคูณ Kg ด้วย 2.2 นอกจากนี้ยังมีค่าคงที่หากการแปลงต้องมีค่าคงที่และความสามารถในการสร้างหลายขั้นตอน ดังนั้นเมื่อแปลงคำว่าเซลเซียสเป็นฟาเรนไฮต์คุณคูณเซลเซียสด้วย 1.8 แล้วเพิ่ม 32 คีย์คือจาก UOM, เป็น UOM และขั้นตอนการคำนวณ

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


ขอบคุณสำหรับอาหารที่น่าสนใจมากสำหรับความคิด - ฉันเรียนรู้มาก อย่างไรก็ตามฉันไม่คิดว่า EAV เป็นรูปแบบที่เหมาะสมในกรณีของฉัน (ถ้าฉันเข้าใจคำแนะนำของคุณอย่างถูกต้อง) เพราะแม้ว่าเราจะมีคอลัมน์ 100s แต่พวกเขาก็ไม่กระจัดกระจาย อย่างไรก็ตาม DID นี้จุดประกายความคิดที่เกี่ยวข้อง (ดู UPDATE ในโพสต์ต้นฉบับของฉัน)
kmote

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

8

ทำงานทั้งหมด

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

นอกจากนี้โปรดทราบว่าการแปลงไม่ปลอดภัยมากและอาจเกิดความผิดพลาดในการปัดเศษการโอเวอร์โฟลว์ ฯลฯ

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

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

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


1
ศักยภาพ "การตีความที่ผิดพลาด" ที่คุณพูดถึงเป็นหนึ่งในข้อกังวลที่ฉันมีเกี่ยวกับสถาปัตยกรรมปัจจุบันของฐานข้อมูลนี้ - และสิ่งที่ฉันพยายามหาวิธีลด
kmote

1
จุดที่ดีเกี่ยวกับข้อเสียเปรียบที่อาจเกิดขึ้นของการแก้ปัญหาชื่อคอลัมน์
kmote

1
@kmote ไม่ใช่ปัญหาง่ายๆ - เรามีรายงานที่การทำธุรกรรมแต่ละรายการอาจมีหน่วยการวัดดั้งเดิมแตกต่างกันไป แต่ก็มีทั้งหมด - ซึ่งเป็นผลรวมหลังจากการแปลงเป็นหน่วยที่ผู้ใช้เลือก
เคด Roux

7

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

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

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

NB วิธีแก้ไขที่เกี่ยวข้องกับปัญหาอื่นคือเมื่อจัดเก็บการประทับเวลาในฐานข้อมูลเพื่อเก็บไว้ในหน่วย 'ฐาน' - UTCเสมอ

คำถาม & คำตอบอื่น ๆ ที่เกี่ยวข้องในหัวข้อ ...

  • /programming/12977021/best-practice-for-storing-weights-in-a-sql-database

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


5

เนื่องจากหน่วยใดสามารถแปลงเป็นหน่วยอื่นที่มีชนิดเดียวกันได้ด้วยสูตร:

y = ((x + xOffset) * multiplicand / denominator) + yOffset

ฉันจะสร้างตารางที่มีประเภทหน่วยบวก 4 ค่าเหล่านี้

From Unit     To Unit      Unit Type    From Offset    Multiplicand    Denominator    To Offset
'milligrams'  'grams'      'mass'       0              1               1000           0
'grams'      'kilograms'   'mass'       0              1               1000           0
'grams'      'ounces'      'mass'       0              100000          2835           0
'ounces'     'pound'       'mass'       0              1               16             0

หลังจากเพิ่มการวัดทั้งหมดที่คุณมีแนวโน้มที่จะแปลงเป็นและจากอยู่ด้านใดด้านหนึ่งของรายการให้เรียกใช้ Query ที่คุณแทรกการดำเนินการผกผันโดยเพียงแค่คัดลอกออฟเซ็ต

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


3

หลังจากอ่านคำตอบของ @Todd Everett มีวิธีแก้ปัญหาเกิดขึ้นกับฉันดังนั้นฉันจะไปต่อและตอบคำถามของฉันเอง สิ่งที่ฉันคิดว่าฉันจะทำคือการสร้างแยกต่างหากColumnUnitsตารางกับสี่คอลัมน์: Schema, Table, Column, UnitsID(ที่ UnitsID เป็น FK จะแยกUnitsOfMeasureตาราง) จึงทำแผนที่คอลัมน์ใด ๆ มอบให้กับหน่วยที่เกี่ยวข้องของวัด เห็นได้ชัดว่าข้อเสียที่ใหญ่ที่สุดของความคิดนี้คือนักพัฒนาจะต้องจำไว้ว่าต้องแก้ไขตารางนี้เมื่อใดก็ตามที่พวกเขาเปลี่ยนชื่อคอลัมน์หรือตาราง [ อาจใช้ทริกเกอร์ DDL ? ] มิฉะนั้นระบบจะหยุดทำงาน. แต่สมมติว่าการเปลี่ยนชื่อดังกล่าวนั้นหายากและ dev-shop เล็ก (ในกรณีของฉันคนเดียว) สถาปัตยกรรมนี้ควรใช้งานได้ ข้อได้เปรียบคือไม่ต้องทำการเปลี่ยนแปลงที่รุกรานกับฐานข้อมูลปัจจุบันและฉันต้องเก็บค่าหนึ่งครั้งสำหรับทุกคอลัมน์แทนที่จะเป็นหนึ่งครั้งต่อแถวเนื่องจากตัวเลือกที่สองของฉันในโพสต์ดั้งเดิมของฉันจะต้องมี


ปริศนาที่น่าสนใจ ... และแนวคิดที่น่าสนใจที่คุณมี ความคิดของคุณจะทำให้การสืบค้นง่ายขึ้น แต่ดูเหมือนจะไม่ประสบความสำเร็จมากนัก คุณเพิ่งย้ายข้อมูลอ้างอิงไปยังที่อื่น สิ่งที่รบกวนฉันมากที่สุดเกี่ยวกับการออกแบบนี้
Sir Swears-a-lot

... คือถ้ารายการนั้นมีแอตทริบิวต์มากกว่าคุณยังคงต้องเพิ่มคอลัมน์อีก ด้วยเหตุนี้ฉันชอบ @todd everett คำแนะนำเกี่ยวกับการออกแบบ eav
Sir Swears-a-lot
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.