执行读取大量数据SQL执行一段时间就不执行了?
MyCat的默认SQL执行超时时间是300S(5分钟),需要调整MyCat的配置文件server.xml的配置。
<system>
<!--sql超时,单位秒-->
<property name="sqlExecuteTimeout">1800</property>
</system>
ER分片子表的路由规则
一、如果子表与父表的关联字段是父表的分片字段
<!--使用orders表的主键user_id进行分片-->
<table name="orders" dataNode="dn1,dn2" rule="mod-long" needAddLimit="false" >
<!-- 关联分片字段 -->
<childTable name="order_items" primaryKey="order_items_id" joinKey="order_id" parentKey="order_id" />
</table>
- 在对子表进行update时(根据主键),会向所有节点发送sql语句。
- 字表的分片规则则按照父表进行分片
- 查询字表时,如果根据字表的主键来查,会被路由到所有节点(此时应该保证子表在所有分片是主键唯一的)
- 如果根据父节点的分片字段(joinKey)来进行查询,会根据父表的路由规则进行查询。字表与父表进行join查询时也会走父表的路由。
二、当子表与父表的关联字段不是父表的分片字段时,
<!--根据orders表的地域编码area_code来分片-->
<table name="orders" dataNode="dn1,dn2" rule="mod-long" needAddLimit="false" >
<!-- 关联非分片字段 -->
<childTable name="user_items" primaryKey="user_iterm_id" joinKey="order_id" parentKey="order_id" />
</table>
- 子表的分片规则是根据父表的parentKey所在的分片区域进行分片。
- 对字表进行update语句(通过主键ID或者parentKey)时会向所有节点发送sql,因为无法确定父节点的分片信息。
- 必须通过查找对应的父表记录来确认子表所在分片,如果找不到则会抛出错误,在join查询的时候,路由走的是所有分片节点。
- 非主键的分片,MyCAT 提供了“主键到分片”的内存缓存机制,热点数据按照主键查询,丝毫不损失性能。
MyCat数据导入与导出
一、导出
导出分片数据最好是到每个分片节点去导出,然后进行合并,避免数据冲突。
二、导入
导入大量的分片数据可以使用 select * from table into outfile
命令从需要备份的mysql数据库导出数据。然后用命令行工具连接到MyCat,并执行 “load data infile ` 命令来导入分片数据。
多对多关联关系
业务中往往存在多对多
的关联关系,比如:商户会员+订单+商户
,这时分片的策略往往是根据业务需求、性能差异来决定的(多表join)。如果需要获取会员所有的商户订单,并且依赖会员表的业务关系较多这时就可以考虑使用会员表分片。反之则相反。
ER分片子表update操作
ER分片,对childTabe进行update时、不能更新joinKey ,会报:Parent relevant column cant’t be update …….。很多框架更新默认都会根据主键更新所有字段,可以说这是很坑的地方,需要对sql进行重写。。
非主键分片性能优化
对于某些场景下,可能分片的字段不是主键。主键分片也并非是唯一的选择。
该业务字段是最频繁的或者最重要的查询条件。
将数据尽可能均匀分布的各个节点
<!--配置了primaryKey 会缓存非主键分片的映射--> <table name="orders" primaryKey="order_id" dataNode="dn1,dn2" rule="mod-long" needAddLimit="false" > <!-- 关联非分片字段 --> <childTable name="user_items" primaryKey="user_iterm_id" joinKey="order_id" parentKey="order_id" /> </table>
这种情况下MyCAT 提供了“主键到分片”的内存缓存机制,热点数据按照主键查询,不用担心牺牲了主键查询的性能。
对于非主键分片的 table,填写属性
primaryKey
,此时 MyCAT 会将你根据主键查询的 SQL 语句的第一次执 行结果进行分析,确定该 Table 的某个主键在什么分片上,并进行主键到分片 ID 的缓存。第二次或后续查询 mycat 会优先从缓存中查询是否有 id–>node 即主键到分片的映射,如果有直接查询,通过此种方法提高了非主 键分片的查询性能。
MyCat建表和存储过程
MyCat建表需要使用注解语法,如
select 1 from table
,查出来的数据在那个节点往哪个节点执行。
创建存储过程
/*!mycat: sql=select 1 from 表 */ CREATE DEFINER=
root
@%
PROCEDUREproc_test
() BEGIN END ;
建表
/*!mycat: sql=select 1 from 表 */create table ttt(id int);
MyCat性能监控工具——MyCat-Web
MyCat官方提供的性能监控工具,可以对sql进行监控、查询统计、执行时间监控。可以根据监控结果对程序或者配置进行一系列的调整。
点这里下载MyCat-Web,使用方法见解压后的readme.txt。
MyCat快速体验,MyCat官方已经制作好了镜像,集成了一套测试环境,安装VirtualBox导入即可快速体验。
MyCat拆分原则(转自MyCat权威指南)
达到一定数量级才拆分(800 万)
不到 800 万但跟大表(超 800 万的表)有关联查询的表也要拆分,在此称为大表关联表
大表关联表如何拆:小于 100 万的使用全局表;大于 100 万小于 800 万跟大表使用同样的拆分策略;无 法跟大表使用相同规则的,可以考虑从 java 代码上分步骤查询,不用关联查询,或者破例使用全局表。
破例的全局表:如 item_sku 表 250 万,跟大表关联了,又无法跟大表使用相同拆分策略,也做成了全局 表。破例的全局表必须满足的条件:没有太激烈的并发 update,如多线程同时 update 同一条 id=1 的记录。虽 有多线程 update,但不是操作同一行记录的不在此列。多线程 update 全局表的同一行记录会死锁。批量 insert 没问题。
拆分字段是不可修改的。
拆分字段只能是一个字段,如果想按照两个字段拆分,必须新建一个冗余字段,冗余字段的值使用两个字 段的值拼接而成(如大区+年月拼成 zone_yyyymm 字段)。
拆分算法的选择和合理性评判:按照选定的算法拆分后每个库中单表不得超过 800 万
能不拆的就尽量不拆。如果某个表不跟其他表关联查询,数据量又少,直接不拆分,使用单库即可。
开发框架的选择
由于MyCat的兼容性、不能更新分片字段等限制。不建议使用Hibernate框架开发,最好的选择是能控制SQL的框架,比如
MyBatis
、JDBC
,可以针对SQL进行优化。