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,key_type=java.lang.Long"; 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,key_type=java.lang.Long";
DML規範
ignite中 dml
與標準sql中的基本一致,唯一區別在於ignite中底層是KV結構,所以 insert
語句可以處理key對應的值。示例如下:
INSERT INTO student (_key, studid, name, email, dob) VALUES (1, '1', 'student_1', 'student_1gmail.com', '2017-09-28');
完整dml初始化指令碼:
-- student INSERT INTO student (_key, studid, name, email, dob) VALUES (1, '1', 'student_1', 'student_1gmail.com', '2017-09-28'); INSERT INTO student (_key, studid, name, email, dob) VALUES (2, '2', 'student_2', 'student_2gmail.com', '2017-09-28'); ... --grade INSERT INTO grade (_key, studid, grade) VALUES (1, '1',3); INSERT INTO grade (_key, studid, grade) VALUES (2, '2',64); ...
初始化完成後可通過監控程式看到如下監控情況 :
可以發現快取和資料均已初始化成功。
使用Mybatis查詢ignite快取
由於ignite可以作為 DataSource
的例項,所以猜想應該也可以通過Mybatis去查詢ignite,這樣可以替代原來需要 SqlFieldsQuery
查詢並對結果進行逐行解析的方式。經驗證後發現ignite能完美支援myabtis,所以在查詢ignite的方式上有了一個更便捷的方式。
與普通使用mybatis的方式一樣,定義 IgniteMapper.xml
和 IgniteMapper.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作為加速層,而又不用做過多改動。
還有,寫部落格確實有點費時間....................