摘要:數據庫關系數據庫將數據保存在表中來模擬應用程序中不同的實體。這些行之間的連接稱作關系,也是關系數據庫模型的基礎。就像這個示例中看到的那樣,關系數據庫存儲數據高效且避免重復。最好的例子就是,支持一組關系數據庫引擎,包括流行的和。
數據庫就是有組織的存儲應用程序數據,然后查詢檢索指定需要的那部分。大部分web應用程序都采用基于關系模型的數據庫,也稱作結構化查詢語言(SQL)數據庫。但是最近幾年面向文檔數據庫和鍵值數據庫(通常稱作NoSQL數據庫),成為非常流行的替代者。個人推薦《七周七數據庫》這本書,它對各種類型的數據庫、應用場景和多種不同類型數據庫配合使用有比較好的講解。
1、SQL數據庫關系數據庫將數據保存在表中來模擬應用程序中不同的實體。例如,一個訂單管理應用程序數據庫可能會有customers、products和orders表。
一個表有一個固定數量的列和一個可變的行數。列定義了數據表所代表的實體的屬性。例如,customers表會有name、address、phone等列。表中的每一行定義了由所有列的值組成的實際數據元素。
表有種特殊列稱作主鍵,它持有一個惟一的標識符為表中存儲的每一行。表也可以有外鍵,用于引用其他表的主鍵。這些行之間的連接稱作關系,也是關系數據庫模型的基礎。
圖像5-1展示了存儲users和roles表的簡單數據庫圖。連接兩個表的線代表兩個表之間的關系。
圖像5-1. 關系數據庫示例
在這個數據庫表中,roles表存儲了一組所有可能的用戶角色,每一個都被定義為唯一id值——也是表的主鍵。users表包含一組用戶,同樣每一個都有唯一id值。除了主鍵id,roles表還有name列,而users表還有username和password列。在users表中的role_id列是一個引用role表中id列的外鍵,以這種方式確立分配給每個用戶的角色。
就像這個示例中看到的那樣,關系數據庫存儲數據高效且避免重復。重命名用戶角色在這個數據庫中會變得異常簡單,因為角色名保存在多帶帶的地方。當roles表中的角色名發生改變,所有用戶持有的role_id引用的角色會立即看到這些變化。
而另一方面,將數據拆分到多個表中則會變得更加復雜。生成一組用戶及其角色會產生一個小問題,因為用戶和用戶角色需要從兩張表中讀,且只有連接后才能一起出現。當需要的時候關系數據庫引擎會提供支持來執行兩個表的連接操作。
2、NoSQL數據庫與上一節描述相反的、非關系模型的數據庫被統稱為NoSQL數據庫。NoSQL數據庫常見的組織方式是使用collections代替表、documents代替記錄。NoSQL數據庫的設計方式使得連接會很復雜,所以大部分都不支持這個操作。圖像5-1如果用NoSQL數據庫結構來表達則是這樣的:列出用戶及他們的角色,需要應用程序自己通過讀取每個用戶的role_id字段去執行連接操作,然后查找roles表。
圖像5-2展示了更接近NoSQL數據庫的設計思想。這個操作運用了一個被稱為反模式的思想,減少了表的數量卻增加了重復數據。
圖像5-2. NoSQL數據庫示例
這種結構的數據庫為每個用戶顯式的存儲用戶角色名。重命名角色名絕對是一項昂貴的操作,可能需要更新大量的文檔。
但對于NoSQL數據庫這并不都是壞消息。雖然有重復的數據,但是查詢速度快,因為不需要連接,可以直接列出用戶和他們的角色。
3、SQL還是NoSQLSQL數據庫擅長以高效、緊湊的形式存儲結構化數據。這些數據庫竭盡全力保持一致性。NoSQL數據庫會放低一些一致性要求,因此在性能上有更大的優勢。
全面分析和比較數據庫類型已經超出了本教程的范圍。對于中小型應用程序SQL數據庫和NoSQL數據庫完全可以勝任,且性能幾乎差不多。
4、Python數據庫框架Python有大部分的數據庫引擎包,包括開源的和商業的。Flask在可使用的數據庫包上沒有限制,所以你可以使用MySQL、Postgres、SQLite、Redis、MongoDB或者CouchDB中你喜歡的任何一個。
如果這些還不夠,也有大量的數據庫抽象層包,如SQLAlchemy或MongoEngine讓你像操作常規Python對象那樣,而不是數據庫實體表、文檔或查詢語句。
在選擇數據庫框架的時候需要評估許多因素:
易用性
如果直接比較數據庫引擎和數據庫抽象層,第二者明顯勝出。抽象層又稱作對象關系映射(ORM)或對象文檔映射(ODM),提供從高級面向對象操作到底層數據庫指令的透明轉換。
性能
ORM和ODM的轉化需要從對象域轉化為數據庫域,所以會有一些開銷。大多數情況下,性能損耗是微不足道的,但總有例外。一般來說,ORM和ODM獲得的生產力遠遠超過了性能下降的那部分,所以這不是一個有效的論點來完全拋棄ORM和ODM。應該關心的是選擇怎樣的數據庫抽象層,提供可訪問底層數據庫中特定操作,就像本地數據庫指令那樣實現的抽象層最佳。
可移植性
數據庫的選擇必須考慮開發和生產平臺。例如,如果你計劃在云主機上托管應用程序,那么你應該找出提供該服務的數據庫。
另一方面ORM和ODM的可移植性不錯。盡管一些框架只為單個數據庫引擎提供抽象層,有些抽象層更高級,可以選擇哪種數據庫引擎且訪問使用的是同一個面向對象的接口。最好的例子就是SQLAlchemy ORM,支持一組關系數據庫引擎,包括流行的MySQL、Postgres和SQLite。
Flask集成
選擇一個集成了Flask的框架并不是必須的,但是可以不用自己寫集成代碼。Flask集成可以簡化配置和操作,所以應該優先使用專門設計的Flask擴展包。
基于這些目的,Flask-SQLAlchemy將是本書示例中應該選擇的數據庫框架,它對SQLAlchemy進行了封裝。
5、使用Flask-SQLAlchemy管理數據庫Flask-SQLAlchemy是一個Flask擴展,它簡化了在Flask應用程序中對SQLAlchemy的使用。SQLAlchemy是一個強大的關系數據庫框架,支持一些數據庫后端。提供高級的ORM和底層訪問數據庫的本地SQL功能。
和其他擴展一樣,通過pip安裝Flask-SQLAlchemy:
(venv) $ pip install flask-sqlalchemy
在Flask-SQLAlchemy,數據庫被指定為URL。表格5-1列出三個最受歡迎的數據庫引擎url的格式。