溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

PostgreSQL 使用 PreparedStatement 導(dǎo)致查詢慢的分析

發(fā)布時間:2020-07-24 17:34:20 來源:網(wǎng)絡(luò) 閱讀:1510 作者:yrgw 欄目:網(wǎng)絡(luò)安全

實驗環(huán)境:

DB is PostgreSQL version 8.2.15 

JDK1.8

測試一

使用JDBC查詢一個SQL:

PostgreSQL 使用 PreparedStatement 導(dǎo)致查詢慢的分析

public static void test1(String url, Properties props){
        String sql = "SELECT l.src_ip, l.location_id, "
                + "SUM(l.us_bytes) as up_usage, "
                + "SUM(l.ds_bytes) as down_usage, "
                + "(SUM(l.us_bytes) + SUM(l.ds_bytes) ) as total_usage "
                + "FROM unmapped_endpoint_location_hours l "
                + "where l.org_id = 195078 "
                + "AND date_time >= '2017-04-01 00:00:00.0' AND date_time < '2017-04-08 00:00:00.0' "
                + "AND l.location_id in (2638,2640,2654 ) "
                + "GROUP BY l.src_ip, l.location_id ";
        
        Connection conn = null;
        Statement sta = null;        try {
            System.out.println("Start query1:" );            long s_time = System.currentTimeMillis();
            conn = DriverManager.getConnection(url, props);
            sta = conn.createStatement();
            sta.execute(sql);
            System.out.println("Using Time: " + (System.currentTimeMillis() - s_time));
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {            if (conn != null) {                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }            if (sta != null) {                try {
                    sta.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

PostgreSQL 使用 PreparedStatement 導(dǎo)致查詢慢的分析

結(jié)果:

Start query1:
Using Time: 11519 ms

測試二

使用JDBC PreparedStatement 查詢相同的SQL:

PostgreSQL 使用 PreparedStatement 導(dǎo)致查詢慢的分析

public static void test2(String url, Properties props){
        String sql2 = "SELECT l.src_ip, l.location_id, "
                + "SUM(l.us_bytes) as up_usage, "
                + "SUM(l.ds_bytes) as down_usage, "
                + "(SUM(l.us_bytes) + SUM(l.ds_bytes) ) as total_usage "
                + "FROM unmapped_endpoint_location_hours l "
                + "where l.org_id = ? "
                + "AND date_time >= ? AND date_time < ? "
                + "AND l.location_id in (2638,2640,2654 ) "
                + "GROUP BY l.src_ip, l.location_id";
        
        Connection conn = null;
        PreparedStatement preSta = null;        try {
            System.out.println("Start query2:");            long s_time = System.currentTimeMillis();
            conn = DriverManager.getConnection(url, props);
            preSta = conn.prepareStatement(sql2);
            preSta.setString(1, "195078");
            preSta.setString(2, "2017-04-01 00:00:00.0");
            preSta.setString(3, "2017-04-09 00:00:00.0");
            preSta.executeQuery();
            System.out.println("Using Time: " + (System.currentTimeMillis() - s_time));
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {            if (conn != null) {                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }            if (preSta != null) {                try {
                    preSta.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

PostgreSQL 使用 PreparedStatement 導(dǎo)致查詢慢的分析

結(jié)果:

Start query2:
Using Time: 143031 ms

相同的SQL,測試二和測試一結(jié)果為什么差別這么大?

測試一的SQL沒有使用PreparedStatement 方式,直接給了原始的SQL。測試二的使用了PreparedStatement ,但是在set參數(shù)的時候用的都是String。

兩者查詢速度相差10倍,這是不是很奇怪?

現(xiàn)在來做另一個實驗:

測試三

使用JDBC PreparedStatement 查詢相同的SQL:

PostgreSQL 使用 PreparedStatement 導(dǎo)致查詢慢的分析

public static void test3(String url, Properties props){
        String sql2 = "SELECT l.src_ip, l.location_id, "
                + "SUM(l.us_bytes) as up_usage, "
                + "SUM(l.ds_bytes) as down_usage, "
                + "(SUM(l.us_bytes) + SUM(l.ds_bytes) ) as total_usage "
                + "FROM unmapped_endpoint_location_hours l "
                + "where l.org_id = ? "
                + "AND date_time >= ? AND date_time < ? "
                + "AND l.location_id in (2638,2640,2654 ) "
                + "GROUP BY l.src_ip, l.location_id";
        
        Connection conn = null;
        PreparedStatement preSta = null;        try {
            System.out.println("Start query3:");            long s_time = System.currentTimeMillis();
            conn = DriverManager.getConnection(url, props);
            preSta = conn.prepareStatement(sql2);            
            int org_id = 195078;
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
            Date d1 = null;
            Date d2 = null;            try {
                d1 = df.parse("2017-04-01 00:00:00");
                d2 = df.parse("2017-04-09 00:00:00");
            } catch (ParseException e1) {
                e1.printStackTrace();
            }
            preSta.setInt(1, org_id);
            preSta.setTimestamp(2, new java.sql.Timestamp(d1.getTime()));
            preSta.setTimestamp(3, new java.sql.Timestamp(d2.getTime()));
            preSta.executeQuery();
            System.out.println("Using Time: " + (System.currentTimeMillis() - s_time));
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {            if (conn != null) {                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }            if (preSta != null) {                try {
                    preSta.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

PostgreSQL 使用 PreparedStatement 導(dǎo)致查詢慢的分析

結(jié)果:

Start query3:
Using Time: 16245 ms

測試結(jié)果和測試一的結(jié)果差不多,為什么?

這次測試同樣使用了PreparedStatement,但是在設(shè)置參數(shù)的時候指定了參數(shù)的類型。

explan analyze

查看explan

PostgreSQL 使用 PreparedStatement 導(dǎo)致查詢慢的分析

dev=# explain analyze SELECT count(loc.name) AS totalNum
dev-# FROM (SELECT t.src_ip, t.location_id, t.up_usage, t.down_usage, t.total_usage
dev(#       FROM (SELECT l.src_ip, l.location_id,
dev(#                   SUM(l.us_bytes) as up_usage,
dev(#                   SUM(l.ds_bytes) as down_usage,
dev(#                   (SUM(l.us_bytes) + SUM(l.ds_bytes) ) as total_usage
dev(#             FROM unmapped_endpoint_location_hours l
dev(#             where l.org_id = 195078dev(#                   AND date_time >= '2017-04-11 00:00:00.0' AND date_time < '2017-04-20 00:00:00.0'dev(#                   AND l.location_id in (2638,2640)
dev(#                   GROUP BY l.src_ip, l.location_id ) t
dev(# WHERE t.total_usage > 0.0 ) m
dev-# LEFT OUTER JOIN locations loc on m.location_id = loc.id WHERE loc.org_id = 195078;

PostgreSQL 使用 PreparedStatement 導(dǎo)致查詢慢的分析

Time: 15202.518 ms

PostgreSQL 使用 PreparedStatement 導(dǎo)致查詢慢的分析

Prepare Expalin:

PREPARE  test(int,text,text,int) as
SELECT count(loc.name) AS totalNum
FROM (SELECT t.src_ip, t.location_id, t.up_usage, t.down_usage, t.total_usage
      FROM (SELECT l.src_ip, l.location_id,
                  SUM(l.us_bytes) as up_usage,
                  SUM(l.ds_bytes) as down_usage,
                  (SUM(l.us_bytes) + SUM(l.ds_bytes) ) as total_usage
            FROM unmapped_endpoint_location_hours l
            where l.org_id = $1
                  AND date_time >= $2 AND date_time < $3
                  AND l.location_id in (2638,2640)
                  GROUP BY l.src_ip, l.location_id ) t
WHERE t.total_usage > 0.0 ) m
LEFT OUTER JOIN locations loc on m.location_id = loc.id WHERE loc.org_id = $4;

Explain analyze EXECUTE test(195078,'2017-04-11 00:00:00.0','2017-04-20 00:00:00.0',195078);
dev=# EXECUTE test(195078,'2017-04-11 00:00:00.0','2017-04-20 00:00:00.0',195078);




向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI