SqlAlchemy:基於Python的ORM框架之數據庫逆向工程(正向工程)- sqlacodegen

目錄

時間過得真快

多因子數據庫及數據API設計經驗

數據庫逆向工程


時間過得真快

感慨一聲:都要2020了!

由於工作繁忙,已經不是學生時代,所以現在的文章數量少了很多。

不過,我爭取寫出一點高質量的體會,彌補數量上的缺憾。

 

最近在做多因子(數量化投資)的底層數據庫及數據API基建工作。

看了不少基於關係型數據庫的多因子數據庫結構,也看了不少關於數據API的代碼。

經過反覆推敲,終於初步確定數據庫的表結構、數據API的基本思路。

只要頂層設計得好,寫代碼是很快的。在此總結一些經驗。

 

多因子數據庫及數據API設計經驗

我之前比較反感在Python裏用ORM,而不是直接用SQL,是因爲曾經見到的代碼,拿着ORM這把牛刀去殺雞。

請見我之前的文章《疑問:對於反三範式設計下的關係型數據庫,是否需要ORM?》。

當時我提了三點不想用ORM的理由。

1. 當時的數據庫不講三範式,數據冗餘得完全可以不用聯合查詢(單表可以涵蓋很多內容)。

2. 頁面展示。pandas的read_sql可以直接成爲dataframe,而dataframe.to_html又可以直接成爲<table></table>。當時的需求是前端展示以表格爲主。當時我看見有人在類似DAO層(其實並沒有分層)的地方,把table封裝成object。握草,我到了View層又要把object轉成table?

3. 儘管在切換數據庫類型時,我們可以不用改DAO層的代碼,但是當時一是我們沒有切換數據庫的需求,二是當時的代碼可能就是三五個人寫一寫,再修修補補,既沒有分層,又沒有分模塊。

 

現在,我卻極力向大家推薦ORM。真香!

1. 我們現在的庫滿足三範式。我們用到的原生態數據庫是專業數據機構設計的,三範式、主外鍵、約束,應有盡有。我們落地的數據庫就是把原生態數據庫拷貝了一份,一模一樣。我們自己設計的因子庫,因子表簡單、統一,滿足三範式。有時候還會出現基於“一對多”的“多”去查“一”,或是基於“一”去查“多”。ORM框架一般支持正向查詢和反向查詢。

2. 我們現在無需前端以表格的方式展示。給上層用戶提供的數據查詢API,通過輸入證券代碼、時間、因子名,返回二維表的形式。sql語句由sqlalchemy自主生成,pd.read_sql成df,傳給上層。同時,我看中了不必自己用string拼接sql語句的功能。

3. 現在我們的原生態庫是SQL Server,自己的備份落地庫和因子庫是MySQL。所以爲了不重複寫代碼,用Sqlalchemy在DAO層與DB層之間架一座橋樑是有必要的。

4. 往後要接實盤交易,實盤的數據、訂單,當然應該以對象的方式存在和處理,但數據庫又是關係型數據庫,正好發揮出ORM的優勢。

 

經驗就是:

1. 沒有好不好的技術,只有適不適合的技術。

2. 如果用關係型數據庫,儘量還是符合三範式。

不冗餘,維護成本較低,數據一致性較高。選股票嘛,數據定了就定了,不能改了。你又不能活在未來,10月8日手裏的數據只有這些,只能用這些。後期就算是修改了,在回測(backtesting)的時候,在日期=10月8日的那一天,你也不能用更新後的數據(未來數據)。

3. 橫向分層,縱向分模塊。多人協作,應該事先規定好接口(統一出一套標準)。儘管書上強調過很多次,但真正在實施的過程中,往往不會這麼做。而結局當然也會是:自食其果、自討苦喫。

4. 至於接實盤,要考慮自己在市場上是什麼身份。投機者?套利?對沖

 

數據庫逆向工程

我這裏是基於Python的逆向工程。其他語言當然也有非常經典的框架,如Java的Hibernate。

根據已有的數據庫,逆向生成model描述文件(關係-對象映射描述文件)。

一定要用CMD,不能用PowerShell,否則會出現編碼的問題!

ValueError: source code string cannot contain null bytes

 

安裝 sqlacodegen

pip install sqlacodegen

 

生成mysql的model

sqlacodegen mysql://root:root@localhost:3306/db_wind > models.py

 

生成sql server (mssql)的model

sqlacodegen mssql+pymssql://user:[email protected]:1433/jydb > jy_models.py

如果報錯 ModuleNotFoundError: No module named 'MySQLdb',安裝mysqlclient即可

pip install mysqlclient

如果報錯 sqlalchemy.exc.InvalidRequestError: Could not reflect: requested table(s) not available in Engine(mssql+pymssql://root:***@xxx.xx.xx.x:1433/.....

可能是在命令行內表名沒有區分大小寫。比如,mssql表名要區分大小寫。但,mysql在windows下好像數據庫名和表名不區分大小寫…這個只有自己協調了。

如果只需要生成某些表, --tables table_1,table_2

 

sqlacodegen的幫助

sqlacodegen -h

 

注意事項

如果字段名、表名、數據庫名是中文,逆向生成models.py會出問題!

如果需要輸出sql語句,創建引擎時,設置echo=True即可。

engine = create_engine('mysql+pymysql://qcy:[email protected]:3306/db_wind', echo=True)

 

創建表結構(根據model描述文件)

Base.metadata.create_all(engine)  # 創建表結構

凡是繼承了Base的類,都會被創建成表


Drop所有表

Base.metadata.drop_all(engine)  # drop所有表

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章