# 創建MyCat配置文件,主要包括rule.xml和schema.xml rule.xml中加入 |
<tableRule name="sharding-by-date"> <rule> <columns>CREATE_TIME</columns> <algorithm>sharding-by-date</algorithm> </rule> </tableRule> <function name="sharding-by-date" class="io.mycat.route.function.PartitionByDate"> <property name="dateFormat">yyyy-MM-dd</property> <!--日期格式--> <property name="sBeginDate">2017-06-01</property> <!--開始日期--> <property name="sEndDate">2017-06-15</property> <property name="sPartionDay">1</property> <!--每分片天數--> </function> |
<?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://io.mycat/"> <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100"> <!-- auto sharding by id (long) --> <table name="log" dataNode="dn11,dn12,dn13,dn14,dn15,dn21,dn22,dn23,dn24,dn25,dn31,dn32,dn33,dn34,dn35" rule="sharding-by-date"/> <table name="mac" primaryKey="mac" type="global" dataNode="dn11" /> </schema> <dataNode name="dn11" dataHost="host1" database="db1" /> <dataNode name="dn12" dataHost="host1" database="db2" /> <dataNode name="dn13" dataHost="host1" database="db3" /> <dataNode name="dn14" dataHost="host1" database="db4" /> <dataNode name="dn15" dataHost="host1" database="db5" /> <dataNode name="dn21" dataHost="host2" database="db1" /> <dataNode name="dn22" dataHost="host2" database="db2" /> <dataNode name="dn23" dataHost="host2" database="db3" /> <dataNode name="dn24" dataHost="host2" database="db4" /> <dataNode name="dn25" dataHost="host2" database="db5" /> <dataNode name="dn31" dataHost="host3" database="db1" /> <dataNode name="dn32" dataHost="host3" database="db2" /> <dataNode name="dn33" dataHost="host3" database="db3" /> <dataNode name="dn34" dataHost="host3" database="db4" /> <dataNode name="dn35" dataHost="host3" database="db5" /> <dataHost name="host1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!-- can have multi write hosts --> <writeHost host="host1" url="10.10.10.221:3307" user="root" password="root"></writeHost> </dataHost> <dataHost name="host2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!-- can have multi write hosts --> <writeHost host="host2" url="10.10.10.222:3307" user="root" password="root"></writeHost> </dataHost> <dataHost name="host3" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!-- can have multi write hosts --> <writeHost host="host3" url="10.10.10.223:3307" user="root" password="root"></writeHost> </dataHost> </mycat:schema> |
# 創建所需服務和數據庫 參見 使用Docker部署基於MyCat的MySql https://internal-confluence.ssgm.net/pages/viewpage.action?pageId=1736724 注意,要在3臺服務器上各創建一個服務,每個服務內建立5個數據庫,與上一步中的配置相對應 |
# 創建所需表 連接MyCat的服務,創建表;其中,log爲數據表,mac中保存幾百條mac記錄,用以批量生成測試數據 |
DROP TABLE IF EXISTS `log`; CREATE TABLE `log` ( `id` varchar(36) NOT NULL, `mac` varchar(17) DEFAULT '', `CREATE_TIME` datetime NOT NULL, `terminal_field_strength` varchar(8) DEFAULT '', `ssid_position` varchar(256) DEFAULT '', `access_ap_mac` varchar(17) DEFAULT '', `access_ap_channel` varchar(6) DEFAULT '', `access_ap_encryption_type` varchar(2) DEFAULT '', `x_coordinate` varchar(8) DEFAULT '', `y_coordinate` varchar(8) DEFAULT '', `netbar_wacode` varchar(14) DEFAULT '', `collection_equipment_id` varchar(21) DEFAULT '', `collection_equipment_longitude` varchar(15) DEFAULT '', `collection_equipment_latitude` varchar(15) DEFAULT '', `security_software_orgcode` varchar(10) DEFAULT '', KEY `index_time_mac` (`CREATE_TIME`,`mac`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `mac`; CREATE TABLE `mac` ( `mac` varchar(255) CHARACTER SET utf8 DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; |
# 創建測試數據 由於需要大量的測試數據,因此我們通過輔助表mac和存儲過程來批量插入數據 單獨連接每臺服務器上的MySQL進程,依次切換到db1-db5,導入mac.sql文件,並創建相應的存儲過程 注意,存儲過程創建時要針對當前數據庫修改參數值,讓指定數據庫插入指定日期的數據,否則會導致MyCat查詢不到 創建完存儲過程後,依次在每個庫上執行 call bat();每個庫會插入390萬條記錄 |
CREATE PROCEDURE bat() BEGIN DECLARE v_start datetime DEFAULT STR_TO_DATE('2017-06-01','%Y-%m-%d'); -- 這裏的日期要修改,規則爲 第一臺服務器db1 2017-06-01,db2 2017-06-02,...,第2臺服務器 db1 2017-06-06 .... DECLARE v_sec INT DEFAULT 0; DECLARE v_step INT DEFAULT 3; DECLARE v_size INT DEFAULT 13000; -- mac有300條記錄,插入13000次,總計390萬左右記錄 WHILE v_sec<v_size DO SET v_sec=v_sec+v_step; INSERT INTO log(`id`, `mac`, `CREATE_TIME`, `terminal_field_strength`, `netbar_wacode`, `collection_equipment_id`, `collection_equipment_longitude`, `collection_equipment_latitude`, `security_software_orgcode`) SELECT uuid(),mac,DATE_ADD(v_start,INTERVAL v_sec SECOND),'-96','3712032E000001', '7855129960034CB64CBAE', '117.849381', '36.08163', '785512996' FROM mac ; END WHILE; END ; |
# 測試 連接單獨的數據庫可以測試單數據庫的效率,連接MyCat服務可以測試集羣效率 |
# 測試結果及總結說明 爲處理大數據量情況下數據庫查詢緩慢的問題,搭建MyCat分片集羣,以提高查詢性能 基本測試情況參見文件MyCat測試.xlsx 大數據量查詢的時候,需要進行分頁操作,而此時進行的查詢主要有兩個: 1.查詢具體數據 2.統計所有記錄數,用於前端生成頁碼 其中,主要有以下問題: 前提:數據量大7000萬左右,單庫單表,使用表內分區 1. a.當建立合適的索引時,並限定合適的查詢條件,查詢單頁幾十條數據且跳過的記錄數不是很多時,查詢時間仍在100毫秒以內,因此性能不是問題 b.當a中,跳過的記錄比較多時,如1500萬,耗時大概在11秒左右,已經不可接受 2. count()函數是最耗時的地方.概括說來,單庫情況下,每秒大概可以統計220萬左右記錄,在使用了MyCat中間件後,性能降爲150萬左右/秒, 整體來看,三臺服務器,每臺上面跑5個MySql進程,count()的性能達到1139萬/秒,爲單進程的5倍左右; 從現象來看,MyCat的查詢性能受限於數據量最大,耗時最長的分片,因此應該限制單個分片數據量大小 總結: 使用MyCat,可以做到根據日期進行分片; 要想查詢保持在三四秒左右,每個分片的數據量應保持在最大五六百萬左右 以上測試基於4G內存,每臺計算機上啓動5個MySql進程,沒有對MySql進行參數調整的情況下, 理論上猜想,通過增加機器配置,增加實體機數量,以及通過參數調優,還可以有效提高數據庫性能 另外,此次測試沒有使用merge分區表,猜想如果單庫以日期分,庫內表以小時進行分區,在精確時間查詢的時候應該還會有效提高查詢效率 索引策略: 表結構:mac,enter_time,update_time 寫庫:(mac,update_time) 插入新數據時,如果庫裏有相同mac,ap的n分鐘內的記錄,直接更新該記錄的update_time,否則插入新的記錄 讀庫:依照具體查詢來定,例如(phone,enter_time),(mac,enter_time),(enter_time) |
# 創建MyCat配置文件,主要包括rule.xml和schema.xml rule.xml中加入 |
<tableRule name="sharding-by-date"> <rule> <columns>CREATE_TIME</columns> <algorithm>sharding-by-date</algorithm> </rule> </tableRule> <function name="sharding-by-date" class="io.mycat.route.function.PartitionByDate"> <property name="dateFormat">yyyy-MM-dd</property> <!--日期格式--> <property name="sBeginDate">2017-06-01</property> <!--開始日期--> <property name="sEndDate">2017-06-15</property> <property name="sPartionDay">1</property> <!--每分片天數--> </function> |
<?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://io.mycat/"> <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100"> <!-- auto sharding by id (long) --> <table name="log" dataNode="dn11,dn12,dn13,dn14,dn15,dn21,dn22,dn23,dn24,dn25,dn31,dn32,dn33,dn34,dn35" rule="sharding-by-date"/> <table name="mac" primaryKey="mac" type="global" dataNode="dn11" /> </schema> <dataNode name="dn11" dataHost="host1" database="db1" /> <dataNode name="dn12" dataHost="host1" database="db2" /> <dataNode name="dn13" dataHost="host1" database="db3" /> <dataNode name="dn14" dataHost="host1" database="db4" /> <dataNode name="dn15" dataHost="host1" database="db5" /> <dataNode name="dn21" dataHost="host2" database="db1" /> <dataNode name="dn22" dataHost="host2" database="db2" /> <dataNode name="dn23" dataHost="host2" database="db3" /> <dataNode name="dn24" dataHost="host2" database="db4" /> <dataNode name="dn25" dataHost="host2" database="db5" /> <dataNode name="dn31" dataHost="host3" database="db1" /> <dataNode name="dn32" dataHost="host3" database="db2" /> <dataNode name="dn33" dataHost="host3" database="db3" /> <dataNode name="dn34" dataHost="host3" database="db4" /> <dataNode name="dn35" dataHost="host3" database="db5" /> <dataHost name="host1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!-- can have multi write hosts --> <writeHost host="host1" url="10.10.10.221:3307" user="root" password="root"></writeHost> </dataHost> <dataHost name="host2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!-- can have multi write hosts --> <writeHost host="host2" url="10.10.10.222:3307" user="root" password="root"></writeHost> </dataHost> <dataHost name="host3" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!-- can have multi write hosts --> <writeHost host="host3" url="10.10.10.223:3307" user="root" password="root"></writeHost> </dataHost> </mycat:schema> |
# 創建所需服務和數據庫 參見 使用Docker部署基於MyCat的MySql https://internal-confluence.ssgm.net/pages/viewpage.action?pageId=1736724 注意,要在3臺服務器上各創建一個服務,每個服務內建立5個數據庫,與上一步中的配置相對應 |
# 創建所需表 連接MyCat的服務,創建表;其中,log爲數據表,mac中保存幾百條mac記錄,用以批量生成測試數據 |
DROP TABLE IF EXISTS `log`; CREATE TABLE `log` ( `id` varchar(36) NOT NULL, `mac` varchar(17) DEFAULT '', `CREATE_TIME` datetime NOT NULL, `terminal_field_strength` varchar(8) DEFAULT '', `ssid_position` varchar(256) DEFAULT '', `access_ap_mac` varchar(17) DEFAULT '', `access_ap_channel` varchar(6) DEFAULT '', `access_ap_encryption_type` varchar(2) DEFAULT '', `x_coordinate` varchar(8) DEFAULT '', `y_coordinate` varchar(8) DEFAULT '', `netbar_wacode` varchar(14) DEFAULT '', `collection_equipment_id` varchar(21) DEFAULT '', `collection_equipment_longitude` varchar(15) DEFAULT '', `collection_equipment_latitude` varchar(15) DEFAULT '', `security_software_orgcode` varchar(10) DEFAULT '', KEY `index_time_mac` (`CREATE_TIME`,`mac`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `mac`; CREATE TABLE `mac` ( `mac` varchar(255) CHARACTER SET utf8 DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; |
# 創建測試數據 由於需要大量的測試數據,因此我們通過輔助表mac和存儲過程來批量插入數據 單獨連接每臺服務器上的MySQL進程,依次切換到db1-db5,導入mac.sql文件,並創建相應的存儲過程 注意,存儲過程創建時要針對當前數據庫修改參數值,讓指定數據庫插入指定日期的數據,否則會導致MyCat查詢不到 創建完存儲過程後,依次在每個庫上執行 call bat();每個庫會插入390萬條記錄 |
CREATE PROCEDURE bat() BEGIN DECLARE v_start datetime DEFAULT STR_TO_DATE('2017-06-01','%Y-%m-%d'); -- 這裏的日期要修改,規則爲 第一臺服務器db1 2017-06-01,db2 2017-06-02,...,第2臺服務器 db1 2017-06-06 .... DECLARE v_sec INT DEFAULT 0; DECLARE v_step INT DEFAULT 3; DECLARE v_size INT DEFAULT 13000; -- mac有300條記錄,插入13000次,總計390萬左右記錄 WHILE v_sec<v_size DO SET v_sec=v_sec+v_step; INSERT INTO log(`id`, `mac`, `CREATE_TIME`, `terminal_field_strength`, `netbar_wacode`, `collection_equipment_id`, `collection_equipment_longitude`, `collection_equipment_latitude`, `security_software_orgcode`) SELECT uuid(),mac,DATE_ADD(v_start,INTERVAL v_sec SECOND),'-96','3712032E000001', '7855129960034CB64CBAE', '117.849381', '36.08163', '785512996' FROM mac ; END WHILE; END ; |
# 測試 連接單獨的數據庫可以測試單數據庫的效率,連接MyCat服務可以測試集羣效率 |
# 測試結果及總結說明 爲處理大數據量情況下數據庫查詢緩慢的問題,搭建MyCat分片集羣,以提高查詢性能 基本測試情況參見文件MyCat測試.xlsx 大數據量查詢的時候,需要進行分頁操作,而此時進行的查詢主要有兩個: 1.查詢具體數據 2.統計所有記錄數,用於前端生成頁碼 其中,主要有以下問題: 前提:數據量大7000萬左右,單庫單表,使用表內分區 1. a.當建立合適的索引時,並限定合適的查詢條件,查詢單頁幾十條數據且跳過的記錄數不是很多時,查詢時間仍在100毫秒以內,因此性能不是問題 b.當a中,跳過的記錄比較多時,如1500萬,耗時大概在11秒左右,已經不可接受 2. count()函數是最耗時的地方.概括說來,單庫情況下,每秒大概可以統計220萬左右記錄,在使用了MyCat中間件後,性能降爲150萬左右/秒, 整體來看,三臺服務器,每臺上面跑5個MySql進程,count()的性能達到1139萬/秒,爲單進程的5倍左右; 從現象來看,MyCat的查詢性能受限於數據量最大,耗時最長的分片,因此應該限制單個分片數據量大小 總結: 使用MyCat,可以做到根據日期進行分片; 要想查詢保持在三四秒左右,每個分片的數據量應保持在最大五六百萬左右 以上測試基於4G內存,每臺計算機上啓動5個MySql進程,沒有對MySql進行參數調整的情況下, 理論上猜想,通過增加機器配置,增加實體機數量,以及通過參數調優,還可以有效提高數據庫性能 另外,此次測試沒有使用merge分區表,猜想如果單庫以日期分,庫內表以小時進行分區,在精確時間查詢的時候應該還會有效提高查詢效率 索引策略: 表結構:mac,enter_time,update_time 寫庫:(mac,update_time) 插入新數據時,如果庫裏有相同mac,ap的n分鐘內的記錄,直接更新該記錄的update_time,否則插入新的記錄 讀庫:依照具體查詢來定,例如(phone,enter_time),(mac,enter_time),(enter_time) |