主键一般使用序列或者UUID
使用UUID主要优点是分布式环境下,主键不会重复;缺点是性能相对较低。
序列则相反,他在分布式环境下会重复,但是性能较高。
实验分别测试序列,UUID,使用RAW类型的UUID,测试100W数据插入的时间。
创建实验所需的表
-
drop table test_seq purge;
-
drop table test_uuid purge;
-
drop table test_uuid_raw purge;
-
-
--测试序列
-
create table test_seq(t_id number(8) primary key );
-
--测试UUID
-
create table test_uuid(t_id varchar2(32) primary key);
-
--测试UUID RAW
-
create table test_uuid_raw(t_id raw(16) primary key);
-
-
drop sequence seq;
-
-
create sequence seq
-
increment by 1
-
start with 1
-
cache 300;
-
import java.sql.Connection;
-
import java.sql.DriverManager;
-
import java.sql.PreparedStatement;
-
import java.sql.SQLException;
-
import java.util.UUID;
-
-
import org.apache.commons.codec.DecoderException;
-
import org.apache.commons.codec.binary.Hex;
-
-
public class PrimaryKeyTest {
-
private static int _1W = 10000;
-
private static int COUNT = _1W * 100;
-
private static String URL = "jdbc:oracle:thin:127.0.0.1:1521:orcl";
-
private static String USERNAME = "edmond";
-
private static String PWD = "edmond";
-
-
private static void insertSeq() throws SQLException {
-
System.out.println("测试序列:");
-
long start = System.currentTimeMillis();
-
long end;
-
Connection con = DriverManager.getConnection(URL, USERNAME, PWD);
-
con.setAutoCommit(false);
-
PreparedStatement ps = con.prepareStatement("insert into test_seq(t_id) values(seq.nextval)");
-
for (int i = 0; i < COUNT; i++) {
-
if (i == _1W) {
-
end = System.currentTimeMillis();
-
System.out.println("1W:" + (end - start));
-
} else if (i == _1W * 10) {
-
end = System.currentTimeMillis();
-
System.out.println("10W:" + (end - start));
-
} else if (i == _1W * 20) {
-
end = System.currentTimeMillis();
-
System.out.println("20W:" + (end - start));
-
} else if (i == _1W * 50) {
-
end = System.currentTimeMillis();
-
System.out.println("50W:" + (end - start));
-
} else if (i == _1W * 80) {
-
end = System.currentTimeMillis();
-
System.out.println("80W:" + (end - start));
-
}
-
-
ps.addBatch();
-
if (i % (10 * _1W) == 0) {
-
ps.executeBatch();
-
}
-
}
-
ps.executeBatch();
-
con.commit();
-
ps.close();
-
con.close();
-
-
end = System.currentTimeMillis();
-
System.out.println("100W:" + (end - start));
-
-
}
-
-
private static void insertUUID() throws SQLException {
-
System.out.println("测试UUID:");
-
long start = System.currentTimeMillis();
-
long end;
-
Connection con = DriverManager.getConnection(URL, USERNAME, PWD);
-
con.setAutoCommit(false);
-
PreparedStatement ps = con.prepareStatement("insert into test_uuid(t_id) values(?)");
-
for (int i = 0; i < COUNT; i++) {
-
if (i == _1W) {
-
end = System.currentTimeMillis();
-
System.out.println("1W:" + (end - start));
-
} else if (i == _1W * 10) {
-
end = System.currentTimeMillis();
-
System.out.println("10W:" + (end - start));
-
} else if (i == _1W * 20) {
-
end = System.currentTimeMillis();
-
System.out.println("20W:" + (end - start));
-
} else if (i == _1W * 50) {
-
end = System.currentTimeMillis();
-
System.out.println("50W:" + (end - start));
-
} else if (i == _1W * 80) {
-
end = System.currentTimeMillis();
-
System.out.println("80W:" + (end - start));
-
}
-
-
String id = UUID.randomUUID().toString().replaceAll("-", "");
-
ps.setString(1, id);
-
ps.addBatch();
-
-
if (i % (10 * _1W) == 0) {
-
ps.executeBatch();
-
}
-
}
-
ps.executeBatch();
-
con.commit();
-
ps.close();
-
con.close();
-
-
end = System.currentTimeMillis();
-
System.out.println("100W:" + (end - start));
-
-
}
-
-
private static void insertUUIDRaw() throws SQLException, DecoderException {
-
System.out.println("测试UUID RAW:");
-
long start = System.currentTimeMillis();
-
long end;
-
Connection con = DriverManager.getConnection(URL, USERNAME, PWD);
-
con.setAutoCommit(false);
-
PreparedStatement ps = con.prepareStatement("insert into test_uuid_raw(t_id) values(?)");
-
for (int i = 0; i < COUNT; i++) {
-
if (i == _1W) {
-
end = System.currentTimeMillis();
-
System.out.println("1W:" + (end - start));
-
} else if (i == _1W * 10) {
-
end = System.currentTimeMillis();
-
System.out.println("10W:" + (end - start));
-
} else if (i == _1W * 20) {
-
end = System.currentTimeMillis();
-
System.out.println("20W:" + (end - start));
-
} else if (i == _1W * 50) {
-
end = System.currentTimeMillis();
-
System.out.println("50W:" + (end - start));
-
} else if (i == _1W * 80) {
-
end = System.currentTimeMillis();
-
System.out.println("80W:" + (end - start));
-
}
-
-
byte[] data = Hex.decodeHex(UUID.randomUUID().toString().replaceAll("-", "").toCharArray());
-
ps.setBytes(1, data);
-
ps.addBatch();
-
-
if (i % (10 * _1W) == 0) {
-
ps.executeBatch();
-
}
-
}
-
ps.executeBatch();
-
con.commit();
-
ps.close();
-
con.close();
-
-
end = System.currentTimeMillis();
-
System.out.println("100W:" + (end - start));
-
}
-
-
public static void main(String[] args) throws ClassNotFoundException, SQLException, DecoderException {
-
Class.forName("oracle.jdbc.OracleDriver");
-
insertSeq();
-
insertUUID();
-
insertUUIDRaw();
-
}
-
}
测试结果如下:
|
|
1w
|
10w
|
20w
|
50w
|
80w
|
100w
|
|
序列
|
939
|
949
|
1584
|
3847
|
7732
|
12010
|
|
UUID Varchar2
|
2196
|
2915
|
14591
|
107528
|
861084
|
3051716
|
|
UUID RAW
|
607
|
1237
|
9302
|
37817
|
169935
|
986043
|

不同的主键方案,不仅对索引维护有性能影响,同时也对索引的使用造成影响。(UUID作为主键索引的value占用空间比序列大很多)。



同样的查询需求,都使用了主键索引,但是采用UUID作为主键,他的物理读和一致性读都远远超过了采用序列的情况。
所以如果没有分布式环境的需求(例如层级数据上报),可以尽量采用序列作为主键。
单纯就插入性能而言,序列>UUID RAW>UUID Varchar2
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29254281/viewspace-1066263/
,如需转载,请注明出处,否则将追究法律责任。