一个优秀的程序员不仅要鲁的一手好的代码,更要写的出一手优质的SQL语句。
下面讲讲sql究竟是如何做到优化的。
前期准备工作:
1.海量数据的生成
a.
public class DataGenerator {
private final static String PARAM_IP = "localhost"; //数据库IP地址,本机使用localhost
private final static String PARAM_USERNAME = "icbc"; //数据库用户名
private final static String PARAM_PASSWORD = "icbc";//数据库密码
private final static String PARAM_SID = "orcl";//数据库sid
private final static String PARAM_PORT = "1521"; //端口号
private final static boolean FORCE_REBUILD = true; // 建表前是否删除已经存在的对象,默认为true
private final static int ROW_COUNT = 100000; //创建数据库的条数
private Logger logger ;
public DataGenerator(){
logger = Logger.getLogger(this.getClass().getName());
}
/**
* 获取数据连接
* @return Connection 数据库连接对象
* @version 1.0
* @since 1.6.0
* @deprecated
* @see http://www.baidu.com
* @throws DBException
* 数据操作异常
*/
private Connection getConnection() throws DBException {
Connection conn = null;
String url = null;
try {
url = "jdbc:oracle:thin:@" + DataGenerator.PARAM_IP + ":"
+ DataGenerator.PARAM_PORT + ":" + DataGenerator.PARAM_SID;
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection(url,
DataGenerator.PARAM_USERNAME, DataGenerator.PARAM_PASSWORD);
conn.setAutoCommit(false);
} catch (Exception e) {
throw new DBException("数据库连接[" + url + "]创建失败", e);
}
return conn;
}
/**
* 创建T_CARD_OP_LOG表
*
* @throws DBException
*/
public void createCOLTable(boolean forceRebuild) throws DBException {
try {
Connection conn = this.getConnection();
Statement stmt = conn.createStatement();
if (forceRebuild == true) {
logger.info("正在删除已存在对象");
try {
stmt.execute("drop table T_CARD_OP_LOG");
stmt.execute("drop sequence SEQ_CARD_OP_LOG");
} catch (SQLException e) {
logger.info("T_CARD_OP_LOG表不存在,忽略删除操作");
}
}
String createCOLSQL = "create table T_CARD_OP_LOG(OP_ID NUMBER(12) not null,CARD_NO VARCHAR2(19) ,OPER_NO NUMBER(4),AMT NUMBER(12,2) ,OP_DATE DATE )";
stmt.execute(createCOLSQL);
String createCOLPKSQL = "alter table T_CARD_OP_LOG add constraint PK_OP_ID primary key (OP_ID)";
stmt.execute(createCOLPKSQL);
String createCOLSeqSQL = "create sequence SEQ_CARD_OP_LOG minvalue 1 maxvalue 999999999999999999999999999 start with 1 increment by 1 cache 20";
stmt.execute(createCOLSeqSQL);
stmt.close();
conn.close();
} catch (Exception e) {
throw new DBException("T_CARD_OP_LOG表创建失败", e);
}
}
/**
* 初始化T_CARD_OP_LOG数据
*
* @throws DBException
*/
private void insertColTable() throws DBException {
try {
Connection conn = this.getConnection();
String sql = "INSERT INTO t_card_op_log(op_id , card_no , oper_no , amt , op_date) "
+ "values ([id] , ‘[cardbin][area][cardno]‘ , ‘[operno]‘ , ‘[amt]‘ , to_date(‘201405[date]‘ , ‘yyyymmdd‘))";
List<String> cardBin = new ArrayList();
// 牡丹灵通卡
cardBin.add("955880");
cardBin.add("955881");
// E时代
cardBin.add("955882");
cardBin.add("622202");
cardBin.add("622203");
// 理财金
cardBin.add("955888");
// 将CardBin数据调节成非均匀分布
for (int i = 1; i <= 30; i++) {
cardBin.add("622202");
}
List<String> areas = new ArrayList<String>();
areas.add("0402");// 石家庄
areas.add("0403");// 唐山
areas.add("0404");// 秦皇岛
areas.add("0405");// 邯郸
areas.add("0406");// 邢台
areas.add("0407");// 衡水
areas.add("0408");// 沧州
areas.add("0409");// 保定
areas.add("0410");// 廊坊
areas.add("0411");// 承德
areas.add("0412");// 张家口
// 将区域数据调节成非均匀分布
for (int i = 1; i <= 30; i++) {
areas.add("0402");
}
List<String> opno = new ArrayList();
opno.add("1314");// POS消费
opno.add("1315");// 存款
opno.add("1316");// 取款
opno.add("1317");// 转账
// 将交易数据调节成非均匀分布
for (int i = 1; i <= 30; i++) {
opno.add("1316");
}
logger.info("开始初始化T_CARD_NO_LOG数据");
for (int i = 1; i <= DataGenerator.ROW_COUNT; i++) {
int cardBinIndex = new Double((Math.random() * 100)).intValue()
% cardBin.size();
int areaIndex = new Double((Math.random() * 100)).intValue()
% areas.size();
int opnoIndex = new Double((Math.random() * 100)).intValue()
% opno.size();
String cardNo = new DecimalFormat("000000000")
.format(new Double((Math.random() * 10000)).intValue());
int amt = new Double((Math.random() * 1000000)).intValue();
int date = (new Double((Math.random() * 1000)).intValue() % 31) + 1;
String executeSQL = new String(sql);
executeSQL = executeSQL
.replace("[id]", "seq_card_op_log.nextval")
.replace("[cardbin]", cardBin.get(cardBinIndex))
.replace("[area]", areas.get(areaIndex))
.replace("[cardno]", cardNo)
.replace("[operno]", opno.get(opnoIndex))
.replace("[amt]", String.valueOf(amt))
.replace("[date]", String.valueOf(date));
Statement stmt = conn.createStatement();
stmt.execute(executeSQL);
stmt.close();
if (i % 1000 == 0) {
System.out.println("Rows : " + i);
}
}
conn.commit();
logger.info("T_CARD_NO_LOG数据初始化成功");
} catch (Exception e) {
// TODO Auto-generated catch block
throw new DBException("初始化T_CARD_OP_LOG数据失败", e);
}
}
// 初始化数据
public void init() throws DBException {
// 初始化
try {
this.createCOLTable(DataGenerator.FORCE_REBUILD);
this.insertColTable();
} catch (DBException e) {
throw e;
}
}
public static void main(String[] args) {
DataGenerator gen = new DataGenerator();
try {
gen.init();
} catch (Exception e) {
e.printStackTrace();
}
}
}
b
public class DBException extends Exception {
private DBException() {
}
public DBException(String msg, Exception e) {
super(msg, e);
}
}
文件结构
2.oracle用户的创建
3 优化
(1)select * from t_card_op_log where oper_no=‘1314‘怎么优化呢?
建立字段号的索引:
create index idx_col_operno on t_card_op_log(oper_no)
2组合索引
3函数索引