Oracle JDB 瘦客户端 - 未使用 varchar2 的唯一索引

发布于 2024-12-16 12:24:40 字数 3029 浏览 2 评论 0原文

首先是一些基础知识。

爪哇6 OJDBC6 Oracle 10.2.0.4(在 11g 版本中也有相同的结果)

我发现,当使用 OJDBC6 客户端从 Java 执行并使用可能使用本机/OCI 驱动程序的 SQL Gate 工具时,sql 语句的行为有所不同。由于某种原因,优化器选择对 Java 中执行的语句使用哈希连接,而不对其他语句使用哈希连接。

这是表格:

CREATE TABLE DPOWNERA.XXX_CHIP (
   xxxCH_ID        NUMBER(22)       NOT NULL, 
   xxxCHP_ID       NUMBER(22)       NOT NULL, 
   xxxSP_ID        NUMBER(22)           NULL, 
   xxxCU_ID        NUMBER(22)           NULL, 
   xxxFT_ID        NUMBER(22)           NULL, 
   UEMTE_ID        NUMBER(38)           NULL, 
   xxxCH_CHIPID    VARCHAR2(30)     NOT NULL
)

索引:

ALTER TABLE DPOWNERA.XXX_CHIP ADD
  (
     CONSTRAINT IX_AK1_XXX_CHIPV2
     UNIQUE ( XXXCH_CHIPID )
     USING INDEX
     TABLESPACE DP_DATA01 
     PCTFREE 10
     INITRANS 2
     MAXTRANS 255
     STORAGE (
        INITIAL 128 K
        NEXT 128 K
        MINEXTENTS 1
        MAXEXTENTS UNLIMITED
    )
);

这是我使用的 SQL:

SELECT *
    FROM   (SELECT m2.*,
            rownum rnum
            FROM   (SELECT m_chip.xxxch_id,
                      m_chip.xxxch_chipid
                      FROM   xxx_chip m_chip
                      ORDER  BY m_chip.xxxch_chipid) m2
            WHERE  rownum < 101)
WHERE  rnum >= 1; 

最后摘录自解释计划:

SQL 工具查询:

OPERATION        OBJECT_NAME         COST  CARDINALITY CPU_COST
---------------- ------------------- ----- ----------- ----------
SELECT STATEMENT NULL                    2          10      11740
VIEW             NULL                    2          10      11740
COUNT            NULL                 NULL        NULL       NULL
VIEW             NULL                    2          10      11740
NESTED LOOPS     NULL                    2          10      11740
TABLE ACCESS     XXX_CHIP                1     1000000       3319
INDEX            IX_AK1_XXX_CHIPV2       1          10       2336
TABLE ACCESS     XXX_CUSTOMER            1           1        842
INDEX            IX_PK_XXX_CUSTOMER      1           1        105

QQL Java 查询 OJDBC 瘦客户端:

**OPERATION        OBJECT_NAME         COST  CARDINALITY CPU_COST**
SELECT STATEMENT NULL                15100         100 1538329415
VIEW             NULL                15100         100 1538329415
COUNT            NULL                 NULL        NULL       NULL
VIEW             NULL                15100     1000000 1538329415
SORT             NULL                15100     1000000 1538329415
HASH JOIN        NULL                 1639     1000000  424719850
VIEW             index$_join$_004        3           3    2268646
HASH JOIN        NULL                 NULL        NULL       NULL
INDEX            IX_AK1_XXX_CUSTOMER     1           3        965
INDEX            IX_PK_XXX_CUSTOMER      1           3        965
TABLE ACCESS     xxx_CHIP             1614     1000000  320184788

所以,我不明白为什么优化器选择哈希连接? 我的猜测是 varchar2 的处理方式有所不同。

First som basics.

Java 6
OJDBC6
Oracle 10.2.0.4 (also the same result in 11g version)

I am experiencing that a sql statement is behaving differently when executed from Java with the OJDBC6 client and using the tool SQL Gate that probably uses a native/OCI driver. For som reason the optimizer chooses to use hash join for the executed statement in Java but not for the other.

Here is the table:

CREATE TABLE DPOWNERA.XXX_CHIP (
   xxxCH_ID        NUMBER(22)       NOT NULL, 
   xxxCHP_ID       NUMBER(22)       NOT NULL, 
   xxxSP_ID        NUMBER(22)           NULL, 
   xxxCU_ID        NUMBER(22)           NULL, 
   xxxFT_ID        NUMBER(22)           NULL, 
   UEMTE_ID        NUMBER(38)           NULL, 
   xxxCH_CHIPID    VARCHAR2(30)     NOT NULL
)

The index:

ALTER TABLE DPOWNERA.XXX_CHIP ADD
  (
     CONSTRAINT IX_AK1_XXX_CHIPV2
     UNIQUE ( XXXCH_CHIPID )
     USING INDEX
     TABLESPACE DP_DATA01 
     PCTFREE 10
     INITRANS 2
     MAXTRANS 255
     STORAGE (
        INITIAL 128 K
        NEXT 128 K
        MINEXTENTS 1
        MAXEXTENTS UNLIMITED
    )
);

Here is the SQL i used:

SELECT *
    FROM   (SELECT m2.*,
            rownum rnum
            FROM   (SELECT m_chip.xxxch_id,
                      m_chip.xxxch_chipid
                      FROM   xxx_chip m_chip
                      ORDER  BY m_chip.xxxch_chipid) m2
            WHERE  rownum < 101)
WHERE  rnum >= 1; 

And finally excerpts from the explain plan:

SQL Tool Query:

OPERATION        OBJECT_NAME         COST  CARDINALITY CPU_COST
---------------- ------------------- ----- ----------- ----------
SELECT STATEMENT NULL                    2          10      11740
VIEW             NULL                    2          10      11740
COUNT            NULL                 NULL        NULL       NULL
VIEW             NULL                    2          10      11740
NESTED LOOPS     NULL                    2          10      11740
TABLE ACCESS     XXX_CHIP                1     1000000       3319
INDEX            IX_AK1_XXX_CHIPV2       1          10       2336
TABLE ACCESS     XXX_CUSTOMER            1           1        842
INDEX            IX_PK_XXX_CUSTOMER      1           1        105

QQL Java Query OJDBC Thin client:

**OPERATION        OBJECT_NAME         COST  CARDINALITY CPU_COST**
SELECT STATEMENT NULL                15100         100 1538329415
VIEW             NULL                15100         100 1538329415
COUNT            NULL                 NULL        NULL       NULL
VIEW             NULL                15100     1000000 1538329415
SORT             NULL                15100     1000000 1538329415
HASH JOIN        NULL                 1639     1000000  424719850
VIEW             index$_join$_004        3           3    2268646
HASH JOIN        NULL                 NULL        NULL       NULL
INDEX            IX_AK1_XXX_CUSTOMER     1           3        965
INDEX            IX_PK_XXX_CUSTOMER      1           3        965
TABLE ACCESS     xxx_CHIP             1614     1000000  320184788

So, i am lost to why the hash join is chosen by the optimizer?
My guess is that the varchar2 is treated differently.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

压抑⊿情绪 2024-12-23 12:24:40

我找到了答案,它比我想象的要简单。这一切都与索引列的 VARCHAR2 数据类型有关。我的数据库设置为语言和国家/地区“en”、“US”,但在本地
我有另一种语言和地区。因此,优化器正确地丢弃了索引,因为它没有配置与客户端相同的语言和国家/地区。

所以我测试它的方法是使用 eclipse.ini 文件中输入的一些额外的 -D 参数来启动 eclipse。

-Duser.language=en
-Duser.country=US
-Duser.region=US

然后,在 Eclipse 的数据源资源管理器中,我创建了一个连接并运行了我的语句,它的工作非常顺利。

因此,吸取的教训是始终确保客户端和数据库在语言方面兼容。也许我们会进行更改,因此我们在数据库中使用 UTF-8,这样每次安装都是相同的。否则,您将必须根据国家/地区和语言为每次安装进行配置。

希望这会对某人有所帮助。如果答案不清楚,请发表评论。

I found an answer and it was simpler than i thought. It all has to do with the VARCHAR2 datatype of the index column. My database was set to language and country "en", "US" but locally
i have another language and region. Therfore the optimizer rightly discarded the index since it wasn't configured with the same language and country as the client.

So what i did to test it was to start my eclipse with some extra -D parameters entered in my eclipse.ini file.

-Duser.language=en
-Duser.country=US
-Duser.region=US

Then in the data source explorer in Eclipse i had created a connection and ran my statement and it worked like a charm.

So lesson learned is to always see to that the client and database are compatible language wise. Probably we will change so we use UTF-8 in the database so it is the same for every installation. Otherwise you will have to configure it for every installation depending on country and language.

Hope this will help someone. If the answer was unclear please post a comment.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文