今天就跟大家聊聊有關(guān)基于TPC-C基準的Python ORM的性能測試,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
十余年的訥河網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。成都全網(wǎng)營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整訥河建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)建站從事“訥河網(wǎng)站設(shè)計”,“訥河網(wǎng)站推廣”以來,每個客戶項目都認真落實執(zhí)行。
當開發(fā)與數(shù)據(jù)庫需要在一起使用的應(yīng)用程序時,對象關(guān)系映射器(ORM)通常用于Python編程中。Python ORM的示例是SQLAlchemy,Peewee,Pony-ORM和Django。選擇ORM性能起著至關(guān)重要的作用。但是如何比較這些工具集?ORM性能基準提供了明確的度量,但仍有很大的改進空間。我研究并擴展了定性的ORM基準,以幫助有需要開發(fā)需要的。定性的Python ORM基準Tortoise ORM(鏈接到存儲庫)分析了11種SQL查詢的六個ORM的速度。
通常,Tortoise基準可以評估各種ORM的查詢執(zhí)行速度。但是,這種測試方法存在一個缺陷:大多數(shù)ORM被選擇用于Web應(yīng)用程序。在這種情況下,多個用戶經(jīng)常將所有形式的查詢發(fā)送到數(shù)據(jù)庫。因為在這種情況下沒有評估的基準測試工具能夠評估Python ORM的性能,所以我決定編寫自己的PonyORM和SQLAlchemy進行比較。作為基礎(chǔ),我采用了TPC-C基準。
自1988年以來,TPC一直在數(shù)據(jù)處理領(lǐng)域開發(fā)測試。它們早已成為行業(yè)標準,幾乎所有設(shè)備供應(yīng)商都在各種硬件和軟件樣本上使用它們。這些測試的主要特征是它們專注于在盡可能接近真實條件的巨大負載下進行測試。
TPC-C模擬倉庫網(wǎng)絡(luò)。它包括五個同時執(zhí)行的各種類型和復(fù)雜性的事務(wù)的組合。該測試的目的是評估多個虛擬用戶同時訪問數(shù)據(jù)庫時事務(wù)處理的速度。
我決定使用適合此任務(wù)的TPC-C測試方法測試兩個Python ORM(SQLALchemy和PonyORM)。該測試的目的是評估多個虛擬用戶同時訪問數(shù)據(jù)庫時事務(wù)處理的速度。
測試說明
第一步是創(chuàng)建并填充倉庫網(wǎng)絡(luò)的數(shù)據(jù)庫。
該數(shù)據(jù)庫包含八個關(guān)系:
1. 倉庫
2. 區(qū)
3. 訂購
4. 訂單行
5. 股票
6. 項目
7. 顧客
8. 歷史
Pony和SQLAlchemy的數(shù)據(jù)庫是相同的。僅索引主鍵和外鍵。小A會自動創(chuàng)建這些索引。在SQLAlchemy中,我手動創(chuàng)建了它。
在測試過程中,幾種虛擬用戶將不同類型的事務(wù)發(fā)送到數(shù)據(jù)庫。每個事務(wù)包含幾個請求??偣灿形宸N類型的交易以不同的發(fā)生概率提交處理:
交易:
1. 新訂單-45%
2. 付款-43%
3. order_status-4%
4. 交付-4%
5. 股票水平-4%
發(fā)生交易的可能性與原始TPC-C測試中的相同。
但是,請記住,由于技術(shù)上的限制以及我想測試以下處理器的性能,因此在具有64 GB以上RAM(需要大量處理器和巨大磁盤空間)的服務(wù)器上進行了原始TPC-C測試。 ORM而不是硬件抵抗巨大負載的能力,因此此測試有所簡化。
與TPC-C測試的主要區(qū)別如下:
主要區(qū)別:
1. 該測試運行的虛擬用戶少于原始測試
2. 我的測試的表條目較少。例如:原始測試中“庫存”關(guān)系中的條目數(shù)是使用公式100,000 * W計算的,其中W是倉庫數(shù)。在此測試中為100 *W。
3. 在TPC-C中,某些事務(wù)具有從數(shù)據(jù)庫查詢數(shù)據(jù)的多個選項。例如,在支付交易中,有一種可能性,將通過ID從數(shù)據(jù)庫中請求客戶,而另一種則是由姓和名。目前,我的測試僅按ID撥打電話。
4. 我的測試數(shù)據(jù)庫比TPC-C少一個表。在TPC-C測試中,創(chuàng)建訂單后,會將其添加到Order表和NewOrder表中。訂單交付后,便從NewOrder表中將其刪除。每分鐘應(yīng)用大量事務(wù)時,這可以加快工作速度;但是由于我訪問數(shù)據(jù)庫的用戶較少,所以這是不必要的。相反,在Order表中,我添加了bool屬性“ is_o_delivered”,該屬性將為False,直到交付訂單為止。
接下來,我將簡要描述每個事務(wù)的作用。
交易次數(shù)
新命令
1. 將兩個參數(shù)傳遞給事務(wù):倉庫ID和客戶ID
2. 使用傳遞的ID從數(shù)據(jù)庫中選擇倉庫和客戶
3. 從數(shù)據(jù)庫中隨機選擇一個倉庫區(qū)域
4. 生成指示訂單行數(shù)的隨機數(shù)。
5. 創(chuàng)建一個Order對象
6. 循環(huán)創(chuàng)建OrderLine對象。在循環(huán)的每次迭代中,從項目表中選擇一個隨機項目
7. 更改訂單中每個項目的庫存
付款
1. 將兩個參數(shù)傳遞給事務(wù):倉庫ID和客戶ID
2. 通過傳遞的ID從數(shù)據(jù)庫中選擇倉庫和客戶
3. 從數(shù)據(jù)庫中隨機選擇一個倉庫區(qū)域
4. 生成一個指示付款金額的隨機數(shù)
5. 按付款金額增加倉庫和區(qū)域的余額
6. 客戶余額減少付款金額
7. 遞增客戶付款柜臺
8. 客戶付款金額的總和增加
9. 創(chuàng)建歷史記錄對象
訂單狀態(tài)
1. 傳遞客戶ID作為交易的參數(shù)
2. 通過ID和該客戶的最后訂單選擇客戶
3. 從訂單中獲取訂單狀態(tài)和訂單行。
交貨
1. 傳遞倉庫ID作為交易參數(shù)
2. 從數(shù)據(jù)庫中選擇倉庫及其所有區(qū)域
3. 為每個地區(qū)選擇最舊的未交付訂單。
4. 對于每個將交貨狀態(tài)更改為True的訂單
5. 對于每個訂單數(shù)量遞增的客戶
庫存水平
1. 傳遞倉庫ID作為交易參數(shù)
2. 通過ID從數(shù)據(jù)庫中選擇倉庫
3. 選擇該倉庫的最后20個訂單
4. 對于訂單中的每個項目,評估項目的庫存水平
檢測結(jié)果
有兩個ORM參與測試:
1. SQLAlchemy(圖形上的藍線)
2. PonyORM(圖形上的橙色線)
以下是通過2個并行進程訪問數(shù)據(jù)庫運行測試10分鐘的結(jié)果。使用“多重處理”模塊啟動流程。
X軸-時間(以分鐘為單位)
Y軸-已完成的交易數(shù)
作為DBMS,我使用PostgreSQL
所有交易
首先,按照TPC-C測試中的預(yù)期,我對所有五個事務(wù)進行了測試。這項測試的結(jié)果是,小A的速度大約是以前的兩倍。
平均速度:
· 小A-2543筆交易/分鐘
· SQLAlchemy-1353.4事務(wù)/分鐘
之后,我決定分別評估五筆交易中ORM的性能。以下是每筆交易的結(jié)果。
新命令
平均速度:
· 小A-3349.2交易/分鐘
· SQLAlchemy-1415.3事務(wù)/分鐘
付款
平均速度:
· 小A-7175.3事務(wù)/分鐘
· SQLAlchemy-4110.6事務(wù)/分鐘
訂單狀態(tài)
平均速度:
· 小A-16645.6交易/分鐘
· SQLAlchemy-4820.8事務(wù)/分鐘
交貨
平均速度:
· SQLAlchemy-716.9事務(wù)/分鐘
· 小A-323.5交易/分鐘
庫存水平
平均速度:
· 小A-677.3交易/分鐘
· SQLAlchemy-167.9事務(wù)/分鐘
測試結(jié)果分析
收到結(jié)果后,我分析了為什么會這樣,并得出以下結(jié)論:
在5分之4的事務(wù)中,PonyORM的速度更快,因為在生成SQL代碼時,PonyORM會記住將Python表達式轉(zhuǎn)換為SQL的結(jié)果。因此,Pony不會在重復(fù)查詢時再次轉(zhuǎn)換該表達式,而SQLAlchemy在每次需要執(zhí)行查詢時都被強制生成SQL代碼。
Pony中此類查詢的示例:
stocks = select(stock for stock in Stock if stock.warehouse == whouse and stock.item in items).order_by(Stock.id).for_update()
生成的SQL:
SELECT “stock”.”id”, “stock”.”warehouse”, “stock”.”item”, “stock”.”quantity”, “stock”.”ytd”, “stock”.”order_cnt”, “stock”.”remote_cnt”, “stock”.”data”FROM “stock” “stock”WHERE “stock”.”warehouse” = %(p1)s AND “stock”.”item” IN (%(p2)s, %(p3)s)ORDER BY “stock”.”id”FOR UPDATE {‘p1’:7, ‘p2’:7, ‘p3’:37} SQLAlchemy: stocks = session.query(Stock).filter( Stock.warehouse == whouse, Stock.item.in_( items)).order_by(text(“id”)).with_for_update()
生成的SQL:
SELECT stock.id AS stock_id, stock.warehouse_id AS stock_warehouse_id, stock.item_id AS stock_item_id, stock.quantity AS stock_quantity, stock.ytd AS stock_ytd, stock.order_cnt AS stock_order_cnt, stock.remote_cnt AS stock_remote_cnt, stock.data AS stock_dataFROM stockWHERE stock.warehouse_id = %(warehouse_id_1)s AND stock.item_id IN (%(item_id_1)s, %(item_id_2)s) ORDER BY id FOR UPDATE {‘warehouse_id_1’: 7, ‘item_id_1’: 53, ‘item_id_2’: 54}
但是,顯然,SQLAlchemy可以更快地執(zhí)行交付類型事務(wù),因為它可以將應(yīng)用于不同對象的多個UPDATE操作組合到一個命令中。
例:
INFO:www.zpedu.com/sqlalchemy.engine.base.Engine:UPDATE order_line SET delivery_d=% (delivery_d)s WHERE order_line.id = %(order_line_id)s INFO:sqlalchemy.engine.base.Engine:( {‘delivery_d’: datetime.datetime(2020, 4, 6, 14, 33, 6, 922281), ‘order_line_id’: 316}, {‘delivery_d’: datetime.datetime(2020, 4, 6, 14, 33, 6, 922272), ‘order_line_id’: 317}, {‘delivery_d’: datetime.datetime(2020, 4, 6, 14, 33, 6, 922261))
在這種情況下,小A會為每個更新發(fā)送單獨的查詢。
結(jié)論
根據(jù)測試的結(jié)果,我可以說Pony從數(shù)據(jù)庫中選擇的速度更快。另一方面,在某些情況下,SQLAlchemy可以以更高的速度生成Update類型的查詢。
看完上述內(nèi)容,你們對基于TPC-C基準的Python ORM的性能測試有進一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。