Repository: housepower/ClickHouse-Native-JDBC
Pull request #31 (2018-06-19 03:41:39)

benchmark with yandex/clickhouse-jdbc


Patch:
diff --git a/.travis.yml b/.travis.yml
index cc25e0d..ca2c279 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,6 @@
 sudo: required
 language: java
+dist: trusty
 services:
   - docker
 jdk:
diff --git a/pom.xml b/pom.xml
index 6cc5034..a096f76 100644
--- a/pom.xml
+++ b/pom.xml
@@ -58,6 +58,18 @@
             <version>4.11</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>com.carrotsearch</groupId>
+            <artifactId>junit-benchmarks</artifactId>
+            <version>0.7.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>ru.yandex.clickhouse</groupId>
+            <artifactId>clickhouse-jdbc</artifactId>
+            <version>0.1.40</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-all</artifactId>
diff --git a/src/main/java/com/github/housepower/jdbc/ClickHouseConnection.java b/src/main/java/com/github/housepower/jdbc/ClickHouseConnection.java
index 6dc52d6..892539f 100644
--- a/src/main/java/com/github/housepower/jdbc/ClickHouseConnection.java
+++ b/src/main/java/com/github/housepower/jdbc/ClickHouseConnection.java
@@ -136,13 +136,13 @@ public class ClickHouseConnection extends SQLConnection {
         int rows = 0;
         connection.sendQuery(insertQuery, atomicInfo.get().client(), configure.settings());
         Block header = connection.receiveSampleBlock(configure.queryTimeout(), atomicInfo.get().server());
-
         while (true) {
-            Block block = input.next(header, 8192);
+            Block block = input.next(header, ClickHouseDefines.MAX_BLOCK_SIZE);
 
             if (block == null || block.rows() == 0) {
                 connection.sendData(new Block());
                 connection.receiveEndOfStream(configure.queryTimeout(), atomicInfo.get().server());
+
                 return rows;
             }
 
diff --git a/src/main/java/com/github/housepower/jdbc/ClickHouseResultSet.java b/src/main/java/com/github/housepower/jdbc/ClickHouseResultSet.java
index 726f644..5a0fd9d 100644
--- a/src/main/java/com/github/housepower/jdbc/ClickHouseResultSet.java
+++ b/src/main/java/com/github/housepower/jdbc/ClickHouseResultSet.java
@@ -18,7 +18,6 @@ import java.sql.SQLException;
 import java.sql.Statement;
 import java.sql.Timestamp;
 import java.util.Calendar;
-import java.util.Iterator;
 
 public class ClickHouseResultSet extends SQLResultSet {
     private int row = -1;
@@ -107,8 +106,7 @@ public class ClickHouseResultSet extends SQLResultSet {
 
     @Override
     public int getInt(int index) throws SQLException {
-        Object data;
-        Validate.isTrue((data = getObject(index)) instanceof Number);
+        Object data = getObject(index);
         return ((Number) data).intValue();
     }
 
@@ -123,15 +121,13 @@ public class ClickHouseResultSet extends SQLResultSet {
 
     @Override
     public byte getByte(int index) throws SQLException {
-        Object data;
-        Validate.isTrue((data = getObject(index)) instanceof Number);
+        Object data = getObject(index);
         return ((Number) data).byteValue();
     }
 
     @Override
     public Date getDate(int index) throws SQLException {
-        Object data;
-        Validate.isTrue((data = getObject(index)) instanceof Date);
+        Object data = getObject(index);
         return (Date) data;
     }
 
@@ -142,43 +138,37 @@ public class ClickHouseResultSet extends SQLResultSet {
 
     @Override
     public long getLong(int index) throws SQLException {
-        Object data;
-        Validate.isTrue((data = getObject(index)) instanceof Number);
+        Object data = getObject(index);
         return ((Number) data).longValue();
     }
 
     @Override
     public Array getArray(int index) throws SQLException {
-        Object data;
-        Validate.isTrue((data = getObject(index)) instanceof Array);
+        Object data = getObject(index);
         return (Array) data;
     }
 
     @Override
     public float getFloat(int index) throws SQLException {
-        Object data;
-        Validate.isTrue((data = getObject(index)) instanceof Number);
+        Object data = getObject(index);
         return ((Number) data).floatValue();
     }
 
     @Override
     public short getShort(int index) throws SQLException {
-        Object data;
-        Validate.isTrue((data = getObject(index)) instanceof Number);
+        Object data = getObject(index);
         return ((Number) data).shortValue();
     }
 
     @Override
     public double getDouble(int index) throws SQLException {
-        Object data;
-        Validate.isTrue((data = getObject(index)) instanceof Number);
+        Object data = getObject(index);
         return ((Number) data).doubleValue();
     }
 
     @Override
     public String getString(int index) throws SQLException {
-        Object data;
-        Validate.isTrue((data = getObject(index)) instanceof String);
+        Object data = getObject(index);
         return (String) data;
     }
 
@@ -193,15 +183,13 @@ public class ClickHouseResultSet extends SQLResultSet {
 
     @Override
     public Timestamp getTimestamp(int index) throws SQLException {
-        Object data;
-        Validate.isTrue((data = getObject(index)) instanceof Timestamp);
+        Object data = getObject(index);
         return (Timestamp) data;
     }
 
     @Override
     public BigDecimal getBigDecimal(int index) throws SQLException {
-        Object data;
-        Validate.isTrue((data = getObject(index)) instanceof Number);
+        Object data = getObject(index);
         return new BigDecimal(data.toString());
     }
 
diff --git a/src/main/java/com/github/housepower/jdbc/buffer/SocketBuffedReader.java b/src/main/java/com/github/housepower/jdbc/buffer/SocketBuffedReader.java
index 159ff74..e14af10 100644
--- a/src/main/java/com/github/housepower/jdbc/buffer/SocketBuffedReader.java
+++ b/src/main/java/com/github/housepower/jdbc/buffer/SocketBuffedReader.java
@@ -1,12 +1,12 @@
 package com.github.housepower.jdbc.buffer;
 
+import com.github.housepower.jdbc.settings.ClickHouseDefines;
+
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.Socket;
 
-import com.github.housepower.jdbc.settings.ClickHouseDefines;
-
 public class SocketBuffedReader implements BuffedReader {
 
     private int limit;
@@ -17,7 +17,7 @@ public class SocketBuffedReader implements BuffedReader {
     private final InputStream in;
 
     public SocketBuffedReader(Socket socket) throws IOException {
-        this(socket.getInputStream(), ClickHouseDefines.DEFAULT_BUFFER_SIZE);
+        this(socket.getInputStream(), ClickHouseDefines.SOCKET_BUFFER_SIZE);
     }
 
     SocketBuffedReader(InputStream in, int capacity) {
diff --git a/src/main/java/com/github/housepower/jdbc/buffer/SocketBuffedWriter.java b/src/main/java/com/github/housepower/jdbc/buffer/SocketBuffedWriter.java
index 3add63a..9a3f4d9 100644
--- a/src/main/java/com/github/housepower/jdbc/buffer/SocketBuffedWriter.java
+++ b/src/main/java/com/github/housepower/jdbc/buffer/SocketBuffedWriter.java
@@ -1,11 +1,11 @@
 package com.github.housepower.jdbc.buffer;
 
+import com.github.housepower.jdbc.settings.ClickHouseDefines;
+
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.Socket;
 
-import com.github.housepower.jdbc.settings.ClickHouseDefines;
-
 public class SocketBuffedWriter implements BuffedWriter {
 
     private int position;
@@ -16,7 +16,7 @@ public class SocketBuffedWriter implements BuffedWriter {
 
     public SocketBuffedWriter(Socket socket) throws IOException {
         this.position = 0;
-        this.capacity = ClickHouseDefines.DEFAULT_BUFFER_SIZE;
+        this.capacity = ClickHouseDefines.SOCKET_BUFFER_SIZE;
 
         this.buf = new byte[capacity];
         this.out = socket.getOutputStream();
diff --git a/src/main/java/com/github/housepower/jdbc/connect/PhysicalConnection.java b/src/main/java/com/github/housepower/jdbc/connect/PhysicalConnection.java
index 3c4ce53..1b45d7c 100644
--- a/src/main/java/com/github/housepower/jdbc/connect/PhysicalConnection.java
+++ b/src/main/java/com/github/housepower/jdbc/connect/PhysicalConnection.java
@@ -132,8 +132,8 @@ public class PhysicalConnection {
 
             Socket socket = new Socket();
             socket.setTcpNoDelay(true);
-            socket.setSendBufferSize(ClickHouseDefines.DEFAULT_BUFFER_SIZE);
-            socket.setReceiveBufferSize(ClickHouseDefines.DEFAULT_BUFFER_SIZE);
+            socket.setSendBufferSize(ClickHouseDefines.SOCKET_BUFFER_SIZE);
+            socket.setReceiveBufferSize(ClickHouseDefines.SOCKET_BUFFER_SIZE);
             socket.connect(endpoint, configure.connectTimeout());
 
             return new PhysicalConnection(socket, new BinarySerializer(socket), new BinaryDeserializer(socket));
diff --git a/src/main/java/com/github/housepower/jdbc/data/Block.java b/src/main/java/com/github/housepower/jdbc/data/Block.java
index 7a40fef..58df398 100644
--- a/src/main/java/com/github/housepower/jdbc/data/Block.java
+++ b/src/main/java/com/github/housepower/jdbc/data/Block.java
@@ -1,6 +1,7 @@
 package com.github.housepower.jdbc.data;
 
 import com.github.housepower.jdbc.connect.PhysicalInfo;
+import com.github.housepower.jdbc.misc.Slice;
 import com.github.housepower.jdbc.misc.Validate;
 import com.github.housepower.jdbc.serializer.BinaryDeserializer;
 import com.github.housepower.jdbc.serializer.BinarySerializer;
@@ -44,9 +45,7 @@ public class Block {
         serializer.writeVarInt(rows);
 
         for (Column column : columns) {
-            serializer.writeStringBinary(column.name());
-            serializer.writeStringBinary(column.type().name());
-            column.type().serializeBinaryBulk(column.data(), serializer);
+            column.serializeBinaryBulk(serializer);
         }
     }
 
@@ -83,7 +82,8 @@ public class Block {
             String type = deserializer.readStringBinary();
 
             IDataType dataType = DataTypeFactory.get(type, serverInfo);
-            cols[i] = new Column(name, dataType, dataType.deserializeBinaryBulk(rows, deserializer));
+            Object []arr = dataType.deserializeBinaryBulk(rows, deserializer);
+            cols[i] = new Column(name, dataType, new Slice(arr));
         }
 
         return new Block(rows, cols, info);
diff --git a/src/main/java/com/github/housepower/jdbc/data/Column.java b/src/main/java/com/github/housepower/jdbc/data/Column.java
index 9f6c088..6b2eec0 100644
--- a/src/main/java/com/github/housepower/jdbc/data/Column.java
+++ b/src/main/java/com/github/housepower/jdbc/data/Column.java
@@ -1,15 +1,36 @@
 package com.github.housepower.jdbc.data;
 
+import com.github.housepower.jdbc.misc.Slice;
+import com.github.housepower.jdbc.serializer.BinarySerializer;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.sql.Types;
+
 public class Column {
 
     private final String name;
     private final IDataType type;
-    private final Object[] rowsData;
+    private final Slice rowsData;
+    private final int rows;
+
+    private boolean isConstant;
 
-    public Column(String name, IDataType type, Object[] rowsData) {
+    public Column(String name, IDataType type, Slice rowsData) {
         this.name = name;
         this.type = type;
         this.rowsData = rowsData;
+        this.rows = rowsData.size();
+    }
+
+    // const column
+    public Column(String name, IDataType type, Object constData, int rows) {
+        this.name = name;
+        this.type = type;
+        this.isConstant = true;
+        this.rows = rows;
+        this.rowsData = new Slice(1);
+        this.rowsData.add(constData);
     }
 
     public String name() {
@@ -20,13 +41,36 @@ public class Column {
         return this.type;
     }
 
-    public Object[] data() {
+    public Slice data() {
         return rowsData;
     }
 
     public Object data(int rows) {
-        return rowsData[rows];
+        if (isConstant) {
+            return rowsData.get(0);
+        }
+        return rowsData.get(rows);
     }
 
+    public void serializeBinaryBulk(BinarySerializer serializer) throws SQLException, IOException {
+        serializer.writeStringBinary(name);
+        serializer.writeStringBinary(type.name());
 
+        if (type.sqlTypeId() == Types.ARRAY) {
+            Object[] objects = new Object[rows];
+            for (int i = 0; i < rows; i++) {
+                objects[i] = rowsData.get(isConstant ? 0 : i);
+            }
+            type.serializeBinaryBulk(objects, serializer);
+            return;
+        }
+
+        if (isConstant) {
+            for (int i = 0; i < rows; i++) {
+                type.serializeBinary(rowsData.get(0), serializer);
+            }
+        } else {
+            type.serializeBinaryBulk(rowsData.iterator(), serializer);
+        }
+    }
 }
diff --git a/src/main/java/com/github/housepower/jdbc/data/IDataType.java b/src/main/java/com/github/housepower/jdbc/data/IDataType.java
index b6ee6f3..4833c31 100644
--- a/src/main/java/com/github/housepower/jdbc/data/IDataType.java
+++ b/src/main/java/com/github/housepower/jdbc/data/IDataType.java
@@ -6,6 +6,7 @@ import com.github.housepower.jdbc.serializer.BinarySerializer;
 
 import java.io.IOException;
 import java.sql.SQLException;
+import java.util.Iterator;
 
 public interface IDataType {
     String name();
@@ -24,7 +25,17 @@ public interface IDataType {
 
     Object deserializeBinary(BinaryDeserializer deserializer) throws SQLException, IOException;
 
-    void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException;
+    default void serializeBinaryBulk(Iterator<Object> data, BinarySerializer serializer) throws SQLException, IOException {
+        while(data.hasNext()) {
+            serializeBinary(data.next(), serializer);
+        }
+    }
+
+    default void serializeBinaryBulk(Object []data, BinarySerializer serializer) throws SQLException, IOException {
+        for(Object d : data) {
+            serializeBinary(d, serializer);
+        }
+    }
 
     Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer) throws SQLException, IOException;
 }
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeDate.java b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeDate.java
index 8649060..e72e90b 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeDate.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeDate.java
@@ -70,8 +70,6 @@ public class DataTypeDate implements IDataType {
     @Override
     public void serializeBinary(Object data, BinarySerializer serializer)
         throws SQLException, IOException {
-        Validate.isTrue(data instanceof Date,
-                        "Expected Date Parameter, but was " + data.getClass().getSimpleName());
         LocalDate localDate = new LocalDate(((Date) data).getTime(), dateTimeZone);
         int daysSinceEpoch = Days.daysBetween(epochDate, localDate).getDays();
         serializer.writeShort((short) daysSinceEpoch);
@@ -84,14 +82,6 @@ public class DataTypeDate implements IDataType {
         return new Date(localDate.toDate().getTime());
     }
 
-    @Override
-    public void serializeBinaryBulk(Object[] data, BinarySerializer serializer)
-        throws SQLException, IOException {
-        for (Object datum : data) {
-            serializeBinary(datum, serializer);
-        }
-    }
-
     @Override
     public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer)
         throws IOException {
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeFloat32.java b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeFloat32.java
index 0d8ff69..bd4c642 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeFloat32.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeFloat32.java
@@ -2,7 +2,6 @@ package com.github.housepower.jdbc.data.type;
 
 import com.github.housepower.jdbc.data.IDataType;
 import com.github.housepower.jdbc.misc.SQLLexer;
-import com.github.housepower.jdbc.misc.Validate;
 import com.github.housepower.jdbc.serializer.BinaryDeserializer;
 import com.github.housepower.jdbc.serializer.BinarySerializer;
 
@@ -41,8 +40,6 @@ public class DataTypeFloat32 implements IDataType {
 
     @Override
     public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        Validate.isTrue(data instanceof Float, "Expected Float Parameter, but was " + data.getClass().getSimpleName());
-
         serializer.writeFloat((Float) data);
     }
 
@@ -51,13 +48,6 @@ public class DataTypeFloat32 implements IDataType {
         return deserializer.readFloat();
     }
 
-    @Override
-    public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException {
-        for (Object datum : data) {
-            serializeBinary(datum, serializer);
-        }
-    }
-
     @Override
     public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer) throws IOException {
         Float[] data = new Float[rows];
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeFloat64.java b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeFloat64.java
index 4b4e444..ceade14 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeFloat64.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeFloat64.java
@@ -2,7 +2,6 @@ package com.github.housepower.jdbc.data.type;
 
 import com.github.housepower.jdbc.data.IDataType;
 import com.github.housepower.jdbc.misc.SQLLexer;
-import com.github.housepower.jdbc.misc.Validate;
 import com.github.housepower.jdbc.serializer.BinaryDeserializer;
 import com.github.housepower.jdbc.serializer.BinarySerializer;
 
@@ -41,9 +40,6 @@ public class DataTypeFloat64 implements IDataType {
 
     @Override
     public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        Validate.isTrue(data instanceof Double || data instanceof Float,
-            "Expected Double Parameter, but was " + data.getClass().getSimpleName());
-
         serializer.writeDouble(((Number) data).doubleValue());
     }
 
@@ -52,13 +48,6 @@ public class DataTypeFloat64 implements IDataType {
         return deserializer.readDouble();
     }
 
-    @Override
-    public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException {
-        for (Object datum : data) {
-            serializeBinary(datum, serializer);
-        }
-    }
-
     @Override
     public Double[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer) throws IOException {
         Double[] data = new Double[rows];
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt16.java b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt16.java
index 6d24b4e..29e9ce6 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt16.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt16.java
@@ -1,10 +1,9 @@
 package com.github.housepower.jdbc.data.type;
 
+import com.github.housepower.jdbc.data.IDataType;
 import com.github.housepower.jdbc.misc.SQLLexer;
-import com.github.housepower.jdbc.misc.Validate;
 import com.github.housepower.jdbc.serializer.BinaryDeserializer;
 import com.github.housepower.jdbc.serializer.BinarySerializer;
-import com.github.housepower.jdbc.data.IDataType;
 
 import java.io.IOException;
 import java.sql.SQLException;
@@ -48,9 +47,6 @@ public class DataTypeInt16 implements IDataType {
 
     @Override
     public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        Validate.isTrue(data instanceof Byte || data instanceof Short,
-            "Expected Short Parameter, but was " + data.getClass().getSimpleName());
-
         serializer.writeShort(((Number) data).shortValue());
     }
 
@@ -63,13 +59,6 @@ public class DataTypeInt16 implements IDataType {
         return s;
     }
 
-    @Override
-    public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException {
-        for (Object datum : data) {
-            serializeBinary(datum, serializer);
-        }
-    }
-
     @Override
     public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer) throws SQLException, IOException {
         Object[] data = new Object[rows];
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt32.java b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt32.java
index dc6d597..3ecf237 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt32.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt32.java
@@ -1,8 +1,7 @@
 package com.github.housepower.jdbc.data.type;
 
-import com.github.housepower.jdbc.misc.SQLLexer;
-import com.github.housepower.jdbc.misc.Validate;
 import com.github.housepower.jdbc.data.IDataType;
+import com.github.housepower.jdbc.misc.SQLLexer;
 import com.github.housepower.jdbc.serializer.BinaryDeserializer;
 import com.github.housepower.jdbc.serializer.BinarySerializer;
 
@@ -47,14 +46,14 @@ public class DataTypeInt32 implements IDataType {
     }
 
     @Override
-    public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        Validate.isTrue(data instanceof Number,
-            "Expected Integer Parameter, but was " + data.getClass().getSimpleName());
+    public void serializeBinary(Object data, BinarySerializer serializer)
+        throws SQLException, IOException {
         serializer.writeInt(((Number) data).intValue());
     }
 
     @Override
-    public Object deserializeBinary(BinaryDeserializer deserializer) throws SQLException, IOException {
+    public Object deserializeBinary(BinaryDeserializer deserializer)
+        throws SQLException, IOException {
         int res = deserializer.readInt();
         if (isUnsigned) {
             return 0xffffffffL & res;
@@ -63,14 +62,8 @@ public class DataTypeInt32 implements IDataType {
     }
 
     @Override
-    public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException {
-        for (Object datum : data) {
-            serializeBinary(datum, serializer);
-        }
-    }
-
-    @Override
-    public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer) throws SQLException, IOException {
+    public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer)
+        throws SQLException, IOException {
         Object[] data = new Object[rows];
         for (int row = 0; row < rows; row++) {
             data[row] = this.deserializeBinary(deserializer);
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt64.java b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt64.java
index 400b054..bde5889 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt64.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt64.java
@@ -2,12 +2,10 @@ package com.github.housepower.jdbc.data.type;
 
 import com.github.housepower.jdbc.data.IDataType;
 import com.github.housepower.jdbc.misc.SQLLexer;
-import com.github.housepower.jdbc.misc.Validate;
 import com.github.housepower.jdbc.serializer.BinaryDeserializer;
 import com.github.housepower.jdbc.serializer.BinarySerializer;
 
 import java.io.IOException;
-import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.nio.ByteBuffer;
 import java.sql.SQLException;
@@ -52,15 +50,14 @@ public class DataTypeInt64 implements IDataType {
     }
 
     @Override
-    public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        Validate.isTrue(data instanceof Byte || data instanceof Short || data instanceof Integer ||
-            data instanceof Long, "Expected Long Parameter, but was " + data.getClass().getSimpleName());
-
+    public void serializeBinary(Object data, BinarySerializer serializer)
+        throws SQLException, IOException {
         serializer.writeLong(((Number) data).longValue());
     }
 
     @Override
-    public Object deserializeBinary(BinaryDeserializer deserializer) throws SQLException, IOException {
+    public Object deserializeBinary(BinaryDeserializer deserializer)
+        throws SQLException, IOException {
         long l = deserializer.readLong();
         if (isUnsigned) {
             BigInteger unsigned = new BigInteger(1, longToBytes(l));
@@ -75,22 +72,17 @@ public class DataTypeInt64 implements IDataType {
         return buffer.array();
     }
 
-    public static BigInteger parseBigIntegerPositive(String num,int bitlen) {
+    public static BigInteger parseBigIntegerPositive(String num, int bitlen) {
         BigInteger b = new BigInteger(num);
-        if (b.compareTo(BigInteger.ZERO) < 0)
+        if (b.compareTo(BigInteger.ZERO) < 0) {
             b = b.add(BigInteger.ONE.shiftLeft(bitlen));
-        return b;
-    }
-
-    @Override
-    public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException {
-        for (Object datum : data) {
-            serializeBinary(datum, serializer);
         }
+        return b;
     }
 
     @Override
-    public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer) throws SQLException, IOException {
+    public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer)
+        throws SQLException, IOException {
         Object[] data = new Object[rows];
         for (int row = 0; row < rows; row++) {
             data[row] = this.deserializeBinary(deserializer);
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt8.java b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt8.java
index d709d2d..a16ced3 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt8.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeInt8.java
@@ -2,7 +2,6 @@ package com.github.housepower.jdbc.data.type;
 
 import com.github.housepower.jdbc.data.IDataType;
 import com.github.housepower.jdbc.misc.SQLLexer;
-import com.github.housepower.jdbc.misc.Validate;
 import com.github.housepower.jdbc.serializer.BinaryDeserializer;
 import com.github.housepower.jdbc.serializer.BinarySerializer;
 
@@ -48,7 +47,6 @@ public class DataTypeInt8 implements IDataType {
 
     @Override
     public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        Validate.isTrue(data instanceof Number, "Expected Byte Parameter, but was " + data.getClass().getSimpleName());
         serializer.writeByte(((Number)data).byteValue());
     }
 
@@ -61,13 +59,6 @@ public class DataTypeInt8 implements IDataType {
         return b;
     }
 
-    @Override
-    public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException {
-        for (Object datum : data) {
-            serializeBinary(datum, serializer);
-        }
-    }
-
     @Override
     public Number[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer) throws IOException {
         Number[] data = new Number[rows];
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeString.java b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeString.java
index 4a321d8..52c9161 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeString.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeString.java
@@ -2,7 +2,6 @@ package com.github.housepower.jdbc.data.type;
 
 import com.github.housepower.jdbc.data.IDataType;
 import com.github.housepower.jdbc.misc.SQLLexer;
-import com.github.housepower.jdbc.misc.StringView;
 import com.github.housepower.jdbc.serializer.BinaryDeserializer;
 import com.github.housepower.jdbc.serializer.BinarySerializer;
 
@@ -39,13 +38,7 @@ public class DataTypeString implements IDataType {
 
     @Override
     public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        if (data instanceof String) {
-            serializer.writeStringBinary((String) data);
-        } else if (data instanceof StringView) {
-            serializer.writeStringViewBinary((StringView) data);
-        } else {
-            throw new SQLException("Expected String Parameter, but was " + data.getClass().getSimpleName());
-        }
+        serializer.writeStringBinary((String) data);
     }
 
     @Override
@@ -53,13 +46,6 @@ public class DataTypeString implements IDataType {
         return deserializer.readStringBinary();
     }
 
-    @Override
-    public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException {
-        for (Object datum : data) {
-            serializeBinary(datum, serializer);
-        }
-    }
-
     @Override
     public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer)
         throws SQLException, IOException {
@@ -72,6 +58,6 @@ public class DataTypeString implements IDataType {
 
     @Override
     public Object deserializeTextQuoted(SQLLexer lexer) throws SQLException {
-        return lexer.stringLiteral();
+        return String.valueOf(lexer.stringLiteral());
     }
 }
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeUUID.java b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeUUID.java
index b6249d4..a2b4b4f 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/DataTypeUUID.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/DataTypeUUID.java
@@ -2,8 +2,6 @@ package com.github.housepower.jdbc.data.type;
 
 import com.github.housepower.jdbc.data.IDataType;
 import com.github.housepower.jdbc.misc.SQLLexer;
-import com.github.housepower.jdbc.misc.StringView;
-import com.github.housepower.jdbc.misc.Validate;
 import com.github.housepower.jdbc.serializer.BinaryDeserializer;
 import com.github.housepower.jdbc.serializer.BinarySerializer;
 
@@ -41,14 +39,11 @@ public class DataTypeUUID implements IDataType {
 
     @Override
     public Object deserializeTextQuoted(SQLLexer lexer) throws SQLException {
-        return lexer.stringLiteral();
+        return String.valueOf(lexer.stringLiteral());
     }
 
     @Override
     public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        Validate.isTrue(data instanceof String || data instanceof StringView,
-            "Expected String Parameter, but was " + data.getClass().getSimpleName());
-
         UUID uuid = UUID.fromString(String.valueOf(data));
         serializer.writeLong(uuid.getMostSignificantBits());
         serializer.writeLong(uuid.getLeastSignificantBits());
@@ -59,13 +54,6 @@ public class DataTypeUUID implements IDataType {
         return new UUID(deserializer.readLong(), deserializer.readLong()).toString();
     }
 
-    @Override
-    public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException {
-        for (Object datum : data) {
-            serializeBinary(datum, serializer);
-        }
-    }
-
     @Override
     public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer) throws SQLException, IOException {
         String[] data = new String[rows];
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeArray.java b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeArray.java
index 725ad99..16beb93 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeArray.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeArray.java
@@ -74,8 +74,6 @@ public class DataTypeArray implements IDataType {
 
     @Override
     public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        Validate.isTrue(data instanceof Array, "Expected Array Parameter, but was " + data.getClass().getSimpleName());
-
         offsetIDataType.serializeBinary(((Object[]) ((Array) data).getArray()).length, serializer);
         elemDataType.serializeBinaryBulk(((Object[]) ((Array) data).getArray()), serializer);
     }
@@ -90,18 +88,12 @@ public class DataTypeArray implements IDataType {
     public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException {
         long offset = 0;
         for (Object datum : data) {
-            Validate.isTrue(datum instanceof Array,
-                "Expected Array Parameter, but was " + datum.getClass().getSimpleName());
-
             Object[] arrayData = (Object[]) ((Array) datum).getArray();
             offset += arrayData.length;
             offsetIDataType.serializeBinary(offset, serializer);
         }
 
         for (Object datum : data) {
-            Validate.isTrue(datum instanceof Array,
-                "Expected Array Parameter, but was " + datum.getClass().getSimpleName());
-
             Object[] arrayData = (Object[]) ((Array) datum).getArray();
             elemDataType.serializeBinaryBulk(arrayData, serializer);
         }
@@ -131,6 +123,6 @@ public class DataTypeArray implements IDataType {
         IDataType arrayNestedType = DataTypeFactory.get(lexer, serverInfo);
         Validate.isTrue(lexer.character() == ')');
         return new DataTypeArray("Array(" + arrayNestedType.name() + ")",
-            arrayNestedType, DataTypeFactory.get("UInt64", serverInfo));
+                                 arrayNestedType, DataTypeFactory.get("UInt64", serverInfo));
     }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeDateTime.java b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeDateTime.java
index a4c83e0..7a99e66 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeDateTime.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeDateTime.java
@@ -89,8 +89,6 @@ public class DataTypeDateTime implements IDataType {
 
     @Override
     public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        Validate.isTrue(data instanceof Timestamp,
-            "Expected Timestamp Parameter, but was " + data.getClass().getSimpleName());
         serializer.writeInt((int) ((((Timestamp) data).getTime()) / 1000));
     }
 
@@ -99,13 +97,6 @@ public class DataTypeDateTime implements IDataType {
         return new Timestamp(deserializer.readInt() * 1000L);
     }
 
-    @Override
-    public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException {
-        for (Object datum : data) {
-            serializeBinary(datum, serializer);
-        }
-    }
-
     @Override
     public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer) throws SQLException, IOException {
         Timestamp[] data = new Timestamp[rows];
@@ -121,7 +112,7 @@ public class DataTypeDateTime implements IDataType {
             StringView dataTimeZone = lexer.stringLiteral();
             Validate.isTrue(lexer.character() == ')');
             return new DataTypeDateTime("DateTime(" +
-                String.valueOf(dataTimeZone) + ")", serverInfo);
+                                        dataTimeZone + ")", serverInfo);
         }
         return new DataTypeDateTime("DateTime", serverInfo);
     }
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeDecimal.java b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeDecimal.java
index 94fb192..0c6ff4b 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeDecimal.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeDecimal.java
@@ -81,9 +81,6 @@ public class DataTypeDecimal implements IDataType {
 
     @Override
     public void serializeBinary(Object data, BinarySerializer serializer) throws IOException {
-        if (!(data instanceof BigDecimal)) {
-            throw new RuntimeException(String.format("Error data type %s.", data.getClass().getSimpleName()));
-        }
         BigDecimal targetValue = ((BigDecimal) data).multiply(scaleFactor);
         switch (this.nobits) {
             case 32: {
@@ -124,13 +121,6 @@ public class DataTypeDecimal implements IDataType {
         return value;
     }
 
-    @Override
-    public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException {
-        for (Object obj : data) {
-            serializeBinary(obj, serializer);
-        }
-    }
-
     @Override
     public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer) throws SQLException, IOException {
         BigDecimal[] data = new BigDecimal[rows];
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeEnum16.java b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeEnum16.java
index 3985d89..b3dd1e3 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeEnum16.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeEnum16.java
@@ -3,7 +3,6 @@ package com.github.housepower.jdbc.data.type.complex;
 import com.github.housepower.jdbc.connect.PhysicalInfo;
 import com.github.housepower.jdbc.data.IDataType;
 import com.github.housepower.jdbc.misc.SQLLexer;
-import com.github.housepower.jdbc.misc.StringView;
 import com.github.housepower.jdbc.misc.Validate;
 import com.github.housepower.jdbc.serializer.BinaryDeserializer;
 import com.github.housepower.jdbc.serializer.BinarySerializer;
@@ -58,9 +57,6 @@ public class DataTypeEnum16 implements IDataType {
 
     @Override
     public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        Validate.isTrue(data instanceof String || data instanceof StringView,
-            "Expected Enum8 Parameter, but was " + data.getClass().getSimpleName());
-
         for (int i = 0; i < names.length; i++) {
             if (data.equals(names[i])) {
                 serializer.writeShort(values[i]);
@@ -89,13 +85,6 @@ public class DataTypeEnum16 implements IDataType {
         throw new SQLException("");
     }
 
-    @Override
-    public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException {
-        for (Object datum : data) {
-            serializeBinary(datum, serializer);
-        }
-    }
-
     @Override
     public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer) throws SQLException, IOException {
         String[] data = new String[rows];
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeEnum8.java b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeEnum8.java
index 9b22b59..fd5d371 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeEnum8.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeEnum8.java
@@ -3,7 +3,6 @@ package com.github.housepower.jdbc.data.type.complex;
 import com.github.housepower.jdbc.connect.PhysicalInfo;
 import com.github.housepower.jdbc.data.IDataType;
 import com.github.housepower.jdbc.misc.SQLLexer;
-import com.github.housepower.jdbc.misc.StringView;
 import com.github.housepower.jdbc.misc.Validate;
 import com.github.housepower.jdbc.serializer.BinaryDeserializer;
 import com.github.housepower.jdbc.serializer.BinarySerializer;
@@ -58,9 +57,6 @@ public class DataTypeEnum8 implements IDataType {
 
     @Override
     public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        Validate.isTrue(data instanceof String || data instanceof StringView,
-            "Expected Enum8 Parameter, but was " + data.getClass().getSimpleName());
-
         for (int i = 0; i < names.length; i++) {
             if (data.equals(names[i])) {
                 serializer.writeByte(values[i]);
@@ -89,13 +85,6 @@ public class DataTypeEnum8 implements IDataType {
         throw new SQLException("");
     }
 
-    @Override
-    public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException {
-        for (Object datum : data) {
-            serializeBinary(datum, serializer);
-        }
-    }
-
     @Override
     public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer) throws SQLException, IOException {
         String[] data = new String[rows];
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeFixedString.java b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeFixedString.java
index 1701b2b..4b5e649 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeFixedString.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeFixedString.java
@@ -3,8 +3,6 @@ package com.github.housepower.jdbc.data.type.complex;
 import com.github.housepower.jdbc.connect.PhysicalInfo;
 import com.github.housepower.jdbc.data.IDataType;
 import com.github.housepower.jdbc.misc.SQLLexer;
-import com.github.housepower.jdbc.misc.StringView;
-import com.github.housepower.jdbc.misc.StringViewCoding;
 import com.github.housepower.jdbc.misc.Validate;
 import com.github.housepower.jdbc.serializer.BinaryDeserializer;
 import com.github.housepower.jdbc.serializer.BinarySerializer;
@@ -57,22 +55,18 @@ public class DataTypeFixedString implements IDataType {
 
     @Override
     public Object deserializeTextQuoted(SQLLexer lexer) throws SQLException {
-        return lexer.stringLiteral();
+        return String.valueOf(lexer.stringLiteral());
     }
 
     @Override
-    public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        if (data instanceof String) {
-            writeBytes(((String) data).getBytes(), serializer);
-        } else if (data instanceof StringView) {
-            writeBytes(StringViewCoding.bytes((StringView) data), serializer);
-        } else {
-            throw new SQLException("Expected FixedString Parameter, but was " + data.getClass().getSimpleName());
-        }
+    public void serializeBinary(Object data, BinarySerializer serializer)
+        throws SQLException, IOException {
+        writeBytes(((String) data).getBytes(), serializer);
     }
 
-    private void writeBytes(byte []bs, BinarySerializer serializer) throws IOException, SQLException {
-        byte []res;
+    private void writeBytes(byte[] bs, BinarySerializer serializer)
+        throws IOException, SQLException {
+        byte[] res;
         if (bs.length > n) {
             throw new SQLException("The size of FixString column is too large, got " + bs.length);
         }
@@ -86,19 +80,14 @@ public class DataTypeFixedString implements IDataType {
     }
 
     @Override
-    public Object deserializeBinary(BinaryDeserializer deserializer) throws SQLException, IOException {
+    public Object deserializeBinary(BinaryDeserializer deserializer)
+        throws SQLException, IOException {
         return new String(deserializer.readBytes(n));
     }
 
     @Override
-    public void serializeBinaryBulk(Object[] data, BinarySerializer serializer) throws SQLException, IOException {
-        for (Object datum : data) {
-            serializeBinary(datum, serializer);
-        }
-    }
-
-    @Override
-    public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer) throws SQLException, IOException {
+    public Object[] deserializeBinaryBulk(int rows, BinaryDeserializer deserializer)
+        throws SQLException, IOException {
         String[] data = new String[rows];
         for (int row = 0; row < rows; row++) {
             data[row] = new String(deserializer.readBytes(n));
@@ -106,10 +95,13 @@ public class DataTypeFixedString implements IDataType {
         return data;
     }
 
-    public static IDataType createFixedStringType(SQLLexer lexer, PhysicalInfo.ServerInfo serverInfo) throws SQLException {
+    public static IDataType createFixedStringType(SQLLexer lexer,
+                                                  PhysicalInfo.ServerInfo serverInfo)
+        throws SQLException {
         Validate.isTrue(lexer.character() == '(');
         Number fixedStringN = lexer.numberLiteral();
         Validate.isTrue(lexer.character() == ')');
-        return new DataTypeFixedString("FixedString(" + fixedStringN.intValue() + ")", fixedStringN.intValue());
+        return new DataTypeFixedString("FixedString(" + fixedStringN.intValue() + ")",
+                                       fixedStringN.intValue());
     }
 }
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeNullable.java b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeNullable.java
index 8720258..fc60053 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeNullable.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeNullable.java
@@ -64,7 +64,7 @@ public class DataTypeNullable implements IDataType {
 
     @Override
     public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        nullMapDataType.serializeBinary(data == null, serializer);
+        nullMapDataType.serializeBinary( data == null ? 1 : 0, serializer);
         this.nestedDataType.serializeBinary(data == null ? nestedDataType.defaultValue() : data, serializer);
     }
 
diff --git a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeTuple.java b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeTuple.java
index 09d8136..d73f81b 100644
--- a/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeTuple.java
+++ b/src/main/java/com/github/housepower/jdbc/data/type/complex/DataTypeTuple.java
@@ -57,9 +57,6 @@ public class DataTypeTuple implements IDataType {
 
     @Override
     public void serializeBinary(Object data, BinarySerializer serializer) throws SQLException, IOException {
-        Validate.isTrue(data instanceof Struct && "Tuple".equals(((Struct) data).getSQLTypeName()),
-            "Expected Struct Parameter, but was " + data.getClass().getSimpleName());
-
         for (int i = 0; i < nestedTypes.length; i++) {
             nestedTypes[i].serializeBinary(((Struct) data).getAttributes()[i], serializer);
         }
@@ -79,8 +76,6 @@ public class DataTypeTuple implements IDataType {
         for (int i = 0; i < nestedTypes.length; i++) {
             Object[] elemsData = new Object[data.length];
             for (int row = 0; row < data.length; row++) {
-                Validate.isTrue(data[row] instanceof Struct && "Tuple".equals(((Struct) data[row]).getSQLTypeName()),
-                    "Expected Struct Parameter, but was " + data.getClass().getSimpleName());
                 elemsData[row] = ((Struct) data[row]).getAttributes()[i];
             }
             nestedTypes[i].serializeBinaryBulk(elemsData, serializer);
diff --git a/src/main/java/com/github/housepower/jdbc/misc/SQLLexer.java b/src/main/java/com/github/housepower/jdbc/misc/SQLLexer.java
index 75afdb1..a5be3d5 100644
--- a/src/main/java/com/github/housepower/jdbc/misc/SQLLexer.java
+++ b/src/main/java/com/github/housepower/jdbc/misc/SQLLexer.java
@@ -8,7 +8,7 @@ public class SQLLexer {
 
     public SQLLexer(int pos, String data) throws SQLException {
         this.pos = pos;
-        this.data = StringViewCoding.getValues(data);
+        this.data = data.toCharArray();
     }
 
     public char character() {
diff --git a/src/main/java/com/github/housepower/jdbc/misc/Slice.java b/src/main/java/com/github/housepower/jdbc/misc/Slice.java
new file mode 100644
index 0000000..dd599d1
--- /dev/null
+++ b/src/main/java/com/github/housepower/jdbc/misc/Slice.java
@@ -0,0 +1,136 @@
+package com.github.housepower.jdbc.misc;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Spliterator;
+import java.util.function.Consumer;
+
+/**
+ * Slice Object just like the slice of Go
+ */
+public class Slice implements Iterable<Object>{
+    private Object []array;
+
+    private int capacity;
+    private int offset;
+    private int pos;
+
+    public Slice(int capacity) {
+        this.offset = 0;
+        this.pos = 0;
+
+        this.array = new Object[capacity];
+        this.capacity = capacity;
+    }
+
+    public Slice(Object []array) {
+        this.offset = 0;
+        this.pos = array.length;
+
+        this.array = array;
+        this.capacity = array.length;
+    }
+
+    public Slice(Slice slice, int offset, int pos) {
+        this.array = slice.array;
+
+        this.capacity = slice.capacity;
+        this.offset = offset;
+        this.pos = pos;
+    }
+
+
+    public int size() {
+        return pos - offset;
+    }
+
+    public Slice sub(int offsetAdd, int posAdd) {
+        return new Slice(this, offset + offsetAdd, offset + posAdd);
+    }
+
+    public Object get(int index) {
+        return array[index + offset];
+    }
+
+    public void add(Object object) {
+        if (pos >= capacity) {
+            grow(capacity);
+        }
+        array[pos] = object;
+        pos ++;
+    }
+
+    public void set(int index, Object object) {
+        array[offset + index] = object;
+    }
+
+
+    private void grow(int minCapacity) {
+        // overflow-conscious code
+        int oldCapacity = array.length;
+        int newCapacity = oldCapacity + (oldCapacity >> 1);
+        if (newCapacity - minCapacity < 0)
+            newCapacity = minCapacity;
+        if (newCapacity - MAX_ARRAY_SIZE > 0)
+            newCapacity = hugeCapacity(minCapacity);
+        // minCapacity is usually close to size, so this is a win:
+        array = Arrays.copyOf(array, newCapacity);
+        capacity = newCapacity;
+    }
+
+    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
+
+    private static int hugeCapacity(int minCapacity) {
+        if (minCapacity < 0) // overflow
+            throw new OutOfMemoryError();
+        return (minCapacity > MAX_ARRAY_SIZE) ?
+               Integer.MAX_VALUE :
+               MAX_ARRAY_SIZE;
+    }
+
+    public static class SliceIterator implements Iterator<Object>{
+        int current;
+        Slice slice;
+        SliceIterator(Slice slice) {
+            this.slice = slice;
+            this.current = slice.offset;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return current < slice.pos;
+        }
+
+        @Override
+        public Object next() {
+            Object obj = slice.array[current];
+            current ++;
+            return obj;
+        }
+
+        @Override
+        public void remove() {
+            return;
+        }
+
+        @Override
+        public void forEachRemaining(Consumer<? super Object> action) {
+            return;
+        }
+    }
+
+    @Override
+    public Iterator<Object> iterator() {
+        return new SliceIterator(this);
+    }
+
+    @Override
+    public void forEach(Consumer<? super Object> action) {
+
+    }
+
+    @Override
+    public Spliterator<Object> spliterator() {
+        return null;
+    }
+}
diff --git a/src/main/java/com/github/housepower/jdbc/misc/StringViewCoding.java b/src/main/java/com/github/housepower/jdbc/misc/StringViewCoding.java
deleted file mode 100644
index e45a064..0000000
--- a/src/main/java/com/github/housepower/jdbc/misc/StringViewCoding.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.github.housepower.jdbc.misc;
-
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.sql.SQLException;
-import java.util.Arrays;
-
-public class StringViewCoding {
-    private static Field stringValuesField;
-    private static Method encodeBytesMethod;
-
-    // https://github.com/housepower/ClickHouse-Native-JDBC/issues/82
-    // TODO Support jdk9,jdk10, so we temperoary use `new String`
-    public static byte[] bytes(StringView data) throws SQLException {
-        return new String(data.values()).substring(data.start(), data.end()).getBytes();
-//        try {
-//            Method encodeBytesMethod = getEncodeBytesMethod();
-//            return (byte[]) encodeBytesMethod.invoke(null, data.values(), data.start(), data.end() - data.start());
-//        } catch (Exception e) {
-//            throw new SQLException("Cannot get java.lang.StringCoding encode Method", e);
-//        }
-    }
-
-    public static char[] getValues(String data) throws SQLException {
-        return data.toCharArray();
-//        try {
-//            Field field = getStringValueReflectField();
-//            return (char[]) field.get(data);
-//        } catch (IllegalAccessException e) {
-//            throw new SQLException("Cannot get java.lang.String values field", e);
-//        }
-    }
-
-    private static Field getStringValueReflectField() throws SQLException {
-        if (stringValuesField == null) {
-            synchronized (StringViewCoding.class) {
-                if (stringValuesField == null) {
-                    try {
-                        Field stringValueField = String.class.getDeclaredField("value");
-                        stringValueField.setAccessible(true);
-                        StringViewCoding.stringValuesField = stringValueField;
-                    } catch (NoSuchFieldException e) {
-                        throw new SQLException("Cannot get java.lang.String values field", e);
-                    }
-                }
-            }
-        }
-        return stringValuesField;
-    }
-
-
-    private static byte[] toBytes(char[] chars, int start, int end) {
-        CharBuffer charBuffer = CharBuffer.wrap(chars);
-        ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer);
-        byte[] bytes = Arrays.copyOfRange(byteBuffer.array(),
-                                          byteBuffer.position() + start, byteBuffer.position() + end);
-        Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data
-        return bytes;
-    }
-
-    public static Method getEncodeBytesMethod() throws SQLException {
-        if (encodeBytesMethod == null) {
-            synchronized (StringViewCoding.class) {
-                if (encodeBytesMethod == null) {
-                    try {
-                        Class<?> codingClazz = Class.forName("java.lang.StringCoding");
-                        Method encodeBytesMethod =
-                            codingClazz.getDeclaredMethod("encode", char[].class, int.class, int.class);
-                        encodeBytesMethod.setAccessible(true);
-                        StringViewCoding.encodeBytesMethod = encodeBytesMethod;
-                    } catch (Exception e) {
-                        throw new SQLException("Cannot get java.lang.String values field", e);
-                    }
-                }
-            }
-        }
-        return encodeBytesMethod;
-    }
-}
diff --git a/src/main/java/com/github/housepower/jdbc/serializer/BinaryDeserializer.java b/src/main/java/com/github/housepower/jdbc/serializer/BinaryDeserializer.java
index 70f57e8..7539e4e 100644
--- a/src/main/java/com/github/housepower/jdbc/serializer/BinaryDeserializer.java
+++ b/src/main/java/com/github/housepower/jdbc/serializer/BinaryDeserializer.java
@@ -1,12 +1,12 @@
 package com.github.housepower.jdbc.serializer;
 
-import java.io.IOException;
-import java.net.Socket;
-
 import com.github.housepower.jdbc.buffer.BuffedReader;
-import com.github.housepower.jdbc.misc.Container;
 import com.github.housepower.jdbc.buffer.CompressedBuffedReader;
 import com.github.housepower.jdbc.buffer.SocketBuffedReader;
+import com.github.housepower.jdbc.misc.Container;
+
+import java.io.IOException;
+import java.net.Socket;
 
 public class BinaryDeserializer {
 
diff --git a/src/main/java/com/github/housepower/jdbc/serializer/BinarySerializer.java b/src/main/java/com/github/housepower/jdbc/serializer/BinarySerializer.java
index 7b03f58..0fa0fae 100644
--- a/src/main/java/com/github/housepower/jdbc/serializer/BinarySerializer.java
+++ b/src/main/java/com/github/housepower/jdbc/serializer/BinarySerializer.java
@@ -4,13 +4,10 @@ import com.github.housepower.jdbc.buffer.BuffedWriter;
 import com.github.housepower.jdbc.buffer.CompressedBuffedWriter;
 import com.github.housepower.jdbc.buffer.SocketBuffedWriter;
 import com.github.housepower.jdbc.misc.Container;
-import com.github.housepower.jdbc.misc.StringView;
-import com.github.housepower.jdbc.misc.StringViewCoding;
 import com.github.housepower.jdbc.settings.ClickHouseDefines;
 
 import java.io.IOException;
 import java.net.Socket;
-import java.sql.SQLException;
 
 public class BinarySerializer {
     private final Container<BuffedWriter> container;
@@ -18,7 +15,7 @@ public class BinarySerializer {
     public BinarySerializer(Socket socket) throws IOException {
         SocketBuffedWriter socketWriter = new SocketBuffedWriter(socket);
         container = new Container<BuffedWriter>(socketWriter,
-            new CompressedBuffedWriter(ClickHouseDefines.DEFAULT_BUFFER_SIZE, socketWriter));
+            new CompressedBuffedWriter(ClickHouseDefines.SOCKET_BUFFER_SIZE, socketWriter));
     }
 
     public void writeVarInt(long x) throws IOException {
@@ -111,9 +108,4 @@ public class BinarySerializer {
     public void writeBytes(byte[] bytes) throws IOException {
         container.get().writeBinary(bytes);
     }
-
-    public void writeStringViewBinary(StringView data) throws IOException, SQLException {
-        writeVarInt(data.end() - data.start());
-        container.get().writeBinary(StringViewCoding.bytes(data));
-    }
 }
diff --git a/src/main/java/com/github/housepower/jdbc/settings/ClickHouseDefines.java b/src/main/java/com/github/housepower/jdbc/settings/ClickHouseDefines.java
index 5ddded4..7182e29 100644
--- a/src/main/java/com/github/housepower/jdbc/settings/ClickHouseDefines.java
+++ b/src/main/java/com/github/housepower/jdbc/settings/ClickHouseDefines.java
@@ -7,7 +7,10 @@ public class ClickHouseDefines {
     public static final Integer MAJOR_VERSION = 1;
     public static final Integer MINOR_VERSION = 1;
     public static final Integer CLIENT_REVERSION = 54380;
-    public static final Integer DEFAULT_BUFFER_SIZE = 1048576;
     public static final Integer DBMS_MIN_REVISION_WITH_SERVER_TIMEZONE = 54058;
     public static final Integer DBMS_MIN_REVISION_WITH_SERVER_DISPLAY_NAME = 54372;
+
+    public static final int MAX_BLOCK_SIZE = 1048576 * 10;
+    public static int SOCKET_BUFFER_SIZE = 1048576;
+    public static int BUFFER_ROWS = 102400;
 }
diff --git a/src/main/java/com/github/housepower/jdbc/statement/AbstractPreparedStatement.java b/src/main/java/com/github/housepower/jdbc/statement/AbstractPreparedStatement.java
index 8666ab1..2c56011 100644
--- a/src/main/java/com/github/housepower/jdbc/statement/AbstractPreparedStatement.java
+++ b/src/main/java/com/github/housepower/jdbc/statement/AbstractPreparedStatement.java
@@ -81,8 +81,8 @@ public abstract class AbstractPreparedStatement extends ClickHouseStatement impl
 
     @Override
     public void setObject(int index, Object x) throws SQLException {
-        Validate.isTrue((index - 1) < parameters.length,
-            "Index " + index + " is out of bound in PreparedStatement, max index " + (parameters.length + 1));
+//        Validate.isTrue((index - 1) < parameters.length,
+//            "Index " + index + " is out of bound in PreparedStatement, max index " + (parameters.length + 1));
         parameters[index - 1] = x;
     }
 
diff --git a/src/main/java/com/github/housepower/jdbc/statement/ClickHousePreparedInsertStatement.java b/src/main/java/com/github/housepower/jdbc/statement/ClickHousePreparedInsertStatement.java
index cf0b338..142e420 100644
--- a/src/main/java/com/github/housepower/jdbc/statement/ClickHousePreparedInsertStatement.java
+++ b/src/main/java/com/github/housepower/jdbc/statement/ClickHousePreparedInsertStatement.java
@@ -1,29 +1,38 @@
 package com.github.housepower.jdbc.statement;
 
 import com.github.housepower.jdbc.ClickHouseConnection;
+import com.github.housepower.jdbc.misc.Slice;
 import com.github.housepower.jdbc.misc.Validate;
+import com.github.housepower.jdbc.settings.ClickHouseDefines;
 import com.github.housepower.jdbc.stream.ValuesWithParametersInputFormat;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
 
 public class ClickHousePreparedInsertStatement extends AbstractPreparedStatement {
 
     private final int posOfData;
     private final String fullQuery;
     private final String insertQuery;
-    private final List<Object[]> parameters;
+    private final Slice []columns;
+
+	private int maxRows = 0;
 
     public ClickHousePreparedInsertStatement(int posOfData, String fullQuery, ClickHouseConnection conn)
         throws SQLException {
         super(conn, null, computeQuestionMarkSize(fullQuery, posOfData));
+
+    	int parameterSize = computeQuestionMarkSize(fullQuery, posOfData);
         this.posOfData = posOfData;
         this.fullQuery = fullQuery;
-        this.parameters = new ArrayList<Object[]>();
         this.insertQuery = fullQuery.substring(0, posOfData);
+
+        this.columns = new Slice[parameterSize];
+        // TODO make a slicePool
+        for (int i = 0; i < parameterSize; ++i) {
+            this.columns[i] = new Slice(ClickHouseDefines.BUFFER_ROWS);
+		}
     }
 
     @Override
@@ -33,9 +42,9 @@ public class ClickHousePreparedInsertStatement extends AbstractPreparedStatement
 
     @Override
     public int executeUpdate() throws SQLException {
-        parameters.add(super.parameters);
-        return connection.sendInsertRequest(insertQuery,
-            new ValuesWithParametersInputFormat(fullQuery, posOfData, parameters));
+		addParameters();
+		return connection.sendInsertRequest(insertQuery,
+            new ValuesWithParametersInputFormat(fullQuery, posOfData, columns, maxRows));
     }
 
     @Override
@@ -46,20 +55,29 @@ public class ClickHousePreparedInsertStatement extends AbstractPreparedStatement
 
     @Override
     public void addBatch() throws SQLException {
-        parameters.add(super.parameters);
-        super.parameters = new Object[super.parameters.length];
+		addParameters();
     }
 
+    private void addParameters() throws SQLException {
+    	//ensure rows size
+		for (int i = 0; i < super.parameters.length; i++) {
+		    columns[i].add(super.parameters[i]);
+		}
+		maxRows ++;
+	}
+
     @Override
     public void clearBatch() throws SQLException {
-        parameters.clear();
-        super.parameters = new Object[super.parameters.length];
+    	maxRows = 0;
+    	for (int i = 0; i < columns.length; i++) {
+    	    columns[i] = columns[i].sub(0,0);
+        }
     }
 
     @Override
     public int[] executeBatch() throws SQLException {
         Integer rows = connection.sendInsertRequest(
-            insertQuery, new ValuesWithParametersInputFormat(fullQuery, posOfData, parameters));
+            insertQuery, new ValuesWithParametersInputFormat(fullQuery, posOfData, columns, maxRows));
         int[] result = new int[rows];
         Arrays.fill(result, -1);
         clearBatch();
diff --git a/src/main/java/com/github/housepower/jdbc/stream/ValuesInputFormat.java b/src/main/java/com/github/housepower/jdbc/stream/ValuesInputFormat.java
index 40455f5..4bd78c9 100644
--- a/src/main/java/com/github/housepower/jdbc/stream/ValuesInputFormat.java
+++ b/src/main/java/com/github/housepower/jdbc/stream/ValuesInputFormat.java
@@ -3,10 +3,10 @@ package com.github.housepower.jdbc.stream;
 import com.github.housepower.jdbc.data.Block;
 import com.github.housepower.jdbc.data.Column;
 import com.github.housepower.jdbc.misc.SQLLexer;
+import com.github.housepower.jdbc.misc.Slice;
 import com.github.housepower.jdbc.misc.Validate;
 
 import java.sql.SQLException;
-import java.util.Arrays;
 
 public class ValuesInputFormat implements InputFormat {
     private final SQLLexer lexer;
@@ -43,8 +43,9 @@ public class ValuesInputFormat implements InputFormat {
 
         Column[] columns = new Column[columnData.length];
         for (int i = 0; i < columns.length; i++) {
+            Slice slice = new Slice(columnData[i]);
             columns[i] = new Column(header.getByPosition(i).name(),
-                header.getByPosition(i).type(), Arrays.copyOf(columnData[i], rows));
+                header.getByPosition(i).type(), slice.sub(0, rows));
         }
         return new Block(rows, columns);
     }
diff --git a/src/main/java/com/github/housepower/jdbc/stream/ValuesWithParametersInputFormat.java b/src/main/java/com/github/housepower/jdbc/stream/ValuesWithParametersInputFormat.java
index af6d98f..6b28538 100644
--- a/src/main/java/com/github/housepower/jdbc/stream/ValuesWithParametersInputFormat.java
+++ b/src/main/java/com/github/housepower/jdbc/stream/ValuesWithParametersInputFormat.java
@@ -3,34 +3,37 @@ package com.github.housepower.jdbc.stream;
 import com.github.housepower.jdbc.data.Block;
 import com.github.housepower.jdbc.data.Column;
 import com.github.housepower.jdbc.misc.SQLLexer;
+import com.github.housepower.jdbc.misc.Slice;
 import com.github.housepower.jdbc.misc.Validate;
 
 import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
 
 public class ValuesWithParametersInputFormat implements InputFormat {
 
-    private final Iterator<Object[]> iterator;
+    private final Slice[] columns;
+    private final int maxRows;
 
     private SQLLexer lexer;
     private Object[] parametersInLexer;
     private boolean parsed;
+    private int currentRow;
 
     private final int pos;
     private final String query;
 
-    public ValuesWithParametersInputFormat(String query, int pos, List<Object[]> parameters)
+    public ValuesWithParametersInputFormat(String query, int pos, Slice[] columns,
+                                           int maxRows)
         throws SQLException {
         this.pos = pos;
         this.query = query;
-        this.iterator = parameters.iterator();
+        this.columns = columns;
+        this.currentRow = 0;
+        this.maxRows = maxRows;
         this.lexer = new SQLLexer(pos, query);
         this.parsed = false;
     }
 
-    private void parseLexer(Block header) throws SQLException{
+    private void parseLexer(Block header) throws SQLException {
         parametersInLexer = new Object[header.columns()];
 
         char nextChar = lexer.character();
@@ -41,7 +44,8 @@ public class ValuesWithParametersInputFormat implements InputFormat {
             }
 
             if (!lexer.isCharacter('?')) {
-                parametersInLexer[column] =  header.getByPosition(column).type().deserializeTextQuoted(lexer);
+                parametersInLexer[column] =
+                    header.getByPosition(column).type().deserializeTextQuoted(lexer);
             } else {
                 lexer.character();
             }
@@ -51,36 +55,29 @@ public class ValuesWithParametersInputFormat implements InputFormat {
     }
 
     @Override
-    public Block next(Block header, int maxRows) throws SQLException {
-        Object[][] columnData = new Object[header.columns()][maxRows];
-
+    public Block next(Block header, int blockMaxRows) throws SQLException {
         if (!parsed) {
             parseLexer(header);
         }
 
-        for (int row = 0; row < maxRows; row++) {
-            if (!iterator.hasNext()) {
-                return newPreparedBlock(header, row, columnData);
-            }
-            int idx = 0;
-            Object[] params = iterator.next();
-            for (int column = 0; column < header.columns(); column++) {
-                columnData[column][row]  = parametersInLexer[column] == null? params[idx++] : parametersInLexer[column];
-            }
-        }
-        return newPreparedBlock(header, maxRows, columnData);
-    }
+        int numRows = Math.min(blockMaxRows, maxRows - currentRow);
+        Column[] cols = new Column[header.columns()];
 
-    private Block newPreparedBlock(Block header, int rows, Object[][] columnData)
-        throws SQLException {
-        Validate.isTrue(header.columns() == columnData.length, "");
-
-        Column[] columns = new Column[columnData.length];
-        for (int i = 0; i < columns.length; i++) {
-            columns[i] = new Column(header.getByPosition(i).name(),
-                                    header.getByPosition(i).type(),
-                                    Arrays.copyOf(columnData[i], rows));
+        int j = 0;
+        for (int idx = 0; idx < cols.length; idx ++) {
+            if (parametersInLexer == null || parametersInLexer[idx] == null) {
+                cols[idx] = new Column(header.getByPosition(idx).name(),
+                                     header.getByPosition(idx).type(),
+                                     columns[j].sub(currentRow, currentRow + numRows));
+                j ++;
+            } else {
+                // set other parameters to const columns
+                cols[idx] = new Column(header.getByPosition(idx).name(),
+                                     header.getByPosition(idx).type(),
+                                     parametersInLexer[idx], maxRows);
+            }
         }
-        return new Block(rows, columns);
+        currentRow += numRows;
+        return new Block(numRows, cols);
     }
 }


Test patch:
diff --git a/src/test/java/com/github/housepower/jdbc/AbstractITest.java b/src/test/java/com/github/housepower/jdbc/AbstractITest.java
index 3006bf7..1ad32cb 100644
--- a/src/test/java/com/github/housepower/jdbc/AbstractITest.java
+++ b/src/test/java/com/github/housepower/jdbc/AbstractITest.java
@@ -1,13 +1,22 @@
 package com.github.housepower.jdbc;
 
 import java.sql.Connection;
+import java.sql.Driver;
 import java.sql.DriverManager;
+import java.util.Enumeration;
 
 public abstract class AbstractITest {
 
     private static final int SERVER_PORT = Integer.valueOf(System.getProperty("CLICK_HOUSE_SERVER_PORT", "9000"));
 
     protected void withNewConnection(WithConnection withConnection, Object ...args) throws Exception {
+        // deregisterDriver other jdbc drivers
+        Enumeration<Driver> drivers = DriverManager.getDrivers();
+        while (drivers.hasMoreElements()) {
+            DriverManager.deregisterDriver(drivers.nextElement());
+        }
+        DriverManager.registerDriver(new ClickHouseDriver());
+
         Class.forName("com.github.housepower.jdbc.ClickHouseDriver");
         String connectionStr = "jdbc:clickhouse://127.0.0.1:" + SERVER_PORT;
 
diff --git a/src/test/java/com/github/housepower/jdbc/BatchInsertITest.java b/src/test/java/com/github/housepower/jdbc/BatchInsertITest.java
index cd8c410..d7f385d 100644
--- a/src/test/java/com/github/housepower/jdbc/BatchInsertITest.java
+++ b/src/test/java/com/github/housepower/jdbc/BatchInsertITest.java
@@ -55,8 +55,8 @@ public class BatchInsertITest extends AbstractITest {
                 Statement statement = connection.createStatement();
 
                 statement.execute("DROP TABLE IF EXISTS test");
-                statement.execute("CREATE TABLE test(name Array(String), value Array(Float64), value2 Array(Array(Float64)) )ENGINE=Log");
-                PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO test VALUES(?, ?, [[]] )");
+                statement.execute("CREATE TABLE test(name Array(String), value Array(Float64))ENGINE=Log");
+                PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO test VALUES(?, ?)");
 
                 List<String> array = Arrays.asList("aa", "bb", "cc");
                 List<Double> array2 = Arrays.asList(1.2, 2.2, 3.2);
@@ -64,6 +64,7 @@ public class BatchInsertITest extends AbstractITest {
                 for (int i = 0; i < Byte.MAX_VALUE; i++) {
                     preparedStatement.setArray(1, connection.createArrayOf("text", array.toArray()));
                     preparedStatement.setArray(2, connection.createArrayOf("text", array2.toArray()));
+
                     preparedStatement.addBatch();
                 }
 
diff --git a/src/test/java/com/github/housepower/jdbc/DecimalTypeTest.java b/src/test/java/com/github/housepower/jdbc/DecimalTypeITest.java
similarity index 97%
rename from src/test/java/com/github/housepower/jdbc/DecimalTypeTest.java
rename to src/test/java/com/github/housepower/jdbc/DecimalTypeITest.java
index 81818a2..cbe340d 100644
--- a/src/test/java/com/github/housepower/jdbc/DecimalTypeTest.java
+++ b/src/test/java/com/github/housepower/jdbc/DecimalTypeITest.java
@@ -7,7 +7,7 @@ import java.sql.*;
 
 import static org.junit.Assert.assertEquals;
 
-public class DecimalTypeTest extends AbstractITest {
+public class DecimalTypeITest extends AbstractITest {
 
     @Test
     public void testDecimalType() throws Exception {
diff --git a/src/test/java/com/github/housepower/jdbc/InsertComplexTypeITest.java b/src/test/java/com/github/housepower/jdbc/InsertComplexTypeITest.java
index ad9fd40..49d92a4 100644
--- a/src/test/java/com/github/housepower/jdbc/InsertComplexTypeITest.java
+++ b/src/test/java/com/github/housepower/jdbc/InsertComplexTypeITest.java
@@ -3,8 +3,12 @@ package com.github.housepower.jdbc;
 import org.junit.Assert;
 import org.junit.Test;
 
-import java.sql.*;
-import java.util.TimeZone;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.sql.Timestamp;
 
 public class InsertComplexTypeITest extends AbstractITest {
 
@@ -68,7 +72,7 @@ public class InsertComplexTypeITest extends AbstractITest {
                 Assert.assertTrue(rs.next());
                 Assert.assertEquals(rs.getByte(1), 0);
                 Assert.assertTrue(rs.wasNull());
-                statement.executeQuery("DROP TABLE IF EXISTS test");
+//                statement.executeQuery("DROP TABLE IF EXISTS test");
             }
         });
     }
diff --git a/src/test/java/com/github/housepower/jdbc/benchmark/AbstractIBenchmark.java b/src/test/java/com/github/housepower/jdbc/benchmark/AbstractIBenchmark.java
new file mode 100644
index 0000000..e411cae
--- /dev/null
+++ b/src/test/java/com/github/housepower/jdbc/benchmark/AbstractIBenchmark.java
@@ -0,0 +1,52 @@
+package com.github.housepower.jdbc.benchmark;
+
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.util.Enumeration;
+
+
+public abstract class AbstractIBenchmark {
+
+    private static final int SERVER_PORT = Integer.valueOf(System.getProperty("CLICK_HOUSE_SERVER_PORT", "9000"));
+    private static final int SERVER_HTTP_PORT = Integer.valueOf(System.getProperty("CLICK_HOUSE_SERVER_HTTP_PORT", "8123"));
+
+    private final Driver httpDriver = new ru.yandex.clickhouse.ClickHouseDriver();
+    private final Driver nativeDriver = new com.github.housepower.jdbc.ClickHouseDriver();
+
+    protected void withConnection(WithConnection withConnection, ConnectionType connectionType) throws Exception {
+        int port = SERVER_PORT;
+
+        Enumeration<Driver> drivers = DriverManager.getDrivers();
+        while (drivers.hasMoreElements()) {
+            DriverManager.deregisterDriver(drivers.nextElement());
+        }
+
+        switch (connectionType) {
+            case HTTP:
+                Class.forName("ru.yandex.clickhouse.ClickHouseDriver");
+                DriverManager.registerDriver(httpDriver);
+                port = SERVER_HTTP_PORT;
+                break;
+
+            case NATIVE:
+                Class.forName("com.github.housepower.jdbc.ClickHouseDriver");
+                DriverManager.registerDriver(nativeDriver);
+                break;
+        }
+        Connection connection = DriverManager.getConnection("jdbc:clickhouse://127.0.0.1:" + port);
+        try {
+            withConnection.apply(connection);
+        } finally {
+            connection.close();
+        }
+    }
+
+    public interface WithConnection {
+        void apply(Connection connection) throws Exception;
+    }
+
+    public enum ConnectionType {
+        NATIVE, HTTP
+    }
+}
diff --git a/src/test/java/com/github/housepower/jdbc/benchmark/InsertIBenchmark.java b/src/test/java/com/github/housepower/jdbc/benchmark/InsertIBenchmark.java
new file mode 100644
index 0000000..a9e0cad
--- /dev/null
+++ b/src/test/java/com/github/housepower/jdbc/benchmark/InsertIBenchmark.java
@@ -0,0 +1,67 @@
+package com.github.housepower.jdbc.benchmark;
+
+import com.carrotsearch.junitbenchmarks.BenchmarkOptions;
+import com.carrotsearch.junitbenchmarks.BenchmarkRule;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.PreparedStatement;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ */
+public class InsertIBenchmark extends AbstractIBenchmark{
+    AtomicInteger tableMaxId = new AtomicInteger();
+
+    @Rule
+    public TestRule benchmarkRun = new BenchmarkRule();
+
+    public WithConnection benchInsert = new WithConnection(){
+        @Override
+        public void apply(Connection connection) throws Exception {
+            int batchSize = 1000000;
+            Timestamp ts = new Timestamp(System.currentTimeMillis());
+            Date date = new Date(ts.getTime());
+
+            Statement stmt = connection.createStatement();
+
+            int tableId = tableMaxId.getAndIncrement();
+            String testTable = "test_" + tableId;
+
+            stmt.executeQuery("DROP TABLE IF EXISTS " + testTable);
+            stmt.executeQuery("CREATE TABLE " + testTable +" (number UInt32, name String, birthTime DateTime, birthDay Date) Engine = Log");
+            PreparedStatement pstmt = connection.prepareStatement("INSERT INTO "  + testTable +" values(?, ?, ?, ?)");
+
+
+            for (int i = 0; i < batchSize; i++) {
+                pstmt.setInt(1, i);
+                pstmt.setString(2, "i_am_a_string");
+                pstmt.setTimestamp(3, ts);
+                pstmt.setDate(4, date);
+                pstmt.addBatch();
+            }
+            int []res = pstmt.executeBatch();
+            Assert.assertEquals(res.length, batchSize);
+            stmt.executeQuery("DROP TABLE " + testTable);
+        }
+    };
+
+    @BenchmarkOptions(benchmarkRounds = 2, warmupRounds = 0, concurrency = 1)
+    @Test
+    public void benchInsertNative() throws Exception {
+        withConnection(benchInsert, ConnectionType.NATIVE);
+    }
+
+    @BenchmarkOptions(benchmarkRounds = 2, warmupRounds = 0, concurrency = 1)
+    @Test
+    public void benchInsertHttp() throws Exception {
+        withConnection(benchInsert, ConnectionType.HTTP);
+    }
+}
diff --git a/src/test/java/com/github/housepower/jdbc/benchmark/ProfileBenchmark.java b/src/test/java/com/github/housepower/jdbc/benchmark/ProfileBenchmark.java
new file mode 100644
index 0000000..015c83a
--- /dev/null
+++ b/src/test/java/com/github/housepower/jdbc/benchmark/ProfileBenchmark.java
@@ -0,0 +1,75 @@
+package com.github.housepower.jdbc.benchmark;
+
+/**
+ */
+
+import org.junit.Test;
+
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+/**
+ */
+public class ProfileBenchmark extends AbstractIBenchmark{
+    private static long n = 10000000;
+    private static long statsOutputFrequency = 10;
+
+    public WithConnection benchSelectSumInt = connection -> {
+        Statement statement = connection.createStatement();
+        ResultSet rs = statement.executeQuery(String.format("SELECT number as n1 from numbers(%d)", n));
+
+        long sum = 0;
+        long counter = 0;
+
+        Profiler.getInstance().logStat(0, 0);
+        while (rs.next()) {
+            counter++;
+            if (counter % (n / statsOutputFrequency) == 0) {
+                long percentComplete = (long) ((((double) counter) / n) * 100);
+                Profiler.getInstance().logStat(percentComplete, 1);
+            }
+            sum += rs.getLong(1);
+        }
+        System.out.println(sum);
+    };
+
+    public WithConnection benchSelectSumDouble = connection -> {
+        Statement statement = connection.createStatement();
+        ResultSet rs = statement.executeQuery(String.format("SELECT number/rand64() as n1 from numbers(%d)", n));
+
+        double sum = 0;
+        long counter = 0;
+
+        Profiler.getInstance().logStat(0, 0);
+        while (rs.next()) {
+            counter++;
+            if (counter % (n / statsOutputFrequency) == 0) {
+                long percentComplete = (long) ((((double) counter) / n) * 100);
+                Profiler.getInstance().logStat(percentComplete, 1);
+            }
+            sum += rs.getDouble(1);
+        }
+        System.out.println(sum);
+    };
+
+    @Test
+    public void profileSumIntNative() throws Exception {
+        withConnection(benchSelectSumInt, ConnectionType.NATIVE);
+    }
+
+    @Test
+    public void profileSumIntHttp() throws Exception {
+        withConnection(benchSelectSumInt, ConnectionType.HTTP);
+    }
+
+    @Test
+    public void profileSumDoubleNative() throws Exception {
+        withConnection(benchSelectSumDouble, ConnectionType.NATIVE);
+    }
+
+    @Test
+    public void profileSumDoubleHttp() throws Exception {
+        withConnection(benchSelectSumDouble, ConnectionType.HTTP);
+    }
+}
+
diff --git a/src/test/java/com/github/housepower/jdbc/benchmark/Profiler.java b/src/test/java/com/github/housepower/jdbc/benchmark/Profiler.java
new file mode 100644
index 0000000..d61617b
--- /dev/null
+++ b/src/test/java/com/github/housepower/jdbc/benchmark/Profiler.java
@@ -0,0 +1,79 @@
+package com.github.housepower.jdbc.benchmark;
+
+/**
+ * From https://gist.github.com/gothug/3b35fe0cec302efe6f8314a9cab8865e
+ */
+public class Profiler {
+    public class ElapsedTime {
+        private long elapsedTimeMillis;
+        private long elapsedTimeDeltaMillis;
+
+        public long getElapsedTimeMillis() { return elapsedTimeMillis; }
+        public long getElapsedTimeDeltaMillis() { return elapsedTimeDeltaMillis; }
+
+        public ElapsedTime(long etMillis, long etDeltaMillis) {
+            elapsedTimeMillis = etMillis;
+            elapsedTimeDeltaMillis = etDeltaMillis;
+        }
+    }
+
+    private static final long MEGABYTE = 1024L * 1024L;
+
+    public static long bytesToMegabytes(long bytes) {
+        return bytes / MEGABYTE;
+    }
+
+    public static String fixedLengthString(String string, int length) {
+        return String.format("%1$"+length+ "s", string);
+    }
+
+
+    long startTimeMillis;
+    long lastEventTimeMillis;
+    Runtime runtime;
+
+    private static final Profiler _instance = new Profiler();
+
+    public static synchronized Profiler getInstance() {
+        return _instance;
+    }
+
+    private Profiler() {
+        startTimeMillis = System.currentTimeMillis();
+        lastEventTimeMillis = startTimeMillis;
+        runtime = Runtime.getRuntime();
+    }
+
+    public void start() {
+        System.out.println("Profiler started");
+    }
+
+    private ElapsedTime getElapsedTime() {
+        long now = System.currentTimeMillis();
+        long elapsedMillis = now - startTimeMillis;
+        long elapsedDeltaMillis = now - lastEventTimeMillis;
+        lastEventTimeMillis = now;
+        return new ElapsedTime(elapsedMillis, elapsedDeltaMillis);
+    }
+
+    public void logStat(long percentComplete, int runGc) {
+        if (runGc == 1) {
+            runtime.gc();
+        }
+        // Calculate the used memory
+        long totalMemory = runtime.totalMemory();
+        long memory = totalMemory - runtime.freeMemory();
+
+        ElapsedTime elapsedTime = getElapsedTime();
+        long elapsedMillis = elapsedTime.getElapsedTimeMillis();
+        long elapsedDeltaMillis = elapsedTime.getElapsedTimeDeltaMillis();
+
+        String percentCompleteStr = fixedLengthString(String.valueOf(percentComplete), 3) + "%";
+        String totalMemoryStr = fixedLengthString(String.valueOf(bytesToMegabytes(totalMemory)), 5);
+        String usedMemoryStr = fixedLengthString(String.valueOf(bytesToMegabytes(memory)), 5);
+        String totalElapsedMillisStr = fixedLengthString(String.valueOf(elapsedMillis), 6);
+        String millisPassedFromLastLogStr = fixedLengthString(String.valueOf(elapsedDeltaMillis), 6);
+        System.out.println(percentCompleteStr + " Total memory (MB): " + totalMemoryStr + ", used memory (MB): "
+                           + usedMemoryStr + ", time elapsed: " + totalElapsedMillisStr + "(+" + millisPassedFromLastLogStr + " ms)");
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/com/github/housepower/jdbc/benchmark/SelectIBenchmark.java b/src/test/java/com/github/housepower/jdbc/benchmark/SelectIBenchmark.java
new file mode 100644
index 0000000..0a1ac6d
--- /dev/null
+++ b/src/test/java/com/github/housepower/jdbc/benchmark/SelectIBenchmark.java
@@ -0,0 +1,47 @@
+package com.github.housepower.jdbc.benchmark;
+
+import com.carrotsearch.junitbenchmarks.BenchmarkOptions;
+import com.carrotsearch.junitbenchmarks.BenchmarkRule;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+/**
+ */
+public class SelectIBenchmark extends AbstractIBenchmark {
+
+    @Rule
+    public TestRule benchmarkRun = new BenchmarkRule();
+
+    public WithConnection benchSelect = connection -> {
+        long sum = 0;
+        Statement statement = connection.createStatement();
+        long number = 1000000;
+        ResultSet rs = statement.executeQuery(String.format("SELECT number as n1, 'i_am_a_string' , now(), today() from numbers(%d)", number));
+        while (rs.next()) {
+            sum += rs.getInt(1);
+
+            rs.getString(2);
+            rs.getTimestamp(3);
+            rs.getDate(4);
+        }
+        Assert.assertEquals((number-1) * number / 2, sum);
+    };
+
+    @BenchmarkOptions(benchmarkRounds = 2, warmupRounds = 0)
+    @Test
+    public void benchSelectNative() throws Exception {
+        withConnection(benchSelect, ConnectionType.NATIVE);
+    }
+
+    @BenchmarkOptions(benchmarkRounds = 2, warmupRounds = 0)
+    @Test
+    public void benchSelectHTTP() throws Exception {
+        withConnection(benchSelect, ConnectionType.HTTP);
+    }
+}
diff --git a/src/test/java/com/github/housepower/jdbc/benchmark/WideColumnInsertIBenchmark.java b/src/test/java/com/github/housepower/jdbc/benchmark/WideColumnInsertIBenchmark.java
new file mode 100644
index 0000000..1c1ef45
--- /dev/null
+++ b/src/test/java/com/github/housepower/jdbc/benchmark/WideColumnInsertIBenchmark.java
@@ -0,0 +1,76 @@
+package com.github.housepower.jdbc.benchmark;
+
+import com.google.common.base.Strings;
+
+import com.carrotsearch.junitbenchmarks.BenchmarkOptions;
+import com.carrotsearch.junitbenchmarks.BenchmarkRule;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.Statement;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ */
+public class WideColumnInsertIBenchmark extends AbstractIBenchmark{
+    private static final int COLUMN_NUM = 50;
+    private static final int BATCH_SZIE = 200000;
+
+    AtomicInteger tableMaxId = new AtomicInteger();
+
+    @Rule
+    public TestRule benchmarkRun = new BenchmarkRule();
+
+    public WithConnection benchInsert = new WithConnection(){
+        @Override
+        public void apply(Connection connection) throws Exception {
+            Statement stmt = connection.createStatement();
+
+            int tableId = tableMaxId.getAndIncrement();
+            String testTable = "test2_" + tableId;
+
+
+            stmt.executeQuery("DROP TABLE IF EXISTS " + testTable);
+            String createSQL = "CREATE TABLE " + testTable + " (";
+            for (int i = 0; i < COLUMN_NUM; i++) {
+                createSQL += "col_" + i + " String";
+                if (i + 1 != COLUMN_NUM) {
+                    createSQL += ",\n";
+                }
+            }
+            createSQL += ") Engine = Log";
+
+            stmt.executeQuery(createSQL);
+            String params = Strings.repeat("?, ", COLUMN_NUM);
+            PreparedStatement pstmt = connection.prepareStatement("INSERT INTO "  + testTable +" values("   + params.substring(0, params.length()-2) + ")");
+
+
+            for (int i = 0; i < BATCH_SZIE; i++) {
+                for (int j = 0; j < COLUMN_NUM; j++ ) {
+                    pstmt.setString(j + 1, j + 1 + "");
+                }
+                pstmt.addBatch();
+            }
+            int []res = pstmt.executeBatch();
+            Assert.assertEquals(res.length, BATCH_SZIE);
+            stmt.executeQuery("DROP TABLE " + testTable);
+        }
+    };
+
+    @BenchmarkOptions(benchmarkRounds = 1, warmupRounds = 0, concurrency = 1)
+    @Test
+    public void benchInsertNative() throws Exception {
+        withConnection(benchInsert, ConnectionType.NATIVE);
+    }
+
+    @BenchmarkOptions(benchmarkRounds = 1, warmupRounds = 0, concurrency = 1)
+    @Test
+    public void benchInsertHttp() throws Exception {
+        withConnection(benchInsert, ConnectionType.HTTP);
+    }
+}