ãããã¨
jBatchã使ç¨ãã¦ããã¹ããã¡ã¤ã«ã®ä¸èº«ãOracleã«ãã¼ãããã
ã¨ã¯ãããåãªããã¼ã¿ãã¼ãã§ããã°ã¯ã¶ã¯ã¶jBatchã使ãã®ã¯ãªã¼ãã¼ãããããããã ãã§ãããOracleã§SQL*LoaderããæåãªãSQL DeveloperãA5:SQLçå種ã®ãã¼ã«ã使ãã®ãæã£åãæ©ãã
ãã ããããåç´ãªãã¼ã¿ãã¼ãã®å®è£ ãéãã¦å¦ã¹ããã¨ãå¤ãããã®ã¨ã³ããªã®ç®çã¯ãããåç´ãªãã¼ã¿ãã¼ããéãã¦jBatchã®æåãç¥ããã¨ã«ããã
ãããã¨ã¨ãã¦ã¯ãjBatchã使ç¨ãã¦Oracleã«ãã¼ã¿ããã¼ãããã¾ããããã¤ãã®ãã©ã¡ã¼ã¿ãå¤æ´ãã¦ããã®ã¨ãã®å®è¡æéã®å¤åã確èªããã
ç°å¢
æºå
ãã¼ã¿ãã¼ã対象ã®ãã¼ãã«
DROP TABLE hoge PURGE; CREATE TABLE hoge ( hoge_id INTEGER, hoge_value VARCHAR(20) );
idã¨valueã ãã®ãã¼ãã«ã«ãã¼ã¿ãINSERTãã¦ããã
åæºå
ALTER SYSTEM FLUSH BUFFER_CACHE;
ããããä¸åæµããã¨ã«ãOracleã®ãããã¡ãã£ãã·ã¥ãã¯ãªã¢ãã¦ããã
ãã¼ã¿ãã¼ã対象ã®ããã¹ããã¡ã¤ã«
gvMWxxfOjYsLNgsggALU NEadKxrnnkhWtfQSmyai AhALLooojhwCXzNrsDJk ï¼çç¥ï¼
åè¡20ãã¤ãã30000è¡ãã¾ããpartitionã®ã¨ããã§ã¯å¥é説æã
ã½ã¼ã¹
sample-job-dataload.xml
<?xml version="1.0" encoding="UTF-8"?> <job id="sample-job-partition" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0"> <listeners> <listener ref="executionTimeJobListener"></listener> </listeners> <step id="myStep"> <chunk> <reader ref="myDataloadReader"></reader> <processor ref="myDataloadProcessor"></processor> <writer ref="myDataloadWriter"></writer> </chunk> <partition> <plan partitions="1" threads="1"> <properties partition="0"> <property name="startId" value="1" /> <property name="file" value="C:\\Java\\sampledataload\\input_p_1.txt" /> </properties> </plan> </partition> <end on="COMPLETED" /> </step> </job>
ãããã®å®ç¾©ããã¨ã§ãã¼ãã£ã·ã§ã³ã試ãã®ã§ãããªã£ã¦ãããidã®åæå¤ã¯ããããã£ã§å®ç¾©ããã
persistence.xml
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="glassfish4oracle11gee" transaction-type="JTA"> <jta-data-source>jdbc/oracle11gee</jta-data-source> </persistence-unit> </persistence>
GlassFish4ã§Oracle11gXEã®JDBCæ¥ç¶ãã¤ãã ã¨ãåç §ã«GlassFishã«ãã¼ã¿ã½ã¼ã¹ã®è¨å®ãã¦ãããã®ã¨ããã
SampleDataloadReader
@Dependent @Named("myDataloadReader") public class SampleDataloadReader implements ItemReader { private BufferedReader br; @Inject JobContext jobCtx; @Override public void open(Serializable checkpoint) throws Exception { long execID = jobCtx.getExecutionId(); Properties parameters = BatchRuntime.getJobOperator().getParameters(execID); String inputFile = parameters.getProperty("file"); br = Files.newBufferedReader(Paths.get(inputFile), Charset.defaultCharset()); } @Override public Object readItem() throws Exception { String line = br.readLine(); if (line == null) { return null; } return line; } @Override public void close() throws Exception { br.close(); } @Override public Serializable checkpointInfo() throws Exception { return null; } }
reader. ããã¹ããã¡ã¤ã«ãããã¼ã¿èªãã§ãã ãã
SampleDataloadProcessor
@Dependent @Named("myDataloadProcessor") public class SampleDataloadProcessor implements ItemProcessor { @Override public Object processItem(Object item) throws Exception { return item; } }
processor. å¦çã¯ãªããç¡ãã
SampleDataloadWriter
@Dependent @Named("myDataloadWriter") public class SampleDataloadWriter implements ItemWriter { @PersistenceContext(unitName = "glassfish4oracle11gee") private EntityManager em; @Inject JobContext jobCtx; private int hogeId = 0; private int count = 0; @Override public void open(Serializable checkpoint) throws Exception { long eId = jobCtx.getExecutionId(); String t = BatchRuntime.getJobOperator().getParameters(eId).getProperty("startId"); hogeId = Integer.parseInt(t); } @Override public void writeItems(List<Object> items) throws Exception { for (Object o : items) { Hoge newRecord = new Hoge(hogeId, (String)o); em.persist(newRecord); hogeId++; count++; } } @Override public void close() throws Exception { System.out.println("# insert count=" + count); } @Override public Serializable checkpointInfo() throws Exception { return null; } }
INSERTãå®è¡ãããã³ãããã¯jBatchå´ã§åæã«ãã£ã¦ãããã
StartDataload
@Path("/startdataload") public class StartDataload { @GET public void go() { JobOperator job = BatchRuntime.getJobOperator(); long id = job.start("sample-job-dataload", null); System.out.println("id = " + id); } }
jBatchãããã¯ããããã®ã¨ã³ããªãã¤ã³ããArquillianã§ãServletã§ãä½ã§ãè¯ããä»åã¯JAX-RSã«ãããhttp://localhost:8080/jbatchsample/rest/startdataload
ã®URLã§ããã¯ããã
MyApplication
@ApplicationPath("/rest") public class MyApplication extends Application { }
JAX-RSç¨ã®è¨å®ã¯ã©ã¹ã
ExecutionTimeJobListener
@Dependent @Named("executionTimeJobListener") public class ExecutionTimeJobListener implements JobListener { private long start = 0; @Override public void beforeJob() throws Exception { start = System.currentTimeMillis(); } @Override public void afterJob() throws Exception { long end = System.currentTimeMillis(); System.out.println(end - start); } }
å®è¡æéã®è¨æ¸¬ç¨ã¯ã©ã¹ãjBatchã®ã¸ã§ãã¬ãã«ãªã¹ãã¼ã§ãã¸ã§ãã®éå§æã¨çµäºæã®System.currentTimeMillis()
ã®å·®ãåã£ã¦ããã
å®è¡æé
ãã¿ã¼ã³ | 1 | 2 | 3 |
---|---|---|---|
ãªã | 166647 | 179543 | 175293 |
ãããåºæºå¤ã¨ãã¦ãå種ãã©ã¡ã¼ã¿å¤æ´å¾ã®åä½ã¨æ¯è¼ããã
ãã©ã¡ã¼ã¿å¤æ´
å®è¡æéã«å½±é¿ãåºãããªãã©ã¡ã¼ã¿ãªã©ãå¤æ´ããå·®ãåºããã©ããã確èªãã¦ã¿ãã
ã³ãããéé
jBatchã使ç¨ãã¦ããã®ã§ãå³å¯ã«è¨ãã¨chunkã®item-countã§ããããã ãä»åã¯Oracleãåæãªã®ã§å®è³ªçã«ã¯ã³ãããééã¨å義ã§ããã
item-countã®ããã©ã«ãå¤ã¯10ãªã®ã§ãããã100ã«å¤æ´ãã¦ã¿ãã
<chunk item-count="100">
ãã¿ã¼ã³ | 1 | 2 | 3 |
---|---|---|---|
ãªã | 166647 | 179543 | 175293 |
item-count="100" | 28317 | 28825 | 27947 |
ãããã6ï½7åã®å·®ãåºã¦ãããä¼çµ±çãªã»ãªãªã¼éãããã®ãã®ãããå¦çã§ã¯ã³ãããééã®èª¿æ´ãæå¹ãªãã¨ã伺ããã
ãããæ´æ°
JPAããJDBCã®ãããæ´æ°ã使ã ãªã©ã«ããéããJDBCã®ãããæ´æ°ã使ç¨ãã¦ã¯ã¨ãªãä¸åº¦ã«éãè¾¼ãéãå¢ãããããã«ãã£ã¦æ§è½æ¹åãè¦è¾¼ããã±ã¼ã¹ãããã
persistence.xmlã«EclipseLinkç¨ã®ãããæ´æ°ç¨ã®è¨å®ã追å ããããªããã³ãããééã¯100ã®ã¾ã¾ã§å®è¡æéãè¨æ¸¬ããã
<persistence-unit name="glassfish4oracle11gee" transaction-type="JTA"> <jta-data-source>jdbc/oracle11gee</jta-data-source> <properties> <property name="eclipselink.jdbc.batch-writing" value="jdbc"/> <property name="eclipselink.jdbc.batch-writing.size" value="100"/> </properties> </persistence-unit>
ãã¿ã¼ã³ | 1 | 2 | 3 |
---|---|---|---|
ãªã | 166647 | 179543 | 175293 |
item-count="100" | 28317 | 28825 | 27947 |
item-count="100", batch-writing.size=100 | 16002 | 16710 | 16880 |
partition
jBatchã®partitionã使ç¨ãããã«ãã¹ã¬ããã§å¦çãè¡ãã
jBatchã®partitionæ°ã3ãã¹ã¬ããæ°ã3ã«è¨å®ãããç°¡ç¥åã®ãããå¦ç対象ãã¡ã¤ã«30000件ã¯10000 * 3ãã¡ã¤ã«ã«ãããããåå²ãã¦ããã
<partition> <plan partitions="3" threads="3"> <properties partition="0"> <property name="startId" value="1" /> <property name="file" value="C:\\Java\\sampledataload\\input_p_1.txt" /> </properties> <properties partition="1"> <property name="startId" value="10001" /> <property name="file" value="C:\\Java\\sampledataload\\input_p_2.txt" /> </properties> <properties partition="2"> <property name="startId" value="20001" /> <property name="file" value="C:\\Java\\sampledataload\\input_p_3.txt" /> </properties> </plan> </partition>
ãã¿ã¼ã³ | 1 | 2 | 3 |
---|---|---|---|
ãªã | 166647 | 179543 | 175293 |
partitions="3" | 148529 | 148020 | 158559 |
è¥å¹²ã§ã¯ãããæ¹åãè¦ãããããããã¯ç°å¢ä¾åã大ããã¨æããããOracleå´ã®ããã»ã¹ãã¹ã¬ããæ°ã¨åãã ã確ä¿ã§ããªããã°æå³ãç¡ãã®ã§ãããã¯ã¢ããªã±ã¼ã·ã§ã³ãµã¼ãã®ã³ãã¯ã·ã§ã³ãã¼ãªã³ã°ã«ä¾åããã
ã¾ãã表å ã®è¡é åºã¯ã¤ã³ããã¯ã¹ç¯å²ã¹ãã£ã³ã¨æ·±ãé¢é£ãããããããã¼ãã£ã·ã§ã³ã®åå²ã§ãã¼ã¿ãã¼ãã®æéã ããæ©ããªã£ã¦ãæå³ãç¡ãå ´åããããããåèï¼è¡¨ã®è¡é åºã¨ã¤ã³ããã¯ã¹ç¯å²ã¹ãã£ã³
å®è¡æéã®ã¾ã¨ã
ãã¿ã¼ã³ | 1 | 2 | 3 |
---|---|---|---|
ãªã | 166647 | 179543 | 175293 |
item-count="100" | 28317 | 28825 | 27947 |
item-count="100", batch-writing.size=100 | 16002 | 16710 | 16880 |
partitions="3" | 148529 | 148020 | 158559 |
ãã㶠| 14249 | 15237 | 13272 |
ä¸è¨è¡¨ã®ãããã¶ãã¯ãã³ãããééã»ãããæ´æ°ã»ãã¼ãã£ã·ã§ã³ãé©ç¨ãããã®ããªããæå®ç¡ãã®1/10ãããã«ã¯ãªã£ã¦ãããã¨ã伺ããã