關係數據建模:多個簡單查詢與繁重查詢
我正在嘗試確定以組和子組的形式組織並需要查詢的模型數據的最佳方法。具體來說,是否扁平化/抽像到一個表中並將工作放入服務計算以過濾和分組查詢結果(但只有一個查詢)將比擁有所有需要同時執行的單獨查詢執行得更好,但當然不要不需要分組。例如,想像必須按類別將學生測試結果提供給儀表板。
方法 1. 每個測試的表
CREATE TABLE mathSkillsTest( id char, datetake date, multiplication_score integer, division_score integer, algebra_score integer student_id integer REFERENCES students (student_id) ) ...create TABLE verbalSkillsTest// all scores still just integers ...create TABLE readingTest//
優點:更少的抽象更容易推理,更簡單的查詢,例如
var mathscores = (SELECT * FROM mathSkillsTests WHERE student_id = 123)
缺點:如果計劃總是查詢所有組,這意味著我們要查詢每個表。
方法2.一張桌子
CREATE Table abstractTests ( id char, datetake date, category varchar, //"math", testname varchar, // "multiplication" score integer student_id integer REFERENCES students (student_id) )
優點:一表一查詢。
缺點:查詢中有很多處理和分組,以提供按類別/測試/日期分組的結果。也將在一張表上擁有不同的數據。
一種方法是否更具性能和可擴展性?是否有任何一種方法違反了任何最佳實踐?
從標準模式設計方法來看,為了更好的可維護性和簡單性,我認為第二種方法是使用單個更通用的表。歸根結底,您的對像是
tests
. 我相信您會在第一種方法中發現很多欄位冗餘,這是不必要的提高性能的嘗試。如果您通常對相同的欄位進行分組和/或過濾,例如
category
、testname
和datetake
,那麼這些很可能是您在表上的索引的良好候選者,這將在查詢時提供最佳性能,即使您的表變大了足以記錄數十億條記錄。
分析
可能需要 1 到 n 次評估
這表明您在學生和評估之間存在多對多關係。(
testname
)查看給定學生曾經參加過的所有測試。
這是你的主要
SELECT
陳述。建議的解決方案
方法 2b
這與方法 2相同,但非規範化
testname
並將“類別”移動到新TestNames
表的父級。這增加了確保行不能將數學評估與語言類別混合的好處。
儀表板實施
數據庫最適合返回所需的數據。
顯示層(例如網路瀏覽器)最適合使它看起來更漂亮。
這個概念在 SE 和其他地方的幾乎所有 Dynamic Pivot 問題中都有體現。
如果您要以樞軸方式在 3 個單獨的表格中顯示數據,以使顯示看起來像方法 1,那麼無論如何都會向您建議這種方法(動態樞軸)。
使用這種方法,您只需將一個學生的所有 400 多行數據發送到瀏覽器(通常為 JSON 格式),然後讓瀏覽器將它們組合在一起並進行排序。