首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >设置PreparedStatement中的任何param不工作

设置PreparedStatement中的任何param不工作
EN

Stack Overflow用户
提问于 2018-07-20 14:36:43
回答 4查看 1.2K关注 0票数 12

我有这样定义的SQL请求:

代码语言:javascript
复制
private static final String fetchOfferQuery = "SELECT DISTINCT "
        + "sim_id, sim_code, sim_label, sim_state, sim_type, sim_customerid, sim_storeid, sim_projectnumber, sim_version, sim_type_user, sim_type_vente, sim_statut, "
        + "(SELECT MAX(set_date) FROM offer_storage.t_simulationeventtrack_set WHERE set_sim_id = sim_id) AS sim_dateevtmax, "
        + "sim_creation_user, sim_modif_user, sim_rayon, sim_hours_lifetime, sim_eligible_reduced_vat, sim_store_linked, sim_canal, "
        + "ofr_id, CAST(ofr_creationdate AS timestamp) AS ofr_creationdate, ofr_label, ofr_state, ofr_transaction, ofr_modif_date, ofr_del_valid, "
        + "ofr_numcdecli, "
        + "ofi_id, ofi_productid, ofi_quantity,ofi_productprice, ofi_top, ofi_c1promo, ofi_codeactivite, ofi_codrem, "
        + "ofi_datejour, ofi_datepose, ofi_dateprevpose, ofi_datfinc1, ofi_datfinprxvtepromo, ofi_delai, ofi_libligdtl, ofi_montantpresta, "
        + "ofi_montrt, ofi_aro_id, ofi_numartisan, ofi_prxvte, ofi_prxvtepromo, ofi_typinitialoff, ofi_typoff, ofi_c1, ofi_numlig, "
        + "deo_id, deo_numligdtl, deo_codligdtl, deo_libligdtl, "
        + "aro_id, aro_type_offer, aro_type_inioff, aro_top_caisse, aro_num_arty, aro_date_prev, aro_mntrt, aro_date_jour, "
        + "aro_delai, aro_mnt_presta, aro_codact, aro_date_pose "
        + "FROM offer_storage.t_simulation_sim "
        //with fixed date
        + "INNER JOIN offer_storage.t_simulationeventtrack_set ON set_sim_id = sim_id AND set_date >= TO_DATE('20180726000000','yyyymmddhh24miss') "
        //with bind parameter
        //+ "INNER JOIN offer_storage.t_simulationeventtrack_set ON set_sim_id = sim_id AND set_date >= ?  "
        + "LEFT JOIN offer_storage.t_offer_ofr ON ofr_sim_id = sim_id "
        + "LEFT JOIN offer_storage.t_offeritem_ofi ON ofi_ofr_id = ofr_id "
        + "LEFT JOIN offer_storage.t_details_item_offer_deo ON deo_ofi_id = ofi_id "
        + "LEFT JOIN offer_storage.t_artisan_offer_aro ON aro_id = ofi_aro_id "
        + "ORDER BY sim_id, ofr_id, ofi_id, deo_id, aro_id";

如果我在请求中设置了固定日期:

代码语言:javascript
复制
...
            + "INNER JOIN offer_storage.t_simulationeventtrack_set ON set_sim_id = sim_id AND set_date >= TO_DATE('20180726000000','yyyymmddhh24miss') "
        ...

然后播放请求: simulationsSt = connection.prepareStatement(fetchOfferQuery);ResultSet simulationsRs = simulationsSt.executeQuery();

请求需要1分30才能结束。

如果我使用bind参数:

代码语言:javascript
复制
        ...
        + "INNER JOIN offer_storage.t_simulationeventtrack_set ON set_sim_id = sim_id AND set_date >= ?  "
        ...

在executeQuery之前使用set方法(dateLastExtract =20180726000000的同一日期):

代码语言:javascript
复制
        simulationsSt.setTimestamp(1, new Timestamp(this.dateLastExtract.getTime()));

请求需要10分钟!

我需要设置任何param (int、date、string...etc)的所有请求都有问题。因此,它不是特定的日期,它只是当我使用绑定时,当我没有。

关于信息,数据行的数量相当大:

代码语言:javascript
复制
t_simulationeventtrack_set : 66.097.939 rows    
t_details_item_offer_deo : 46.259.704 rows    
t_offeritem_ofi : 14.232.150 rows    
t_artisan_offer_aro : 2.317.658 rows    
t_offer_ofr : 1.801.969 rows    
t_simulation_sim : 1.756.235 rows

CREATE表t_simulationeventtrack_set脚本是:

代码语言:javascript
复制
CREATE TABLE "OFFER_STORAGE"."T_SIMULATIONEVENTTRACK_SET" 
   (    "SET_ID" NUMBER(*,0) NOT NULL ENABLE, 
    "SET_DATE" DATE, 
    "SET_CHANGETYPE" VARCHAR2(254 BYTE), 
    "SET_CHANGE" VARCHAR2(254 BYTE), 
    "SET_USR_ID" NUMBER(*,0), 
    "SET_SIM_ID" NUMBER(*,0), 
     CONSTRAINT "PK_SIMULATIONEVENTTRACK" PRIMARY KEY ("SET_ID")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "OAA_INDX"  ENABLE
   ) SEGMENT CREATION IMMEDIATE 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "OAA_DATA" ;

  CREATE INDEX "OFFER_STORAGE"."IDX_SET_SIM_ID" ON "OFFER_STORAGE"."T_SIMULATIONEVENTTRACK_SET" ("SET_SIM_ID") 
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "OAA_INDX" ;

  CREATE INDEX "OFFER_STORAGE"."IDX_SIMULATIONEVENTTRACK_DATE" ON "OFFER_STORAGE"."T_SIMULATIONEVENTTRACK_SET" ("SET_DATE") 
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "OAA_INDX" ;

  CREATE INDEX "OFFER_STORAGE"."IDX_SIMULATIONEVENTTRACK_FDATE" ON "OFFER_STORAGE"."T_SIMULATIONEVENTTRACK_SET" (TO_CHAR("SET_DATE",'YYYY-MM-DD')) 
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "OAA_INDX" ;

  CREATE INDEX "OFFER_STORAGE"."IDX_SIM_ID_USER_ID" ON "OFFER_STORAGE"."T_SIMULATIONEVENTTRACK_SET" ("SET_SIM_ID", "SET_USR_ID") 
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "OAA_INDX" ;

怎么了?

我试图在"T_SIMULATIONEVENTTRACK_SET“("SET_SIM_ID”、"SET_DATE")上添加一个索引,但它没有改变任何东西。

编辑:

我在这里找到了一个日期参数的解决方案:https://blog.jooq.org/2014/12/22/are-you-binding-your-oracle-dates-correctly-i-bet-you-arent/

如果我用"CAST(?AS DATE)“代替"?",它很快就能工作了!

但是现在我遇到了同样的问题,一个整数仿射。我有一句">= CAST(?AS DATE) OR 1= ?“第二个参数是1或0,如果我放0,它会取每一行,甚至是旧的。

当我说这个简单的整段时,它又慢了.

编辑2 :

下面是绑定的执行计划:

代码语言:javascript
复制
--------------------------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name                        | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                             |       |       |       |   191M(100)|          |
|   1 |  SORT AGGREGATE              |                             |     1 |    14 |       |            |          |
|   2 |   FIRST ROW                  |                             |     1 |    14 |       |     4   (0)| 00:00:01 |
|   3 |    INDEX RANGE SCAN (MIN/MAX)| IDX_SIMULATIONEVENTTRACK_SD |     1 |    14 |       |     4   (0)| 00:00:01 |
|   4 |  SORT ORDER BY               |                             |    26 |  9698 |    17G|   191M  (1)|637:07:31 |
|   5 |   FILTER                     |                             |       |       |       |            |          |
|   6 |    HASH JOIN RIGHT OUTER     |                             |    46M|    16G|  3351M|   915K  (1)| 03:03:10 |
|   7 |     TABLE ACCESS FULL        | T_DETAILS_ITEM_OFFER_DEO    |    46M|  2815M|       |   145K  (1)| 00:29:01 |
|   8 |     HASH JOIN RIGHT OUTER    |                             |    14M|  4263M|   134M|   384K  (1)| 01:16:57 |
|   9 |      TABLE ACCESS FULL       | T_ARTISAN_OFFER_ARO         |  2317K|   108M|       |  4543   (1)| 00:00:55 |
|  10 |      HASH JOIN OUTER         |                             |    14M|  3589M|   325M|   187K  (1)| 00:37:28 |
|  11 |       HASH JOIN RIGHT OUTER  |                             |  1823K|   304M|   125M| 35194   (1)| 00:07:03 |
|  12 |        TABLE ACCESS FULL     | T_OFFER_OFR                 |  1824K|   104M|       |  5995   (1)| 00:01:12 |
|  13 |        TABLE ACCESS FULL     | T_SIMULATION_SIM            |  1778K|   195M|       | 12293   (1)| 00:02:28 |
|  14 |       TABLE ACCESS FULL      | T_OFFERITEM_OFI             |    14M|  1183M|       | 69005   (1)| 00:13:49 |
|  15 |    INDEX RANGE SCAN          | IDX_SIMULATIONEVENTTRACK_SD |     1 |    14 |       |     4   (0)| 00:00:01 |
|  16 |    INDEX RANGE SCAN          | IDX_SET_SIM_ID              |     2 |    12 |       |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------------------

以及没有绑定的执行计划(更快):

代码语言:javascript
复制
-----------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name                          | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |                               |       |       |       |   163K(100)|          |
|   1 |  SORT AGGREGATE                     |                               |     1 |    14 |       |            |          |
|   2 |   FIRST ROW                         |                               |     1 |    14 |       |     4   (0)| 00:00:01 |
|   3 |    INDEX RANGE SCAN (MIN/MAX)       | IDX_SIMULATIONEVENTTRACK_SD   |     1 |    14 |       |     4   (0)| 00:00:01 |
|   4 |  SORT ORDER BY                      |                               |   156K|    57M|    60M|   163K  (1)| 00:32:41 |
|   5 |   NESTED LOOPS OUTER                |                               |   156K|    57M|       |   150K  (1)| 00:30:07 |
|   6 |    NESTED LOOPS OUTER               |                               | 48049 |    14M|       | 40080   (1)| 00:08:01 |
|   7 |     NESTED LOOPS OUTER              |                               | 48049 |    12M|       | 35935   (1)| 00:07:12 |
|   8 |      HASH JOIN OUTER                |                               |  6085 |  1123K|       | 12654   (1)| 00:02:32 |
|   9 |       NESTED LOOPS                  |                               |       |       |       |            |          |
|  10 |        NESTED LOOPS                 |                               |  5930 |   747K|       |  6654   (1)| 00:01:20 |
|  11 |         SORT UNIQUE                 |                               |  6008 | 84112 |       |   643   (0)| 00:00:08 |
|  12 |          TABLE ACCESS BY INDEX ROWID| T_SIMULATIONEVENTTRACK_SET    |  6008 | 84112 |       |   643   (0)| 00:00:08 |
|  13 |           INDEX RANGE SCAN          | IDX_SIMULATIONEVENTTRACK_DATE |  6008 |       |       |    20   (0)| 00:00:01 |
|  14 |         INDEX UNIQUE SCAN           | PK_SIMULATION                 |     1 |       |       |     1   (0)| 00:00:01 |
|  15 |        TABLE ACCESS BY INDEX ROWID  | T_SIMULATION_SIM              |     1 |   115 |       |     2   (0)| 00:00:01 |
|  16 |       TABLE ACCESS FULL             | T_OFFER_OFR                   |  1779K|   101M|       |  5994   (1)| 00:01:12 |
|  17 |      TABLE ACCESS BY INDEX ROWID    | T_OFFERITEM_OFI               |     8 |   688 |       |     4   (0)| 00:00:01 |
|  18 |       INDEX RANGE SCAN              | IDX_OFI_OFR_ID                |     9 |       |       |     2   (0)| 00:00:01 |
|  19 |     TABLE ACCESS BY INDEX ROWID     | T_ARTISAN_OFFER_ARO           |     1 |    49 |       |     2   (0)| 00:00:01 |
|  20 |      INDEX UNIQUE SCAN              | PK_ARTISANOFFER               |     1 |       |       |     1   (0)| 00:00:01 |
|  21 |    TABLE ACCESS BY INDEX ROWID      | T_DETAILS_ITEM_OFFER_DEO      |     3 |   189 |       |     4   (0)| 00:00:01 |
|  22 |     INDEX RANGE SCAN                | IDX_DEO_OFI_ID                |    22 |       |       |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------------------------

谢谢

EN

回答 4

Stack Overflow用户

发布于 2018-07-23 20:09:50

当两个本质上相同的查询的副本具有非常不同的性能特性时,原因通常是优化器如何计算执行计划。

对于上面的内容,我将注意到您的查询有一个笛卡儿连接。根据有关笛卡尔Joins的Oracle文档:

“在某些情况下,优化器可以选择两个表之间的公共筛选条件作为可能的联接条件。”

显然选择非最佳执行计划的一个可能原因可能是绑定变量的存在--请参阅执行计划变更的原因上的文档:

“影响费用的一些因素包括:

..。绑定变量类型和值……“

Oracle文档中对语句的一种解释是:“如果您指定了一个笛卡儿联接,您可能需要一些运气才能使它运行良好-而使用绑定变量并不会增加您的机会”。

如果您通过替换"FROM t_user_usr,t_simulationeventtrack_set "来更新查询

“从t_user_usr内部加入t_simulationeventtrack_set ON xxx=yyy "

(xxx=yyy可能是WHERE中的条件之一,但是不可能判断哪一个没有表描述)可能会使优化器表现得更好。

第一个问题的语句是:“请求被启动,但它永远不会结束,不会显示错误。”在这种情况下“从不”有多长时间?我之所以这样问是因为,当某物需要一秒钟的时间时,接近30秒的任何东西都很可能会在我的机器上被杀死。

最近的问题是..。还是1= ?‘将强制查询的执行计划不使用SIM_ID + SET_DATE索引(给定数据大小,该索引将产生性能问题)。

考虑到条件的作用,我只需在Java代码中准备两条语句(一条带有日期条件,另一条没有日期条件)--这应该允许优化器为每个语句选择正确的索引。

票数 4
EN

Stack Overflow用户

发布于 2018-07-23 15:09:48

SQL引擎似乎消除了常量表达式,如X OR 1=0X。而对于动态准备的表达式则不是这样,没有在set_date上使用某些索引。

该条件的目的是禁用set_date上的筛选,用于所有set_date值。

如果可行的话,你可以用

代码语言:javascript
复制
        + "AND (set_date >= TO_DATE('2018-07-19', 'YYYY-MM-DD') "
        + "OR 1 = ?) "

使用

代码语言:javascript
复制
        + "AND set_date >= ? "

代码语言:javascript
复制
       LocalDate d = seen == 1 ? LocalDate.of(1900, 1, 1) : LocalDate.of(2018, 7, 19);
       java.sql.Date sd = new java.sql.Date(d.toEpochDay);
       simulationsSt.setDate(1, sd);
票数 3
EN

Stack Overflow用户

发布于 2018-07-26 08:36:41

请求被启动,但它永远不会结束,也不会显示错误。

当您有一个长时间运行的语句(超过几秒钟)时,您可以在v$session_longops中看到它

代码语言:javascript
复制
select * from v$session_longops v order by v.start_time desc;

找到它,取出sql_id并在dba_hist_sqltext中查找语句

代码语言:javascript
复制
select * from dba_hist_sqltext t where t.sql_id = 'b6usrg82hwsa3';

及其在dba_hist_sql_plan中的执行计划:

代码语言:javascript
复制
select * from dba_hist_sql_plan p where p.sql_id = 'b6usrg82hwsa3' order by p.plan_hash_value, p.id;

您可能在这里得到超过一个(不同的plan_hash_value)。

正如Joop已经发布的那样,当您通过绑定变量实际设置参数时,可能会遇到不同的执行计划。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51444951

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档