《MySQL VS MongoDB 你會如何選擇?》要點:
本文介紹了MySQL VS MongoDB 你會如何選擇?,希望對您有用。如果有疑問,可以聯系我們。
相關主題:非關系型數據庫
1.1 背景
數據庫幾乎是線上業務架構里的核心服務,在海量數據環境下,數據庫的讀寫效率直接影響著一款產品的體驗,因此從一開始選擇一款適合適的數據庫就顯得尤為重要.
目前主流的開源方案中,最火的莫過于是MySQL和MongoDB了.而長期以來在當今數據庫市場上,MySQL無疑是占有一席之地,作為一個開源的關系型數據庫,MySQL被大量應用在各大網站后臺,哪怕是我們的主流游戲生產環境中.而存在于另外一個世界的非關系型數據庫MongoDB,卻很不安分,混入了這場平靜,來一個“搶奪戰”.
相信大多數人都知道MongoDB是一種文件導向的數據庫管理系統,屬于一種通稱為NoSQL的數據庫,是10gen公司旗下的開源產品,其內部數據存儲的方式與傳統的關系型數據有很大差別.它是一種新型的革命式的數據庫設計方式,不過它不是為了取代傳統的關系型數據庫而被設計的,它們分別代表了不同的數據庫設計思路.
那到底我們該選擇MySQL 還是 MongoDB呢?如果你的業務必須依賴事務關系的話,那選MySQL無疑了,但是有時候我們需要做一些復雜的聚合或需要靈活存取的場景,那么選哪一個更好,則需要認真評估了.為了讓大家在一開始選擇數據庫時有個參考數據,我們對MongoDB 3.0.7和MySQL 5.5.40分別在大數據(百萬級~千萬級)環境下的平均時延、吞吐量進行了研究對比.
1.2 工具簡介
sysbench是一個模塊化的、跨平臺、多線程基準測試工具,主要用于評估測試各種不同系統參數下的數據庫負載情況.而ycsb(Yahoo! Cloud Serving Benchmark)則是雅虎開源的一款通用的、針對各類NoSQL產品的性能測試工具.
接下來我們簡單的介紹一下用于本次研究對比的壓測工具:
2.1 基礎環境
ycsb工程依賴Java、maven,有maven環境后就可以直接在ycsb根目錄下運行package任務.而sysbench編譯安裝需要automake,于是:
#yum -y install mysql-devel automake libtool git wget unzip python-setuptools java-devel
#easy_install argparse
#wget http://ftp.heanet.ie/mirrors/www.apache.org/dist/maven/maven-3/3.1.1/binaries/apache-maven-3.1.1-bin.tar.gz
#tar xf apache-maven-3.1.1-bin.tar.gz -C /usr/local/
#cd /usr/local && ln -s apache-maven-* maven
# echo “export PATH=/usr/local/maven/bin:\$PATH” >> /etc/profile
# source /etc/profile
2.2 下載并安裝
2.2.1 sysbench
我們選擇最新版的sysbench 0.5版本來測試數據庫性能,該版本優化了oltp的lua腳本測試和實時顯示功能.sysbench默認支持MySQL,如果需要測試Oracle/PostgreSQL,則在configure時需要加上–with-oracle或者–with-pgsql參數.
# wget -O sysbench-0.5.zip https://codeload.github.com/akopytov/sysbench/zip/0.5
#unzip sysbench-0.5.zip
# cd sysbench-0.5
#chmod +x autogen.sh
#./autogen.sh
#./configure –prefix=/usr/local/sysbench –with-mysql –with-mysql-includes=/usr/local/mysql/include –with-mysql-libs=/usr/local/mysql/lib
#make && make install
# echo “export PATH=/usr/local/maven/bin:/usr/local/sysbench/bin:\$PATH” >> /etc/profile
# source /etc/profile
檢查是否安裝成功:
2.2.2 ycsb
我們同樣選擇最新版的ycsb來進行測試并使用mvn編譯安裝.
#cd /usr/local/ && git clone https://github.com/brianfrankcooper/YCSB.git
# ln -s YCSB ycsb
#cd ycsb && mvn -pl com.yahoo.ycsb:mongodb-binding -am clean package
#echo “export PATH=/usr/local/ycsb/bin:/usr/local/maven/bin:/usr/local/sysbench/bin:\$PATH” >> /etc/profile
#source /etc/profile
檢查是否安裝成功:
3.1 基礎環境
為了更好地理解后面的測試過程,我們先對sysbench和ycsb的使用參數進行詳細說明.
3.1.1 sysbench
#./bin/sysbench –test= [options]…
3.1.1 sysbench
(2) command參數
3.1.1 ycsb
#./bin/ycsb command database [options]
(1) options參數
(2) command參數
4.1 測試目的
在大數據環境下,對比MySQL 5.5.40與MongoDB 3.0.7的只讀、只更新、只插入,混合模式(讀:寫=3:7)下的平均時延、吞吐量.
4.2 測試環境
4.3 測試過程
測試的數據量變量名假定為size,分別取值為200w、400w、600w、800w、1000w.
每次使用單進程對單個表壓測,每個表均含有4個字段,每次壓測時間不超過30分鐘.
為了讓數據更加符合我們想要的結果,每輪測試完成后,我們都重啟mysqld和mongodb實例,并且用下面的方法刪除系統cache,釋放swap.
#sync — 將臟數據刷新到磁盤
#echo 3 > /proc/sys/vm/drop_caches — 清除OS Cache
#swapoff -a && swapon -a
4.3.1 sysbench
4.3.1.1 準備工作
(1) 創建測試庫
mysql> drop database if exists sysbench_test;
mysql> create database if not exists sysbench_test character set utf8 collate utf8_general_ci;
(2) 查看表結構
`id` int(10) unsigned NOT NULL auto_increment,
`k` int(10) unsigned NOT NULL default ‘0’,
`c` char(120) NOT NULL default ”,
`pad` char(60) NOT NULL default ”,
PRIMARY KEY (`id`),
KEY `k` (`k`));
4.3.1.2 只讀測試
測試命令:
# ./bin/sysbench –db-driver=mysql –test=oltp.lua –num-threads=1 \
–oltp_tables_count=1 –oltp-table-size=${size} –report-interval=10 \
–oltp-dist-type=uniform –rand-init=on –max-requests=0 \
–oltp-test-mode=nontrx –oltp-nontrx-mode=select \
–oltp-read-only=on –oltp-skip-trx=on –mysql-table-engine=innodb \
–mysql-socket=/tmp/mysql.sock –mysql-user=root –mysql-host=localhost \
–mysql-password=`cat /data/save/mysql_root` –mysql-port=3306 \
–mysql-db=sysbench_test [ prepare | run | cleanup ]
4.3.1.3 只更新測試
測試命令:
#./bin/sysbench –db-driver=mysql –test=./share/sysbench/update_index.lua \
–num-threads=1 –oltp_tables_count=1 –oltp-table-size=${size} –report-interval=10 \
–oltp-dist-type=uniform –rand-init=on –max-requests=0 \
–oltp-read-only=off –mysql-table-engine=innodb –mysql-socket=/tmp/mysql.sock \
–mysql-user=root –mysql-host=localhost –mysql-password=`cat /data/save/mysql_root` \
–mysql-port=3306 –mysql-db=sysbench_test [ prepare | –max-time=1800 run | cleanup ]
4.3.1.4 只插入測試
測試命令:
#./bin/sysbench –db-driver=mysql –test=./share/sysbench/insert.lua –num-threads=1 \
–oltp_tables_count=1 –oltp-table-size=${size} –report-interval=10 \
–oltp-dist-type=uniform –rand-init=on –max-requests=0 –oltp-read-only=off \
–mysql-table-engine=innodb –mysql-socket=/tmp/mysql.sock –mysql-user=root \
–mysql-host=localhost –mysql-password=`cat /data/save/mysql_root` –mysql-port=3306 \
–mysql-db=sysbench_test [ prepare | –max-time=1800 run | cleanup ]
4.3.1.5 混合模式測試
測試命令:
#./bin/sysbench –test=./share/sysbench/oltp.lua –mysql-host=localhost –mysql-port=3306 \
–mysql-user=root –mysql-password=`cat /data/save/mysql_root` \
–mysql-db=sysbench_test –mysql-table-engine=innodb \
–oltp-table-size=${size} –report-interval=10 –rand-init=on –max-requests=0 \
–oltp-read-only=off –oltp-point-selects=$((size/3)) –oltp-point-inserts=$((size/3)) \
–oltp-index-updates=$((size/3)) –num-threads=1 –mysql-ignore-errors=all \
–oltp-skip-trx=off –oltp_tables_count=1 [ prepare | –max-time=1800 run | cleanup ]
參數含義請參考上面的使用說明章節.
4.3.2 ycsb
4.3.2.1 準備工作
編輯workload文件,分別修改readproportion、updateproportion、insertproportion為相應的值并分別命名為workload_select、workload_update、workload_insert、workload_complex比如只讀測試workload_select文件內容:
workload=com.yahoo.ycsb.workloads.CoreWorkload
recordcount=${size}
operationcount=${size}
insertstart=0
fieldcount=4
fieldlength=100
readallfields=true
writeallfields=false
fieldlengthdistribution=zipfian
readproportion=1
updateproportion=0
insertproportion=0
requestdistribution=zipfian
table=ycsb_test
maxexecutiontime=1800
4.3.2.2 只讀測試
測試命令:
./bin/ycsb load mongodb -s -threads 1 -P workloads/workload_select
./bin/ycsb run mongodb -s -threads 1 -P workloads/workload_select
4.3.2.3 只更新測試
測試命令:
./bin/ycsb load mongodb -s -threads 1 -P workloads/workload_update
./bin/ycsb run mongodb -s -threads 1 -P workloads/workload_update
4.3.2.4 只插入測試
測試命令:
./bin/ycsb load mongodb -s -threads 1 -P workloads/workload_insert
./bin/ycsb run mongodb -s -threads 1 -P workloads/workload_insert
4.3.2.5 混合模式測試
測試命令:
./bin/ycsb load mongodb -s -threads 1 -P workloads/workload_complex
./bin/ycsb run mongodb -s -threads 1 -P workloads/workload_complex
參數含義請參考上面的使用說明章節.
4.4 測試結果
圖4.1 《吞吐量:單位時間內的操作數》
圖4.2 《平均時延:每次操作所消耗的平均時間》
PS:MongoDB在讀取的場景有著天生的優勢,每秒的Select操作數遠遠超越MySQL.
圖4.3 《吞吐量:單位時間內的操作數》
圖4.4 《平均時延:每次操作所消耗的平均時間》
PS:上圖看出MongoDB在200W記錄的時候,性能較接近MySQL,但是隨著數據量越大性能劇降,而MySQL卻相對較為穩定.同時MySQL的性能要好于MongoDB 2倍.
圖4.5 《吞吐量:單位時間內的操作數》
圖4.6 《平均時延:每次操作所消耗的平均時間》
PS:上圖中MongoDB在300W記錄前性能要優于MySQL,但是隨著數據量越大性能急劇下降,到1000W記錄時已經無法與MySQL競爭了.這里也反應出MySQL不愧是優秀的數據庫,非常穩定,而MongoDB很不穩定.另外,以上測試中MongoDB都是指定了_id插入的,其效率比不指定_id相差很遠.這是因為它的_id通過計算機特征值、時間、進程ID與隨機數來確保生成的_id是唯一的,每次插入都需要檢查該_id是否存在,所以嚴重影響其效率.當然如果業務允許,你也可以不指定_id插入,提高性能.
圖4.7 《吞吐量:單位時間內的操作數》
圖4.8 《平均時延:每次操作所消耗的平均時間》
PS:以上混合模式是主要模擬了游戲的實際場景(寫為主),結合前面的分步測試結果,這里MongoDB比MySQL性能相差至少4倍,會不會感到理所當然?
通過以上測試發現MySQL和MongoDB各有優勢,因此我們給出如下建議作為參考,具體選擇哪款數據庫請根據自身業務場景來決定.
(1) 相比較MySQL,MongoDB數據庫更適合那些讀作業較重的任務模型.MongoDB能充分利用機器的內存資源.如果機器的內存資源豐富的話,MongoDB的查詢效率會快很多.
(2) 相比MongoDB,MySQL數據庫更適合插入、更新為主的任務模型,其效率相比于MongoDB優勢非常明顯.
(3) 在帶”_id”插入數據的時候,MongoDB的插入效率其實并不高.如果想充分利用MongoDB性能的話,推薦采取不帶”_id”的插入方式,然后對相關字段作索引來查詢.
(4) MongoDB適合那些對數據庫具體數據格式不明確或者數據庫數據格式經常變化的需求模型,而且對開發者十分友好.
(5) 穩定性方面,MongoDB不如MySQL,MySQL不愧是一種非常穩定的數據庫,無論在指定主鍵還是在不指定主鍵插入的情況下,其效率都差不了太多, 其穩定性還是毋庸置疑.
(6) 事務支持方面,MySQL占絕對優勢,MongoDB對事務關系支持薄弱,這也是所有NoSQL數據庫共同的缺陷,不過NoSQL并不是為了事務關系而設計的,具體應用還是很需求.
結合我們的游戲業務場景來看,選用MySQL無疑是最理想的選擇.但是有時候我們的游戲數據分析后臺需要做很大量的統計、展示,這對讀取性能要求較高,如果同時能夠結合MongoDB的來提升讀取性能可能更有利于業務的擴展性.主要是把用戶主數據寫到MySQL,用戶日志類數據寫到MongoDB,然后游戲數據分析后臺直接讀取MongoDB做統計分析工作.
1) https://github.com/brianfrankcooper/YCSB
2) http://seanlook.com/2016/03/28/mysql-sysbench
原文來自微信公眾號:運維軍團
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/4276.html