1. 程式人生 > >記一次Mybatis+Oracle, 資料多且日期間隔大時, 查詢非常慢解決過程

記一次Mybatis+Oracle, 資料多且日期間隔大時, 查詢非常慢解決過程

前兩天發現一個sql在專案執行時查詢時間的很長, 但sql在PLSql中查詢時只要1s左右, 以下是原sql:

SELECT  MAX(data) DATA_VALUE
FROM (
    SELECT A.FREEZE_TIME, SUM(A.AP * T2.add_attr * T2.pct / 100) data
    FROM T_CUR_AP A
    INNER JOIN (SELECT lm.METER_ID, lm.add_attr, lm.pct FROM T_LEDGER_METER lm WHERE lm.LEDGER_ID =#{baseId}) T2
    ON A.METER_ID = T2.METER_ID
    WHERE A.FREEZE_TIME >= #{beginTime,jdbcType=TIME}
    AND A.FREEZE_TIME <= #{endTime,jdbcType=TIME}
    GROUP BY A.FREEZE_TIME)
百度後發現有網友說是preparedstatement的問題, 遂把#換成了$, 並用了to_date函式, 如下:
SELECT  MAX(data) DATA_VALUE
FROM (
    SELECT A.FREEZE_TIME, SUM(A.AP * T2.add_attr * T2.pct / 100) data
    FROM T_CUR_AP A
    INNER JOIN (SELECT lm.METER_ID, lm.add_attr, lm.pct FROM T_LEDGER_METER lm WHERE lm.LEDGER_ID =#{baseId}) T2
    ON A.METER_ID = T2.METER_ID
    WHERE A.FREEZE_TIME >= to_date('${beginTime}', 'yyyy-mm-dd hh24:mi:ss')
    AND A.FREEZE_TIME <= to_date('${endTime}', 'yyyy-mm-dd hh24:mi:ss')
    GROUP BY A.FREEZE_TIME)

這樣確實可以, 但是專案中為了防止sql注入, 不允許使用$, 故繼續查閱資料(還不是百度-.-!!)

然後在這篇部落格(http://www.mamicode.com/info-detail-1892493.html)中發現可能是jdbcType的問題, 故查看了下我們表中的日期型別為Date, 於是找到oracle的欄位型別:

發現Date對應的java資料型別是Timestamp, 而我們程式碼中用的型別是Time, 故將程式碼中的jdbcType換為Timestamp, 如下

SELECT  MAX(data) DATA_VALUE
FROM (
    SELECT A.FREEZE_TIME, SUM(A.AP * T2.add_attr * T2.pct / 100) data
    FROM T_CUR_AP A
    INNER JOIN (SELECT lm.METER_ID, lm.add_attr, lm.pct FROM T_LEDGER_METER lm WHERE lm.LEDGER_ID =#{baseId}) T2
    ON A.METER_ID = T2.METER_ID
    WHERE A.FREEZE_TIME >= #{beginTime,jdbcType=TIMESTAMP}
    AND A.FREEZE_TIME <= #{endTime,jdbcType=TIMESTAMP}
    GROUP BY A.FREEZE_TIME)

問題解決!