日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

还是时间惹的祸

發布時間:2023/12/31 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 还是时间惹的祸 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

還是時間惹的禍,今天看到玄爺的db周報中一條sql的邏輯讀很高,執行量每小時也有幾千次,瞟了一眼sql,發現了異常情況,那就是t.gmt_create >= :2 ? and t.gmt_create <= :3,此時我想這條sql應該有救了。

先說一下知識點吧,java.sql定義時間類型包括三個類,date, time, 和 timestamp,分別用來表示日期(無時間信息,eg: yyyy-mm-dd),時間(只處理時間,無日期部分, eg: hh:mm:ss)和時間戳(精確到納秒級別)。在它們都繼承自java.util.date。

而oracle與jdbc之間的類型映射

date ?java.sql.date

date ?java.sql.time

timestamp ? ?java.sql.timestamp

oracle數據庫字段類型主要有date、timestamp。

在9i以后、11g以前的oracle jdbc驅動中存在一個會丟失date類型字段的時間信息的bug,原因是其jdbc驅動將oracle的date類型處理為java.sql.date 類型,這就丟失了時間部分;事實上,如果是使用ibatis,pojo屬性的類型設置為java.util.date,確保 jdbctype不為 date或者time,則避免了這個bug。因為此時ibatis會以java.sql.timestamp來處理該字段;

簡而言之,oracle在處理ibatis傳入到數據庫的變量時候,解析為timestamp類型,如果數據庫中時間字段定義為date類型,由于timestamp類型的精度比date類型的精度高,所以oracle會做出隱身轉換,將date類型轉換為timestamp類型,那么創建在date類型上的索引將不會使用到;

select count(*) ?from order t ?where (o_type = 2 or o_type = 3) ? and p_type = 1 ? and t.o_status = :1 ? and t.gmt_create >= :2 ? and t.gmt_create <= :3 ? ?and t.m_type = :4 ? and t.a_id = :5 ? and t.a_item_id = :6

——————————————————————————————

| operation ? ? ? ? ? ? ? ? ? ? ?| phv/object name ? ? ? ? ? ? ? | ?rows | bytes| ? cost |

——————————————————————————————

|select statement ? ? ? ? ? ? ? ?|———- 1348628516 ———| ? ? ? | ? ? ?| ? ? ?3 |

|sort aggregate ? ? ? ? ? ? ? ? ?| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | ? ? 1 | ? 74 | ? ? ? ?|

| filter?| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? | ? ? ?| ? ? ? ?|

| ?index range scan ? ? ? ? ? ? ?|ind_o_artid ? ? ? ? ? ?| ? ? 1 | ? 74 | ? ? ?3 |

——————————————————————————————

索引idx_artid(a_id, p_type, gmt_create, o_type, m_type, a_item_id, o_status)

跟蹤一下綁定變量的值:

child_number ? position name ?datatype_string ? max_length ? last_captured ? value_string

5 ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1 ? ? ? ? ? :1 ? ? ? ? number ? ? ? ? ? ? ? ? ? ?22 ? ? ? ? 2011-04-25 16:30:07 ? ? ? 3

5 ? ? ? ? ? ? ? ? ? ? ? ? ? ?2 ? ? ? ? ? ?:2 ? ?timestamp?11 ? ? ? ? 2011-04-25 16:30:07

5 ? ? ? ? ? ? ? ? ? ? ? ? ? 3 ? ? ? ? ? ? :3 ? ?timestamp?11 ? ? ? ?2011-04-25 16:30:07

5 ? ? ? ? ? ? ? ? ? ? ? ? ?4 ? ? ? ? ? ? ?:4 ? ?number ? ? ? ? ? ? ? ? ? ? ? 22 ? ? ?2011-04-25 16:30:07 ? ? ? ? ?6

5 ? ? ? ? ? ? ? ? ? ? ? ? ?5 ? ? ? ? ? ? ?:5 ? ?number ? ? ? ? ? ? ? ? ? ? ? ?22 ? ? ?2011-04-25 16:30:07 ? ? ? ? 940

5 ? ? ? ? ? ? ? ? ? ? ? ? ?6 ? ? ? ? ? ? ? :6 ? ?number ? ? ? ? ? ? ? ? ? ? ? 22 ? ? ? 2011-04-25 16:30:07 ? ? ?1791

可以看到oracle將gmt_create綁定為timestamp, 奇怪的是我們沒有在value_string中看到有gmt_create的值;從執行計劃上我們看到filter,原表中gmt_create為date數據類型,這里可以斷定是由于隱式轉換導致了時間字段在索引中排序沒有作用了,所以還要過濾filter,在索引中的gmt_create字段沒有起到過濾的作用,從而導致了大量的邏輯讀;

驗證如下:

11:24:02 bss2@ crm>select /*+index(t idx_artid)*/ count(*)

11:24:25 ? 2 ? ?from order t

11:24:25 ? 3 ? where (o_type = 2 or o_type = 3)

11:24:25 ? 4 ? ? and p_type = 1

11:24:25 ? 5 ? ? and t.o_status = 3

11:24:25 ? 6 ? ? and t.gmt_create >= ‘2011-04-10 11:20:22’

11:24:25 ? 7 ? ? and t.gmt_create <= ‘2011-04-13 11:20:22’—變量值傳入時間的字符串

11:24:25 ? 8 ? ? and t.m_type = 6

11:24:25 ? 9 ? ? and t.a_id = 965

11:24:25 ?10 ? ? and t.a_item_id =1863;

1 row selected.

elapsed: 00:00:00.01

execution plan

———————————————————

plan hash value: 3276776702

—————————————————————————————–

| id ?| operation ? ? ? ? | name ? ? ? ? ? ? ? ?| rows ?| bytes | cost (%cpu)| time ? ? |

—————————————————————————————–

| ? 0 | select statement ?| ? ? ? ? ? ? ? ? ? ? | ? ? 1 | ? ?74 | ? ? 2 ? (0)| 00:00:01 |

| ? 1 | ?sort aggregate ? | ? ? ? ? ? ? ? ? ? ? | ? ? 1 | ? ?74 | ? ? ? ? ? ?| ? ? ? ? ?|

|* ?2 | ? index range scan| idx_artid | ? ? 1 | ? ?74 | ? ? 2 ? (0)| 00:00:01 |

—————————————————————————————–

predicate information (identified by operation id):

—————————————————

2 – access(“t”.”a_id”=965 and “p_type”=1 and

“t”.”gmt_create”>=to_date(‘ 2011-04-10 11:20:22’, ‘yyyy-mm-dd hh24:mi:ss’) and

“t”.”m_type”=6 and “t”.”a_item_id”=1863 and “t”.”o_status”=3 and

“t”.”gmt_create”<=to_date(‘ 2011-04-13 11:20:22’, ‘yyyy-mm-dd hh24:mi:ss’))

filter((“o_type”=2 or “o_type”=3) and “t”.”m_type”=6 and

“t”.”a_item_id”=1863 and “t”.”o_status”=3)

statistics

———————————————————-

1 ?recursive calls

0 ?db block gets

6 ?consistent gets

0 ?physical reads

0 ?redo size

11:28:11 bss2@ crm>select /*+index(t idx_artid)*/ count(*)

11:28:12 ? 2 ? ?from order t

11:28:12 ? 3 ? where (o_type = 2 or o_type = 3)

11:28:12 ? 4 ? ? and p_type = 1

11:28:12 ? 5 ? ? and t.o_status = 3

11:28:12 ? 6 ? ? and t.gmt_create >= to_date(‘2011-04-10 11:20:22′,’yyyy-mm-dd hh24:mi:ss’)

11:28:12 ? 7 ? ? and t.gmt_create <= to_date(‘2011-04-13 11:20:22′,’yyyy-mm-dd hh24:mi:ss’)–用to_date轉換一下

11:28:12 ? 8 ? ? and t.m_type = 6

11:28:12 ? 9 ? ? and t.a_id = 965

11:28:12 ?10 ? ? and t.a_item_id =1863;

1 row selected.

elapsed: 00:00:00.01

execution plan

———————————————————-

plan hash value: 3276776702

—————————————————————————————–

| id ?| operation ? ? ? ? | name ? ? ? ? ? ? ? ?| rows ?| bytes | cost (%cpu)| time ? ? |

—————————————————————————————–

| ? 0 | select statement ?| ? ? ? ? ? ? ? ? ? ? | ? ? 1 | ? ?74 | ? ? 2 ? (0)| 00:00:01 |

| ? 1 | ?sort aggregate ? | ? ? ? ? ? ? ? ? ? ? | ? ? 1 | ? ?74 | ? ? ? ? ? ?| ? ? ? ? ?|

|* ?2 | ? index range scan| idx_artid | ? ? 1 | ? ?74 | ? ? 2 ? (0)| 00:00:01 |

—————————————————————————————–

predicate information (identified by operation id):

—————————————————

2 – access(“t”.”a_id”=965 and “p_type”=1 and

“t”.”gmt_create”>=to_date(‘ 2011-04-10 11:20:22’, ‘syyyy-mm-dd hh24:mi:ss’) and

“t”.”m_type”=6 and “t”.”a_item_id”=1863 and “t”.”o_status”=3 and

“t”.”gmt_create”<=to_date(‘ 2011-04-13 11:20:22’, ‘syyyy-mm-dd hh24:mi:ss’))

filter((“o_type”=2 or “o_type”=3) and “t”.”m_type”=6 and

“t”.”a_item_id”=1863 and “t”.”o_status”=3)

statistics

———————————————————-

0 ?recursive calls

0 ?db block gets

6 ?consistent gets

0 ?physical reads

0 ?redo size

11:24:26 bss2@ crm>select /*+index(t idx_artid)*/ count(*)

11:26:31 ? 2 ? ?from order t

11:26:31 ? 3 ? where (o_type = 2 or o_type = 3)

11:26:31 ? 4 ? ? and p_type = 1

11:26:31 ? 5 ? ? and t.o_status = 3

11:26:31 ? 6 ? ? and t.gmt_create >= to_timestamp(‘2011-04-10 11:20:22′,’yyyy-mm-dd hh24:mi:ss’)

11:26:31 ? 7 ? ? and t.gmt_create <= to_timestamp(‘2011-04-13 11:20:22′,’yyyy-mm-dd hh24:mi:ss’)–模仿沒有經過處理的變量值,ibatis轉換為timestamp

11:26:31 ? 8 ? ? and t.m_type = 6

11:26:31 ? 9 ? ? and t.a_id = 965

11:26:31 ?10 ? ? and t.a_item_id =1863;

1 row selected.

elapsed: 00:00:00.20

execution plan

———————————————————-

plan hash value: 2438882768

——————————————————————————————

| id ?| operation ? ? ? ? ?| name ? ? ? ? ? ? ? ?| rows ?| bytes | cost (%cpu)| time ? ? |

——————————————————————————————

| ? 0 | select statement ? | ? ? ? ? ? ? ? ? ? ? | ? ? 1 | ? ?74 | ? ? 3 ? (0)| 00:00:01 |

| ? 1 | ?sort aggregate ? ?| ? ? ? ? ? ? ? ? ? ? | ? ? 1 | ? ?74 | ? ? ? ? ? ?| ? ? ? ? ?|

|* ?2 | ? filter ? ? ? ? ? | ? ? ? ? ? ? ? ? ? ? | ? ? ? | ? ? ? | ? ? ? ? ? ?| ? ? ? ? ?|

|* ?3 | ? ?index range scan| idx_artid | ? ? 1 | ? ?74 | ? ? 3 ? (0)| 00:00:01 |

——————————————————————————————

predicate information (identified by operation id):

—————————————————

2 – filter(to_timestamp(‘2011-04-10 11:20:22′,’yyyy-mm-dd

hh24:mi:ss’)<=to_timestamp(‘2011-04-13 11:20:22′,’yyyy-mm-dd hh24:mi:ss’))

3 – access(“t”.”a_id”=965 and “p_type”=1 and “t”.”m_type”=6 and

“t”.”a_item_id”=1863 and “t”.”o_status”=3)

filter((“o_type”=2 or “o_type”=3) and “t”.”m_type”=6 and

“t”.”a_item_id”=1863 and internal_function(“t”.”gmt_create”)>=to_timestamp(‘

2011-04-10 11:20:22′,’yyyy-mm-dd hh24:mi:ss’) and

internal_function(“t”.”gmt_create”)<=to_timestamp(‘2011-04-13

11:20:22′,’yyyy-mm-dd hh24:mi:ss’) and “t”.”o_status”=3)

statistics

———————————————————-

1 ?recursive calls

0 ?db block gets

698 ?consistent gets

0 ?physical reads

0 ?redo size

可以看到當我們采用to_timestatmp轉換gmt_create傳入的值后,其執行計劃是和沒有做任何處理查詢變量的是一樣的,

所以接下來的兩種方案可以為:

使用cast(:2 as date)轉換一下;

變量定義為字符串,在采用to_date(:2,’yyyy-mm-dd hh24:mi:ss’);

程序中綁定為date:gmt_create<#2:date#;

結論:在處理時間類型的時候,我們需要特別的謹慎,避免隱式轉換的發生.

總結

以上是生活随笔為你收集整理的还是时间惹的祸的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。