วิธีที่ดีที่สุดในการอ้างอิงข้อมูลฐานข้อมูลคงที่ในรหัส?


24

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

ไม่ใช่เรื่องแปลกที่จะหาข้อมูลคงที่นี้ในตารางฐานข้อมูล (บ่อยครั้งเพราะคุณต้องการอ้างถึงในคีย์ต่างประเทศของตารางอื่น ๆ ) ตารางตัวอย่างง่าย ๆ จะมีรหัสที่ใช้เป็นคีย์หลักและคำอธิบาย ตัวอย่างเช่นตาราง SalesArea ของคุณจะมี (อย่างน้อย) คอลัมน์ SalesAreaId และคอลัมน์ SalesAreaDescription

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

วิธีที่ดีที่สุดในการอ้างถึงข้อมูลคงที่ในรหัสคืออะไร? ทำไม?

  1. เขียนโค้ดรายละเอียดในรหัสของคุณ ใช้สิ่งนี้เพื่อค้นหา SalesAreaId จากฐานข้อมูลเมื่อคุณต้องการ
  2. รหัสฮาร์ดโค้ดในรหัสของคุณ ใช้สิ่งนี้เพื่อค้นหา SalesAreaDescription เมื่อคุณต้องการ
  3. เพิ่มคอลัมน์ลงในตารางสำหรับแต่ละวัตถุประสงค์เช่นคอลัมน์ "IsDefaultOnProductLaunchScreen" และอื่น ๆ (อาจมีจำนวนมาก)
  4. อื่น ๆ อีก.

มีข้อควรพิจารณาพิเศษอื่นใดอีกไหมที่ฉันควรทำเมื่อจัดการกับข้อมูลฐานข้อมูลแบบคงที่? ตัวอย่างเช่นการตั้งชื่อตารางเหล่านี้เป็นพิเศษ?


1
ซ้ำซ้อนที่เป็นไปได้: programmers.stackexchange.com/questions/304169/… ฉันเชื่อว่าคำตอบในเรื่องนั้น (เชื่อมโยง) เข้าสู่หัวใจของปัญหา IMO ที่ดีขึ้นเล็กน้อย
JoeCool

คำตอบ:


14

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

ฉันยังขอแนะนำให้หลีกเลี่ยงการเข้ารหัสอะไรที่ยาก เพิ่มตัวบ่งชี้เริ่มต้น (เริ่มแรกในตาราง DB และในโครงสร้างแคช) สำหรับหน้าจอที่ต้องการค่าเริ่มต้น สำหรับการค้นหาบน non-defauilts ให้ลองจัดเก็บคีย์ที่จะค้นหาในไฟล์กำหนดค่าหรือคุณสมบัติหากคุณทำได้


การแคชเป็นสิ่งที่ดีแน่นอน แต่คุณจะปรับปรุงค่าเหล่านี้ได้อย่างไร สันนิษฐานว่าแอปพลิเคชันเริ่มต้นใหม่หรือกลยุทธ์การตรวจสอบแคชบางประเภท
Steve

1
@Steve ใช่แน่นอน ขึ้นอยู่กับแอพพลิเคชั่น รีสตาร์ทเป็นสิ่งที่ดีสำหรับสิ่งที่เริ่มต้นบ่อยครั้ง สำหรับแอปพลิเคชั่นที่ใช้งานนานอาจโหลดแคชซ้ำวันละครั้งในช่วงเวลาที่ช้า คำถามของฉันจะเป็นอย่างไรเกี่ยวกับสถานการณ์ที่แอปพลิเคชันทำงานหลายช่วงเวลาสั้น ๆ เช่นบางทีสคริปต์ PHP หรือสิ่งที่คล้ายกัน
tylermac

ฐานข้อมูลจะเรียกใช้แคชของตัวเองสำหรับข้อมูลที่เข้าถึงบ่อยดังนั้นคุณจะนำสิ่งที่มีการใช้งานไปใช้อีกครั้ง (และอาจจะไม่ดีเช่นกัน!)
James Anderson

@JamesAnderson: การแคชในแอปพลิเคชันหมายความว่าจะมีการเรียกไปยังฐานข้อมูลเพียงครั้งเดียวเท่านั้น ใช่ฐานข้อมูลจะมีแคชของตัวเอง แต่สิ่งเหล่านั้นสามารถถูกทำให้เป็นโมฆะ / รีเฟรชโดยกิจกรรมนอกการควบคุมแอปพลิเคชันของคุณและคุณยังต้องเชื่อมต่อกับฐานข้อมูลและสร้างแบบสอบถามเพื่อรับข้อมูลนั้น (และหวังว่าจะเป็น แคชของ db) ไม่ใช่เรื่องยากที่จะใช้แคชในแอปพลิเคชั่น
FrustratedWithFormsDesigner

7

อีกทางเลือกหนึ่งในการ DB หรือการเข้ารหัสยากคือการใช้ไฟล์ config อ่านในเวลาเริ่มต้น จากนั้นคุณสามารถเก็บข้อมูลนี้ในโครงสร้างแบบอ่านอย่างเดียวภายในรหัสของคุณ

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


1
ความคิดที่ดีสำหรับข้อมูลคงที่บางประเภท แต่ไม่ดีนักหากคุณต้องการบังคับใช้ความสัมพันธ์ FK ตามที่อธิบายไว้ในคำถาม
Kramii Reinstate Monica

คำถามไม่ได้บอกว่านี่เป็นข้อกำหนดเพียงสถานการณ์เท่านั้น หากไม่ต้องการใช้วิธีปรับแต่งไฟล์ให้ใช้งานได้ดี
Steve

คุณพูดถูกฉันยังไม่ชัดเจนพอ แต่ฉันยินดี ... เพราะฉันเรียนรู้บางสิ่งจากคำตอบของคุณ ฉันไม่เคยเจอวิธีนี้มาก่อน
Kramii Reinstate Monica

3

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

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

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


"บ่อยครั้งที่สิ่งที่เราคิดว่าคงเป็นสิ่งที่ไม่ควรทำ" - จริงดังนั้น
Kramii Reinstate Monica

3

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

ในแอพเรียบง่ายปัจจุบันฉันมีรายการแก้ไขสถานะสำหรับเนื้อหา: ร่าง, เผยแพร่, เก็บถาวร

ไอเท็มเนื้อหาจำเป็นต้องได้รับการปฏิบัติแตกต่างกันไปขึ้นอยู่กับสถานะที่อยู่หากฉันจะเก็บข้อมูลสถานะนี้ไว้ในฐานข้อมูลด้วยค่า 1, 2, 3 ตามลำดับฉันจะตรวจสอบได้อย่างไรว่ามีบางสิ่งในร่าง สถานะ?

if (content.State == 1)
หรือ
if (content.State == "Draft")?

ฉันแค่เข้ารหัสค่ายาก ๆ !
สิ่งเดียวกันถ้าคุณใช้แคช / ตารางแฮช: คุณยังต้องใช้ค่าที่เขียนในรหัสของคุณ เป็นกุญแจสำคัญในการค้นหาข้อมูลของคุณ

อะไรคือข้อเสียของ aproach ที่เข้ารหัสยาก?


ข้อเสียคืออย่างที่พีดีเอกล่าวว่า "บ่อยครั้งที่สิ่งที่เราคิดว่าคงเป็นสิ่งที่ไม่ควรทำ"
tylermac

2
แต่ถ้าคุณอ้างอิงค่าข้อมูลคงที่ในโค้ดคุณจะไม่สามารถเปลี่ยนแปลงค่าในฐานข้อมูลโดยไม่ทำให้แอปเสียหาย แน่นอนมันขึ้นอยู่กับข้อมูลที่ใช้สำหรับ: ตามที่ฉันได้กล่าวไว้ข้างต้นถ้ามันเป็นเพียงการเติมองค์ประกอบ UI เพื่อให้ผู้ใช้สามารถเลือกค่าและมีที่ piped โดยตรงกลับไปยังฐานข้อมูลเป็นส่วนหนึ่งของบันทึกในตารางอื่น จากนั้นข้อมูลสแตติกใน DB สามารถเปลี่ยนแปลงได้อย่างอิสระจากรหัสแอป ฉันค่อนข้างแน่ใจว่าเป็นสถานการณ์ที่ @pdr กำลังพูดถึง: แอปจัดการชุดข้อมูลคงที่เป็นรายการเดียว
เดฟ

2

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

ฉันรู้ว่าที่ NHibernate ออมมีฟังก์ชันการทำงานนี้ผ่านแคชระดับ 2 คุณสามารถบอกให้แคชข้อมูลจากตารางที่แน่นอนและบอกว่าเป็นแบบอ่านอย่างเดียว มันจะถูกโหลดในครั้งแรกที่จำเป็นและจะไม่ตีฐานข้อมูลอีกครั้งหลังจากนั้นแม้ว่าคุณจะเข้าถึงข้อมูลจากหลาย ๆ เซสชันก็ตาม


+1 สำหรับกาลครั้งเดียว แต่สิ่งที่เกี่ยวกับการรักษาแถวที่แตกต่างกันแตกต่างกันอย่างไร
Kramii Reinstate Monica

1
@Kramii - คุณสามารถใช้สิ่งที่ต้องการเรียนการแจงนับ หากข้อมูลเมตาเกี่ยวข้องกับโปรแกรมของคุณเท่านั้นฉันจะใส่ตรรกะทางธุรกิจ ( IsDefaultOn...) ในคุณสมบัติบนเอนทิตี มันจะกลับมาจริงสำหรับนิติบุคคลหนึ่ง ที่จะช่วยให้คุณค้นหาเอนทิตีที่ได้รับจากการรวบรวมทั้งหมด หรือคุณสามารถใช้คลาสคอนโทรลเลอร์ที่จะช่วยให้คุณเรียกใช้เมธอดได้
Scott Whitlock

2

นี่คือการเพิ่มประสิทธิภาพก่อนวัยอันควรที่เลวร้ายยิ่ง

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

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

มีสองวิธีที่จะไปที่นี่: -

เก็บไว้ในฐานข้อมูลและเข้าถึงข้อมูลด้วย "ปกติ" sql

เก็บไว้ในไฟล์คอนฟิกูเรชัน XML แฟนซี (อาจเข้าถึงผ่าน REST หรือ SOAP) ซึ่งสามารถแก้ไขได้ง่ายเมื่อใดก็ตามที่มี "การเปลี่ยนแปลงเชิงกลยุทธ์ของนโยบาย"


1

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


1

ฉันรู้ว่าคำตอบนี้ได้รับการยอมรับ แต่ฉันต้องการแบ่งปันว่าเราทำสิ่งนี้ได้อย่างไรที่ร้านพัฒนาเว็บไซต์ครั้งสุดท้ายที่เราพยายามลด I / O ฐานข้อมูลให้มากที่สุด

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

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

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


0

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

LooseDBCodeBinding (database table)
   ID : Int32 (key)
   Name : String
   HardCodedTypeID : Int32

// in code:
public enum LooseDBCodeBinding
{
   TYPE_1 = 1,
   TYPE_2 = 2,
   TYPE_3 = 3 // etc...
}

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

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