基于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)
	

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