zoukankan      html  css  js  c++  java
  • apache ignite系列(九):使用ddl和dml脚本初始化ignite并使用mybatis查询缓存

    博客又断了一段时间,本篇将记录一下基于ignite对jdbc支持的特性在实际使用过程中的使用。

    使用ddl和dml脚本初始化ignite

    由于spring-boot中支持通过spring.datasource.schema属性指定初始化DDL脚本,spring.datasource.data指定初始化DML脚本。而ignite支持jdbc协议,测试了一下,发现一样可以通过该配置初始化ignite。

    spring.datasource.url=jdbc:ignite:thin://127.0.0.1/
    spring.datasource.driver-class-name=org.apache.ignite.IgniteJdbcThinDriver
    spring.datasource.schema=classpath:db/schema.sql
    spring.datasource.data=classpath:db/data.sql
    

    说明ignite数据源同样可以作为一个DataSource实例。

    DDL的规范

    创建表

    CREATE TABLE [IF NOT EXISTS] tableName (tableColumn [, tableColumn]...
    [, PRIMARY KEY (columnName [,columnName]...)])
    [WITH "paramName=paramValue [,paramName=paramValue]..."]
    

    WITH语法中支持的选项以及含义如下(可参见xml配置中CacheConfiguration的相关配置):

    参数 含义
    TEMPLATE 缓存模式:PARTITIONED或者REPLICATED
    BACKUPS 备份数量
    ATOMICITY 原子模式:ATOMIC或者TRANSACTIONAL
    CACHEGROUP 缓存组名
    AFFINITYKEY 并置键列名
    CACHE_NAME 缓存名(如果不设置的话默认会加SQL_前缀)
    KEY_TYPE 键类型
    VALUE_TYPE 值类型
    DATA_REGION 内存区名

    创建索引

    CREATE [SPATIAL] INDEX [[IF NOT EXISTS] indexName] ON tableName
        (columnName [ASC|DESC] [,...]) [(index_option [...])]
    

    示例:

    schema.sql

    --student学生信息表
    CREATE TABLE IF NOT EXISTS PUBLIC.STUDENT (
     STUDID INTEGER,
     NAME VARCHAR,
     EMAIL VARCHAR,
     dob Date,
     PRIMARY KEY (STUDID))
    WITH "template=replicated,atomicity=ATOMIC,cache_name=student";
    
    CREATE INDEX IF NOT EXISTS STUDENT_NE_INDEX ON PUBLIC.STUDENT (NAME, EMAIL);
    
    -- grade成绩表
    CREATE TABLE IF NOT EXISTS PUBLIC.GRADE (
     STUDID INTEGER,
     grade DOUBLE,
     PRIMARY KEY (STUDID))
    WITH "template=replicated,atomicity=ATOMIC,cache_name=grade";
    

    DML规范

    ignite中dml与标准sql中的基本一致示例如下:

    INSERT INTO student (studid, name, email, dob) VALUES (1, 'student_1', 'student_1gmail.com', '2017-09-28');
    

    完整dml初始化脚本:

    -- student
    INSERT INTO student (studid, name, email, dob) VALUES (1, 'student_1', 'student_1gmail.com', '2017-09-28');
    INSERT INTO student (studid, name, email, dob) VALUES (2, 'student_2', 'student_2gmail.com', '2017-09-28');
    ...
    
    --grade
    INSERT INTO grade (studid, grade) VALUES (1,  3);
    INSERT INTO grade (studid, grade) VALUES (2,  64);
    ...
    

    注:如果使用了KEY_TYPE选项配置自定义KEY类型,那么要么在自定义类型中得有对应的构造方法,要么使用java内置类型的时候,insert语句必须带上_key字段的值。

    例如:
    ddl语句中with选项为

    WITH "template=replicated,atomicity=ATOMIC,cache_name=student,key_type=java.lang.Long";

    那么dml语句就得像下面这么写

    INSERT INTO student (_key, studid, name, email, dob) VALUES (1, '1', 'student_1', 'student_1gmail.com', '2017-09-28');

    初始化完成后可通过监控程序看到如下监控情况 :

    ddl+dml

    可以发现缓存和数据均已初始化成功。

    使用Mybatis查询ignite缓存

    由于ignite可以作为DataSource的实例,所以猜想应该也可以通过Mybatis去查询ignite,这样可以替代原来需要SqlFieldsQuery查询并对结果进行逐行解析的方式。经验证后发现ignite能完美支持myabtis,所以在查询ignite的方式上有了一个更便捷的方式。

    与普通使用mybatis的方式一样,定义IgniteMapper.xmlIgniteMapper.java

    IgniteMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="org.cord.ignite.data.mapper.IgniteMapper">
    
        <resultMap type="org.cord.ignite.data.domain.Student" id="StudentResult">
            <result property="studId" column="studid"/>
            <result property="name" column="name"/>
            <result property="email" column="email"/>
            <result property="dob" column="dob"/>
        </resultMap>
    
        <select id="findStudentsById" parameterType="java.lang.String" resultMap="StudentResult">
            SELECT * FROM student WHERE studid = #{studentId}
        </select>
    
        <select id="findGradeByName" parameterType="java.lang.String" resultType="java.lang.Double">
            SELECT g.grade FROM student s,grade g WHERE s.STUDID=g.STUDID and s.name= #{name}
        </select>
    
    </mapper>
    

    IgniteMapper.java

    public interface IgniteMapper {
    
        /**
         * 根据studentId查询学生信息
         * @param studentId
         * @return Student
         */
        Student findStudentsById(String studentId);
    
        /**
         * 根据学生姓名查询学生分数
         * @param name
         * @return 学生分数
         */
        Double findGradeByName(String name);
    }
    

    查询:

      	...
      	@Autowired
        private IgniteMapper igniteMapper;
        ...
        Student student = igniteMapper.findStudentsById(studentId);
        ...
        double grade = igniteMapper.findGradeByName(name);
    

    注:由于ignite中可以自定义sql函数,测试过,在mybatis中ignite的自定义sql函数同样支持。

    性能

    由于ignite中jdbc的方式属于轻客户端,所以性能要比api的方式差,而在通过mybatis查询的方式其性能表现通过测试得出的结果如下:

    在相同的sql相同数据的情况下,100并发查询:

    mybatis查询

    /findStudentsById 耗时 [13]ms.
    /findStudentsById 耗时 [9]ms.
    /findStudentsById 耗时 [3]ms.
    /findStudentsById 耗时 [10]ms.
    /findStudentsById 耗时 [11]ms.
    /findStudentsById 耗时 [11]ms.
    /findStudentsById 耗时 [13]ms.
    /findStudentsById 耗时 [8]ms.
    /findStudentsById 耗时 [8]ms.
    /findStudentsById 耗时 [14]ms.
    /findStudentsById 耗时 [17]ms.
    /findStudentsById 耗时 [11]ms.
    /findStudentsById 耗时 [8]ms.
    /findStudentsById 耗时 [13]ms.
    /findStudentsById 耗时 [11]ms.
    /findStudentsById 耗时 [10]ms.
    /findStudentsById 耗时 [9]ms.
    /findStudentsById 耗时 [10]ms.
    /findStudentsById 耗时 [12]ms.
    /findStudentsById 耗时 [9]ms.
    /findStudentsById 耗时 [3]ms.
    /findStudentsById 耗时 [3]ms.
    ...
    /findStudentsById 耗时 [1]ms.
    /findStudentsById 耗时 [2]ms.
    /findStudentsById 耗时 [2]ms.
    /findStudentsById 耗时 [2]ms.
    /findStudentsById 耗时 [2]ms.
    /findStudentsById 耗时 [2]ms.
    /findStudentsById 耗时 [2]ms.
    /findStudentsById 耗时 [2]ms.
    /findStudentsById 耗时 [1]ms.
    /findStudentsById 耗时 [1]ms.
    /findStudentsById 耗时 [1]ms.
    /findStudentsById 耗时 [0]ms.
    

    吞吐量为537/sec, 性能有波动情况,稳定后在2ms左右。

    api查询

    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [1]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [1]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [0]ms.
    /cpFindStudentsById 耗时 [0]ms.
    

    吞吐量为1256/sec,性能比较稳定,稳定后在1ms以内。

    完整代码请参考https://github.com/cording/ignite-example

    结论

    ​ 对于不是要求极限性能的场景,mybatis查询方式完全能满足,这使得对于很多现有基于myabtis的项目代码,能相对平滑的使用ignite作为加速层,而又不用做过多改动。

    ​ 还有,写博客确实有点费时间....................

  • 相关阅读:
    Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?
    "=="和equals方法究竟有什么区别?
    Tomcat发生java.lang.OutOfMemoryError: PermGen space的解决方案
    HashMap原理
    springMVC
    SqlServer和Oracle修改表结构语句
    quartz定时任务时间表达式说明
    Linq to Entity 时间差作为筛选条件产生的问题
    密码学基础
    C#如何使用异步编程【BeginInvoke/EndInvoke】
  • 原文地址:https://www.cnblogs.com/cord/p/10293813.html
Copyright © 2011-2022 走看看