[技術部落格]資料庫的評測與選擇
我們以及許多其他項目組都使用了Django作為後端,而采用的資料庫卻有SQLite3, MySQL, PostgreSQL等多種。在alpha階段尾聲時,我們遭受了一次攻擊,在回檔時我們發現了SQLite3有一些不友善。是以我們打算在beta從SQLite3上切換到其他資料庫,是以打算考察一下資料庫的性能。網上現有的評測大多是基于SQL代碼直接測試的,例如這個,而我們在實踐中主要用的是Django封裝的模型,還是有所差别的,是以我們自己進行了一次測試。我們的測試不是十分完善,僅供參考。
三種資料庫都有什麼優勢和坑
測試之前我們先上網調研了一下三種資料庫的優勢與劣勢,可以參考這裡。
SQLite3
優勢
- 非常輕量級
- 小資料量時性能高
- 記憶體占用少
- Django内置,不需要什麼其他配置
不足
- 并發差。(注:SQLite隻支援庫級鎖,這意味着一寫多讀的模式,不能并發的執行寫操作。)
- 單檔案儲存導緻大資料時表現較差。
- 復原等的支援較差
MySQL
- 用的人多,教程多
- 性能還行
- 出錯時復原較好
- 坑比較多
- 大坑UTF-8,網上的教程大多數都有這個問題,與實際的UTF-8并不相容,需要切換UTF8bm4。表現是不支援emoji和部分生僻字。(參考友商網頁不能在評論中打emoji,也不能顯示)
- text要手動區分 small text, middle text, large text,不支援json,array等類型儲存
- 内置的是悲觀鎖
PostgreSQL
- 穩定
- 支援json,jsonb,array,圖等資料的存儲和索引
- text内置支援無限長度
- 高負載,大資料量下性能依然很好
- 比較小衆(但是用的公司其實不少)
- 教程可能比較少
測試用伺服器
在進行測試之前,我們先介紹一下伺服器。伺服器使用的是華為雲贊助的伺服器,現在作為課程設計網站的測試環境之一。伺服器硬體性能穩定,配置如下:
Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz *1
1G 記憶體
2G swap
50G 硬碟
其中我們比較關心的是硬碟性能。4k讀寫性能對于資料庫性能有較大的影響,在機械硬碟,消費級固态和企業級固态上同一個資料庫甚至有數個數量級的性能差距。我們用了dd指令來測試硬碟性能,這兩條大緻測試了順序讀寫和4K性能。
dd if=/dev/zero of=test.dbf bs=500M count=2 oflag=dsync
dd if=/dev/zero of=test.dbf bs=4k count=20000 oflag=dsync
結果如下:

免費的伺服器要什麼自行車,能用就行。
雖然硬碟性能一般,但是三者的測試環境一緻,還是能較公平的展示效果的。
測試内容
我們對三個選手進行了增删改查這四項資料庫正常操作測試。測試代碼完全相同,每組測試唯一的差別是在settings.py中指定的資料庫不一樣。由于我們的主要目的是測試在Django模型層的性能差距,是以對于其他方面有所忽視,我們對于并發上的測試較薄弱,另外跨表查詢也沒有做,測試還是比較水的。主要代碼如下:
def test(request):
times = []
a=time.time()
t=10000 # 還測試了100000
b=list(range(t))
random.shuffle(b)
for i in range(t): # 增
c=Test(con=i) # Test為目标測試資料模型
c.save()
times.append(time.time()-a)
a=time.time()
for i in b: # 查
c=Test.objects.get(con=i)
times.append(time.time()-a)
a=time.time()
for i in b: # 查+改
c=Test.objects.get(con=i)
c.con=-c.con
c.save()
times.append(time.time()-a)
a=time.time()
for i in b: # 删
c=Test.objects.get(con=-i)
c.delete()
times.append(time.time()-a)
saveToFile(times)
settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
# 在測試時隻更換ENGINE為下面兩個,不改其他代碼
'ENGINE': 'django.db.backends.mysql',
'ENGINE':'django.db.backends.postgresql_psycopg2',
}
}
測試結果
我們測了10000組4項操作和100000組操作的執行時間,機關為秒,越短越好。
可以看到:
- SQLite3 在小資料時的确是最快的
- MySQL 基本可以說是墊底了
- PG在較大資料量時優化比MySQL好得多,性能一直和SQLite3較接近
- MySQL和PG在增删上表現更好,可能是結構上的優勢。
結論
一張萬年老圖可以說明問題
就結論上來說,雖然MySQL看上去大比分落後,其實選的啥都行。主要原因是我們網站規模較小,實際差别不大。我們的網站可能最終也不會超過50000條資料。
就我們項目而言,目前采取的是定時備份+SQLite3。考慮到各個資料庫的坑以及復原等的需求,我們打算遷移到PG上,但是優先級較低,不是迫切的需求。