數(shù)據(jù)庫設(shè)計經(jīng)驗談(7) (轉(zhuǎn))
別忘了索引
索引是從數(shù)據(jù)庫中獲取數(shù)據(jù)的最高效方式之一。95% 的數(shù)據(jù)庫性能問題都可以采用索引技術(shù)得到解決。作為一條規(guī)則,我通常對邏輯主鍵使用唯一的成組索引,對系統(tǒng)鍵(作為存儲過程)采用唯一的非成組索引,對任何外鍵列[字段]采用非成組索引。不過,索引就象是鹽,太多了菜就咸了。你得考慮數(shù)據(jù)庫的空間有多大,表如何進行訪問,還有這些訪問是否主要用作讀寫。
大多數(shù)數(shù)據(jù)庫都索引自動創(chuàng)建的主鍵字段,但是可別忘了索引外鍵,它們也是經(jīng)常使用的鍵,比如運行查詢顯示主表和所有關(guān)聯(lián)表的某條記錄就用得上。還有,不要索引 memo/note 字段,不要索引大型字段(有很多字符),這樣作會讓索引占用太多的存儲空間。
不要索引常用的小型表
不要為小型數(shù)據(jù)表設(shè)置任何鍵,假如它們經(jīng)常有插入和刪除操作就更別這樣作了。對這些插入和刪除操作的索引維護可能比掃描表空間消耗更多的時間。
不要把社會保障號碼(SSN)或身份證號碼(ID)選作鍵
永遠都不要使用 SSN 或 ID 作為數(shù)據(jù)庫的鍵。除了隱私原因以外,須知政府越來越趨向于不準許把 SSN 或 ID 用作除收入相關(guān)以外的其他目的,SSN 或 ID 需要手工輸入。永遠不要使用手工輸入的鍵作為主鍵,因為一旦你輸入錯誤,你唯一能做的就是刪除整個記錄然后從頭開始。
我在破解他人的程序時候,我看到很多人把 SSN 或 ID 還曾被用做系列號,當(dāng)然盡管這么做是非法的。而且人們也都知道這是非法的,但他們已經(jīng)習(xí)慣了。后來,隨著盜取身份犯罪案件的增加,我現(xiàn)在的同行正痛苦地從一大攤子數(shù)據(jù)中把 SSN 或 ID 刪除。
不要用用戶的鍵
在確定采用什么字段作為表的鍵的時候,可一定要小心用戶將要編輯的字段。通常的情況下不要選擇用戶可編輯的字段作為鍵。這樣做會迫使你采取以下兩個措施:
1.在創(chuàng)建記錄之后對用戶編輯字段的行為施加限制。假如你這么做了,你可能會發(fā)現(xiàn)你的應(yīng)用程序在商務(wù)需求突然發(fā)生變化,而用戶需要編輯那些不可編輯的字段時缺乏足夠的靈活性。當(dāng)用戶在輸入數(shù)據(jù)之后直到保存記錄才發(fā)現(xiàn)系統(tǒng)出了問題他們該怎么想?刪除重建?假如記錄不可重建是否讓用戶走開?
2.提出一些檢測和糾正鍵沖突的方法。通常,費點精力也就搞定了,但是從性能上來看這樣做的代價就比較大了。還有,鍵的糾正可能會迫使你突破你的數(shù)據(jù)和商業(yè)/用戶界面層之間的隔離。
所以還是重提一句老話:你的設(shè)計要適應(yīng)用戶而不是讓用戶來適應(yīng)你的設(shè)計。
不讓主鍵具有可更新性的原因是在關(guān)系模式下,主鍵實現(xiàn)了不同表之間的關(guān)聯(lián)。比如,Customer 表有一個主鍵 CustomerID,而客戶的定單則存放在另一個表里。Order 表的主鍵可能是 OrderNo 或者 OrderNo、CustomerID 和日期的組合。不管你選擇哪種鍵設(shè)置,你都需要在 Order 表中存放 CustomerID 來保證你可以給下定單的用戶找到其定單記錄。
假如你在 Customer 表里修改了 CustomerID,那么你必須找出 Order 表中的所有相關(guān)記錄對其進行修改。否則,有些定單就會不屬于任何客戶——數(shù)據(jù)庫的完整性就算完蛋了。
如果索引完整性規(guī)則施加到表一級,那么在不編寫大量代碼和附加刪除記錄的情況下幾乎不可能改變某一條記錄的鍵和數(shù)據(jù)庫內(nèi)所有關(guān)聯(lián)的記錄。而這一過程往往錯誤叢生所以應(yīng)該盡量避免。
可選鍵(候選鍵)有時可做主鍵
記住,查詢數(shù)據(jù)的不是機器而是人。
假如你有可選鍵,你可能進一步把它用做主鍵。那樣的話,你就擁有了建立強大索引的能力。這樣可以阻止使用數(shù)據(jù)庫的人不得不連接數(shù)據(jù)庫從而恰當(dāng)?shù)倪^濾數(shù)據(jù)。在嚴格控制域表的數(shù)據(jù)庫上,這種負載是比較醒目的。如果可選鍵真正有用,那就是達到了主鍵的水準。
我的看法是,假如你有可選鍵,比如國家表內(nèi)的 state_code,你不要在現(xiàn)有不能變動的唯一鍵上創(chuàng)建后續(xù)的鍵。你要做的無非是創(chuàng)建毫無價值的數(shù)據(jù)。如你因為過度使用表的后續(xù)鍵[別名]建立這種表的關(guān)聯(lián),操作負載真得需要考慮一下了。
別忘了外鍵
大多數(shù)數(shù)據(jù)庫索引自動創(chuàng)建的主鍵字段。但別忘了索引外鍵字段,它們在你想查詢主表中的記錄及其關(guān)聯(lián)記錄時每次都會用到。還有,不要索引 memo/notes 字段而且不要索引大型文本字段(許多字符),這樣做會讓你的索引占據(jù)大量的數(shù)據(jù)庫空間。
索引是從數(shù)據(jù)庫中獲取數(shù)據(jù)的最高效方式之一。95% 的數(shù)據(jù)庫性能問題都可以采用索引技術(shù)得到解決。作為一條規(guī)則,我通常對邏輯主鍵使用唯一的成組索引,對系統(tǒng)鍵(作為存儲過程)采用唯一的非成組索引,對任何外鍵列[字段]采用非成組索引。不過,索引就象是鹽,太多了菜就咸了。你得考慮數(shù)據(jù)庫的空間有多大,表如何進行訪問,還有這些訪問是否主要用作讀寫。
大多數(shù)數(shù)據(jù)庫都索引自動創(chuàng)建的主鍵字段,但是可別忘了索引外鍵,它們也是經(jīng)常使用的鍵,比如運行查詢顯示主表和所有關(guān)聯(lián)表的某條記錄就用得上。還有,不要索引 memo/note 字段,不要索引大型字段(有很多字符),這樣作會讓索引占用太多的存儲空間。
不要索引常用的小型表
不要為小型數(shù)據(jù)表設(shè)置任何鍵,假如它們經(jīng)常有插入和刪除操作就更別這樣作了。對這些插入和刪除操作的索引維護可能比掃描表空間消耗更多的時間。
不要把社會保障號碼(SSN)或身份證號碼(ID)選作鍵
永遠都不要使用 SSN 或 ID 作為數(shù)據(jù)庫的鍵。除了隱私原因以外,須知政府越來越趨向于不準許把 SSN 或 ID 用作除收入相關(guān)以外的其他目的,SSN 或 ID 需要手工輸入。永遠不要使用手工輸入的鍵作為主鍵,因為一旦你輸入錯誤,你唯一能做的就是刪除整個記錄然后從頭開始。
我在破解他人的程序時候,我看到很多人把 SSN 或 ID 還曾被用做系列號,當(dāng)然盡管這么做是非法的。而且人們也都知道這是非法的,但他們已經(jīng)習(xí)慣了。后來,隨著盜取身份犯罪案件的增加,我現(xiàn)在的同行正痛苦地從一大攤子數(shù)據(jù)中把 SSN 或 ID 刪除。
不要用用戶的鍵
在確定采用什么字段作為表的鍵的時候,可一定要小心用戶將要編輯的字段。通常的情況下不要選擇用戶可編輯的字段作為鍵。這樣做會迫使你采取以下兩個措施:
1.在創(chuàng)建記錄之后對用戶編輯字段的行為施加限制。假如你這么做了,你可能會發(fā)現(xiàn)你的應(yīng)用程序在商務(wù)需求突然發(fā)生變化,而用戶需要編輯那些不可編輯的字段時缺乏足夠的靈活性。當(dāng)用戶在輸入數(shù)據(jù)之后直到保存記錄才發(fā)現(xiàn)系統(tǒng)出了問題他們該怎么想?刪除重建?假如記錄不可重建是否讓用戶走開?
2.提出一些檢測和糾正鍵沖突的方法。通常,費點精力也就搞定了,但是從性能上來看這樣做的代價就比較大了。還有,鍵的糾正可能會迫使你突破你的數(shù)據(jù)和商業(yè)/用戶界面層之間的隔離。
所以還是重提一句老話:你的設(shè)計要適應(yīng)用戶而不是讓用戶來適應(yīng)你的設(shè)計。
不讓主鍵具有可更新性的原因是在關(guān)系模式下,主鍵實現(xiàn)了不同表之間的關(guān)聯(lián)。比如,Customer 表有一個主鍵 CustomerID,而客戶的定單則存放在另一個表里。Order 表的主鍵可能是 OrderNo 或者 OrderNo、CustomerID 和日期的組合。不管你選擇哪種鍵設(shè)置,你都需要在 Order 表中存放 CustomerID 來保證你可以給下定單的用戶找到其定單記錄。
假如你在 Customer 表里修改了 CustomerID,那么你必須找出 Order 表中的所有相關(guān)記錄對其進行修改。否則,有些定單就會不屬于任何客戶——數(shù)據(jù)庫的完整性就算完蛋了。
如果索引完整性規(guī)則施加到表一級,那么在不編寫大量代碼和附加刪除記錄的情況下幾乎不可能改變某一條記錄的鍵和數(shù)據(jù)庫內(nèi)所有關(guān)聯(lián)的記錄。而這一過程往往錯誤叢生所以應(yīng)該盡量避免。
可選鍵(候選鍵)有時可做主鍵
記住,查詢數(shù)據(jù)的不是機器而是人。
假如你有可選鍵,你可能進一步把它用做主鍵。那樣的話,你就擁有了建立強大索引的能力。這樣可以阻止使用數(shù)據(jù)庫的人不得不連接數(shù)據(jù)庫從而恰當(dāng)?shù)倪^濾數(shù)據(jù)。在嚴格控制域表的數(shù)據(jù)庫上,這種負載是比較醒目的。如果可選鍵真正有用,那就是達到了主鍵的水準。
我的看法是,假如你有可選鍵,比如國家表內(nèi)的 state_code,你不要在現(xiàn)有不能變動的唯一鍵上創(chuàng)建后續(xù)的鍵。你要做的無非是創(chuàng)建毫無價值的數(shù)據(jù)。如你因為過度使用表的后續(xù)鍵[別名]建立這種表的關(guān)聯(lián),操作負載真得需要考慮一下了。
別忘了外鍵
大多數(shù)數(shù)據(jù)庫索引自動創(chuàng)建的主鍵字段。但別忘了索引外鍵字段,它們在你想查詢主表中的記錄及其關(guān)聯(lián)記錄時每次都會用到。還有,不要索引 memo/notes 字段而且不要索引大型文本字段(許多字符),這樣做會讓你的索引占據(jù)大量的數(shù)據(jù)庫空間。
預(yù)告:在第四部分將討論保證數(shù)據(jù)完整性,如何保持數(shù)據(jù)庫的清晰和健壯,如何把有害數(shù)據(jù)降低到最小程度。