基於MyCat的按日期分片集羣性能測試



# 創建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)
	

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