2015-04-06 29 views
0

我設計了一個以短鏈接爲中心的數據庫。Rails基於行的數據庫,巨大的請求數

我有以下模式:

create_table "students", force: :cascade do |t| 
    t.string "first_name" 
    t.string "last_name" 
    t.string "email" 
    t.boolean "recruit", default: true 
    t.boolean "archive", default: false 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    create_table "fields", force: :cascade do |t| 
    t.string "name" 
    t.integer "index" 
    t.integer "group_id" 
    t.string "description" 
    t.string "options" 
    t.boolean "hidden" 
    t.boolean "locked",  default: false 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    create_table "groups", force: :cascade do |t| 
    t.string "name" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    create_table "texts", force: :cascade do |t| 
    t.integer "student_id" 
    t.integer "field_id" 
    t.string "content", default: "" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    create_table "options", force: :cascade do |t| 
    t.integer "student_id" 
    t.integer "field_id" 
    t.string "choice",  default: "" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    create_table "addresses", force: :cascade do |t| 
    t.integer "student_id" 
    t.integer "field_id" 
    t.string "address_1", default: "" 
    t.string "address_2", default: "" 
    t.string "city",  default: "" 
    t.integer "state_id", default: 1 
    t.string "zip",  default: "" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

這個組織背後的基礎是一個完全靈活的形式。您只需在字段表中添加一個新行,並且該條目在生成學生的表單上定義了一個新問題。組引用選項字段,文本字段或地址。保存數據時,與給定字段關聯的組會告訴我的應用程序將哪個表放入。此係統運行良好。這是非常靈活的,我可以很容易地看到學生有什麼數據的某些選項,我可以基於幾乎任何東西進行查詢。

問題是當我開始顯示學生。我首先查詢我想要展示的學生,然後我必須搜索每個學生的每個領域。這意味着對於500名學生,我基本上有大約2500條查詢。這會殺死性能。

我想知道什麼最好的方式來加入查詢在一起,加快這個系統是?

部分原因是我不能100%確定學生有給定的字段,所以當我現在查詢時,如果數據庫沒有返回任何結果,我可以創建一個。

回答

0

它不會顯示好像你有任何外鍵這裏定義。使用FK並確保它們在每個表上使用索引的組合應允許快速連接。

我假設你正在使用ActiveRecord的基於Rails的DSL在你的問題。一旦你添加了FK,我會建議你考慮使用joinsActiveRecord Querying doc

如果你擔心某種JOIN列不存在,你可以使用LEFT OUTER JOIN從左側表中調用(在上面的鏈接提到),以joins,這樣你仍然可以得到所有的行,即使有在連接條件中沒有匹配,只需獲得右側的NULL列值。那些是NULL會告訴你哪些不存在,可能需要隨後創建。響應

編輯從OP評論:

我沒有用的SchemaPlus寶石,不過我覺得這很好使用外鍵,如果你想,因爲這是的事情之一它支持(根據its doc)。

對於這個問題:

等有致認爲它是如果 某種原因,數據不再一端存在的外鍵的問題?

外鍵對執行referential integrity至關重要。

例如,如果你有field_id作爲texts表的外鍵,你不能刪除從field表中相應的記錄(不使用cascade刪除下游記錄爲好),因爲它指的是記錄在field

在另一面,你就無法插入texts一排無效field_id - 如果field_id沒有在fields存在,的Postgres會拋出一個外鍵約束違反

外鍵是表設計的關鍵部分,絕對應該使用。它使您無需將所有邏輯都放在應用程序代碼中的所有位置,例如在嘗試插入任何內容之前,必須檢查您要插入的鍵是否有效;相反,如果它們不是,Postgres將違反約束條件,並作爲可處理的異常(例如回滾和返回錯誤)返回到您的應用程序。

基本上,任何時候你在一個表中引用另一個表中的記錄時,都應該在外鍵約束中定義一個id。

此外,它可能值得添加一個主鍵到每個表。我經常喜歡使用serial變量來確保每一行都可以通過一個鍵來識別,即使存在形成隱含主鍵的元組。主鍵也隱式創建基於這些鍵的索引。

+0

嗨。我一直在研究SchemaPlus gem,並且似乎將外部約束作爲一個簡單的慣例添加到我的遷移中。只是把我打算成爲外鍵的所有列正式列出來,是否有任何問題?如果由於某種原因導致數據在一端停止存在,那麼認爲它是一個外鍵會導致問題嗎?我有一些行會引用我的主用戶表,並且可能是一個鍵,但它們也可以被刪除。外鍵會導致刪除中的連鎖反應嗎? – 2015-04-08 03:38:03