SqlComparison

package com.ufo.leftjoin;

import java.security.MessageDigest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.log4j.Logger;

// Used for JDBC connection to DB
class DBParam {
    public static final String Driver = "oracle.jdbc.driver.OracleDriver";
    public static final String DbUrl = "。。。。。。。。MSAPDB";
    public static final String User = "R。。。。。。。A_USER";
    public static final String Pswd = "FF。。。。。。。。wCP";
}

// Used for collection sort
class KeyValue implements Comparable<KeyValue> {
    String key;
    Object value;

    @Override
    public int compareTo(KeyValue another) {
        return this.key.compareTo(another.key);
    }
}

// Used for hold columns
class DhItem{
    String order_no;
    String shipper_code;
    String vehicle_name;
    String vehicle_code;
    String reason_name_mobile;
    String status_name_mobile;
    
    public String toString() {
        List<String> ls=new ArrayList<String>();
        
        ls.add(order_no);
        ls.add(shipper_code);
        ls.add(vehicle_name);
        ls.add(vehicle_code);
        ls.add(reason_name_mobile);
        ls.add(status_name_mobile);
        
        return String.join(",", ls);
    }
}

// Left jion/inner join comparison
public class SqlComparison {
    private static Logger log = Logger.getLogger(SqlComparison.class);

    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;

        try {
            Class.forName(DBParam.Driver).newInstance();
            Properties pro = new Properties();
            pro.setProperty("user", DBParam.User);// 这里不是username或是usr!
            pro.setProperty("password", DBParam.Pswd);// 这里不是pswd
            // pro.setProperty("initialSize", "10");
            // pro.setProperty("maxActive", "12");
            // pro.put("remarksReporting","true");// 这一句才能让rs.getString("REMARKS")起作用

            conn = DriverManager.getConnection(DBParam.DbUrl, pro);
            stmt = conn.createStatement();

            SqlComparison sc = new SqlComparison();

            sc.queryTotalCntinDH(stmt);
            sc.testLeftJoin(stmt);
            sc.testInnerJoin(stmt);
            
            sc.compareTwoPlan(stmt);
        } catch (Exception e) {
            System.out.print(e.getMessage());
            e.printStackTrace();
        } finally {
            try {
                stmt.close();
                conn.close();
            } catch (SQLException e) {
                log.error("Can't close stmt/conn because of " + e.getMessage());
            }
        }
    }
    
    /**
     * Compare left to inner
     * @param stmt
     * @throws SQLException
     */
    private void compareTwoPlan(Statement stmt) throws SQLException {
        long startMs = System.currentTimeMillis();
        
        String leftSql=getLeftjoinSql();
        Map<String,DhItem> leftMap=new HashMap<String,DhItem>();
        
        ResultSet rs = stmt.executeQuery(leftSql);
        while (rs.next()) {
            DhItem dhItem=new DhItem();
            dhItem.order_no=rs.getString("order_no");
            dhItem.shipper_code=rs.getString("shipper_code");
            dhItem.vehicle_name=rs.getString("vehicle_name");
            dhItem.vehicle_code=rs.getString("vehicle_code");
            dhItem.reason_name_mobile=rs.getString("reason_name_mobile");
            dhItem.status_name_mobile=rs.getString("status_name_mobile");
            leftMap.put(toMD5(dhItem.toString()), dhItem);
        }
        
        String innerSql=getNewInnerSql();
        Map<String,DhItem> innerMap=new HashMap<String,DhItem>();
        
        rs = stmt.executeQuery(innerSql);
        while (rs.next()) {
            DhItem dhItem=new DhItem();
            dhItem.order_no=rs.getString("order_no");
            dhItem.shipper_code=rs.getString("shipper_code");
            dhItem.vehicle_name=rs.getString("vehicle_name");
            dhItem.vehicle_code=rs.getString("vehicle_code");
            dhItem.reason_name_mobile=rs.getString("reason_name_mobile");
            dhItem.status_name_mobile=rs.getString("status_name_mobile");
            innerMap.put(toMD5(dhItem.toString()), dhItem);
        }
        
        List<DhItem> onlyInLeftLs=new ArrayList<DhItem>();
        int count=0;
        for(String key:leftMap.keySet()) {
            if(innerMap.containsKey(key)) {
                count++;
            }else {
                DhItem dhItem=leftMap.get(key);
                onlyInLeftLs.add(dhItem);
            }
        }
        
        log.info("There are "+toEastNumFormat(count)+" records in both left and inner.");
        log.info("There are "+toEastNumFormat(onlyInLeftLs.size())+" records only in left.");
        
        List<DhItem> onlyInInnerLs=new ArrayList<DhItem>();

        count=0;
        for(String key:innerMap.keySet()) {
            if(leftMap.containsKey(key)) {
                count++;
            }else {
                DhItem dhItem=innerMap.get(key);
                onlyInInnerLs.add(dhItem);
            }
        }
        
        log.info("There are "+toEastNumFormat(count)+" records in both left and inner.");
        log.info("There are "+toEastNumFormat(onlyInInnerLs.size())+" records only in inner.");
        
        long endMs = System.currentTimeMillis();
        log.info("It takes "+ms2DHMS(startMs,endMs)+" to run function:'compareTwoPlan'.");
    }
    
    private String getLeftjoinSql() {
        StringBuilder sb = new StringBuilder();
        sb.append("     SELECT                                              ");
        sb.append("      DH1.ORDER_NO,                                   ");
        sb.append("      DH1.SHIPPER_CODE ,                              ");
        sb.append("      DH1.VEHICLE_NAME,                               ");
        sb.append("      DH1.VEHICLE_CODE ,                              ");
        sb.append("      DH1.REASON_NAME_MOBILE,                         ");
        sb.append("      DH1.STATUS_NAME_MOBILE                          ");
        sb.append("  from                                                ");
        sb.append("      DELIVERY_HISTORY DH1                            ");
        sb.append("      left JOIN DELIVERY_HISTORY DH2 on               ");
        sb.append("      DH1.SHIPPER_CODE = DH2.SHIPPER_CODE             ");
        sb.append("      and DH1.ORDER_NO = DH2.ORDER_NO                 ");
        sb.append("      and DH2.UPDATED_DATETIME > DH1.UPDATED_DATETIME ");
        sb.append("  where DH2.UPDATED_DATETIME IS NULL                  ");
        sb.append("      and DH1.DISABLED_FLG = 0                        ");
        String sql = sb.toString();
        return sql;
    }
    
    private String getInnerSql() {
        StringBuilder sb = new StringBuilder();
        sb.append("    select   ");
        sb.append("      DH1.ORDER_NO,                                   ");
        sb.append("      DH1.SHIPPER_CODE ,                              ");
        sb.append("      DH1.VEHICLE_NAME,                               ");
        sb.append("      DH1.VEHICLE_CODE ,                              ");
        sb.append("      DH1.REASON_NAME_MOBILE,                         ");
        sb.append("      DH1.STATUS_NAME_MOBILE                          ");
        sb.append("  from                                                                                      ");
        sb.append("         DELIVERY_HISTORY dh1 ,                                                                ");
        sb.append("         (select SHIPPER_CODE,ORDER_NO,max(UPDATED_DATETIME) as utime  from DELIVERY_HISTORY   ");
        sb.append("             group by SHIPPER_CODE,ORDER_NO) dh2                                               ");
        sb.append("     where                                                                                     ");
        sb.append("         dh1.SHIPPER_CODE=dh2.SHIPPER_CODE and                                                 ");
        sb.append("         dh1.ORDER_NO=dh2.ORDER_NO and                                                         ");
        sb.append("         dh1.UPDATED_DATETIME=dh2.utime and                                                    ");
        sb.append("         dh1.DISABLED_FLG='0'                                                                  ");

        String sql = sb.toString();
        
        return sql;
    }
    
    private String getNewInnerSql() {
        StringBuilder sb = new StringBuilder();
        sb.append("    select ");
        sb.append("          a.ORDER_NO,         ");                          
        sb.append("          a.SHIPPER_CODE ,     ");                         
        sb.append("          a.VEHICLE_NAME,          ");                     
        sb.append("          a.VEHICLE_CODE ,             ");                 
        sb.append("          a.REASON_NAME_MOBILE,         ");                
        sb.append("          a.STATUS_NAME_MOBILE ,");
        sb.append("          a.UPDATED_DATETIME");
        sb.append("    from DELIVERY_HISTORY a");
        sb.append("    where not exists(select 1 ");
        sb.append("    from DELIVERY_HISTORY b");
        sb.append("    where b.SHIPPER_CODE=a.SHIPPER_CODE and b.ORDER_NO=a.ORDER_NO and b.UPDATED_DATETIME>a.UPDATED_DATETIME)");
        sb.append("         and  a.DISABLED_FLG=0                                                                  ");

        String sql = sb.toString();
        return sql;
    }
    

    // test leftjoin plan
    private boolean testLeftJoin(Statement stmt)  throws SQLException {
        StringBuilder sb = new StringBuilder();
        sb.append("     SELECT                                              ");
        sb.append("      DH1.ORDER_NO,                                   ");
        sb.append("      DH1.SHIPPER_CODE                               ");
        sb.append("  from                                                ");
        sb.append("      DELIVERY_HISTORY DH1                            ");
        sb.append("      left JOIN DELIVERY_HISTORY DH2 on               ");
        sb.append("      DH1.SHIPPER_CODE = DH2.SHIPPER_CODE             ");
        sb.append("      and DH1.ORDER_NO = DH2.ORDER_NO                 ");
        sb.append("      and DH2.UPDATED_DATETIME > DH1.UPDATED_DATETIME  ");
        sb.append("  where DH2.UPDATED_DATETIME IS NULL                  ");
        sb.append("      and DH1.DISABLED_FLG = 0                        ");
        String sql = sb.toString();

        long startMs = System.currentTimeMillis();
        stmt.executeQuery(sql);
        long endMs = System.currentTimeMillis();
        log.info("It takes "+ms2DHMS(startMs,endMs)+" to run leftjoin plan.");
        
        log.info("Got " + toEastNumFormat(evaluateCntinSql(sql,stmt)) + " records after running leftjoin.");
        return true;
    }
    
    // test innerjoin plan
    private boolean testInnerJoin(Statement stmt)  throws SQLException {
        StringBuilder sb = new StringBuilder();
        sb.append("    select ");
        sb.append("          a.ORDER_NO,         ");                          
        sb.append("          a.SHIPPER_CODE      ");                         
        //sb.append("          a.VEHICLE_NAME,          ");                     
        //sb.append("          a.VEHICLE_CODE ,             ");                 
        //sb.append("          a.REASON_NAME_MOBILE,         ");                
        //sb.append("          a.STATUS_NAME_MOBILE ,");
        //sb.append("          a.UPDATED_DATETIME");
        sb.append("    from DELIVERY_HISTORY a");
        sb.append("    where not exists(select 1 ");
        sb.append("    from DELIVERY_HISTORY b");
        sb.append("    where b.SHIPPER_CODE=a.SHIPPER_CODE and b.ORDER_NO=a.ORDER_NO and b.UPDATED_DATETIME>a.UPDATED_DATETIME)");
        sb.append("         and  a.DISABLED_FLG=0                                                                  ");

        String sql = sb.toString();

        long startMs = System.currentTimeMillis();
        stmt.executeQuery(sql);
        long endMs = System.currentTimeMillis();
        log.info("It takes "+ms2DHMS(startMs,endMs)+" to run inner join plan.");
        
        log.info("Got " + toEastNumFormat(evaluateCntinSql(sql,stmt)) + " records after running inner join.");
        return true;
    }
    
    // evaluate how many records int resultset after running a sql
    private long evaluateCntinSql(String sql,Statement stmt) throws SQLException {
        String sql2 = "select count(*) as cnt from ("+sql+") ";

        ResultSet rs = stmt.executeQuery(sql2);
        while (rs.next()) {
            int cnt = rs.getInt("cnt");
            return cnt;
        }
        return 0;
    }

    // query how many records in table delivery_history
    private boolean queryTotalCntinDH(Statement stmt) throws SQLException {
        String sql = "select count(*) as cnt from delivery_history";

        ResultSet rs = stmt.executeQuery(sql);
        while (rs.next()) {
            int cnt = rs.getInt("cnt");
            log.info("There are " + toEastNumFormat(cnt) + " records in the table:'delivery_history'.");
        }
        return true;
    }

    // 将整数在万分位以逗号分隔表示
    public static String toEastNumFormat(long number) {
        DecimalFormat df = new DecimalFormat("#,####");
        return df.format(number);
    }

    /**
     * change seconds to DayHourMinuteSecond format
     * 
     * @param startMs
     * @param endMs
     * @return
     */
    private static String ms2DHMS(long startMs, long endMs) {
        String retval = null;
        long secondCount = (endMs - startMs) / 1000;
        String ms = (endMs - startMs) % 1000 + "ms";

        long days = secondCount / (60 * 60 * 24);
        long hours = (secondCount % (60 * 60 * 24)) / (60 * 60);
        long minutes = (secondCount % (60 * 60)) / 60;
        long seconds = secondCount % 60;

        if (days > 0) {
            retval = days + "d" + hours + "h" + minutes + "m" + seconds + "s";
        } else if (hours > 0) {
            retval = hours + "h" + minutes + "m" + seconds + "s";
        } else if (minutes > 0) {
            retval = minutes + "m" + seconds + "s";
        } else {
            retval = seconds + "s";
        }

        return retval + ms;
    }
    
    public static String toMD5(String key) {
        char hexDigits[] = {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
        };
        try {
            byte[] btInput = key.getBytes();
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }

}

--END-- 2019-12-20 18:26

posted @ 2019-12-20 17:27  逆火狂飙  阅读(241)  评论(0编辑  收藏  举报
生当作人杰 死亦为鬼雄 至今思项羽 不肯过江东