【问题标题】:EclipseLink Sybase : Existing Index is not usedEclipseLink Sybase:未使用现有索引
【发布时间】:2013-11-29 10:41:21
【问题描述】:

当我通过 JPA / EclipseLink 查询预订表并搜索特定 placeID 时,不使用现有索引 myindex。 Sybase 决定进行表扫描。

当我将 sql 从 Glassfish 日志文件复制到 sql 编辑器并在那里运行时,它使用索引。 ????

简化的sql:

create table pub.BOOKING(
   bookID numeric(10) identity,
   placeID smallint not null
)

create index idx_BOOKING_PLACEID on pub.BOOKING(placeID)   

** 从 JPQL 运行时来自 Sybase ASE 的 SHOWPLAN **

Die Art der Abfrage ist SELECT.           
VON TABELLE  pub.BOOKING                           
Verschachtelte Iteration.                 
Tabellen-Scan.                            
Vorwärts-Scan.                             
Positionierung am Tabellenanfang.          
Parallel mit einem 5-Weg-Hash-Scan ausgefü 
Für die Datenseiten wird eine I/O-Größe vo 
Mit LRU Pufferersetzungsstrategie für Date 
Parallele Netzpufferzusammenführung.       

** JPQL 查询 **

Placement p = em_local.find(Placement.class, 207);
TypedQuery<Booking> query = em_local.createQuery("select b from Booking b where b.placement = :place", Booking.class);
query.setParameter("place", p);
List<Booking> list = query.getResultList();

** 在 sql 编辑器中运行时来自 Sybase ASE 的 SHOWPLAN **

     VON TABELLE
         pub.BOOKING
     Verschachtelte Iteration.
     Index: idx_BOOKING_PLACEID
    Vorwärts-Scan.
    Positionierung durch Schlüssel.
    Schlüssel sind:
        placeID  AUFST
    Parallel mit einem 5-Weg-Hash-Scan ausgeführt.
    Für die Index-Blattebenen wird eine I/O-Größe von 2 KByte verwendet.
    Mit LRU Pufferersetzungsstrategie für Index-Blattseiten.
    Für die Datenseiten wird eine I/O-Größe von 2 KByte verwendet.
    Mit LRU Pufferersetzungsstrategie für Datenseiten.

** 请求从日志文件中选择 **

20131118 08:44:59,845 FINE     sql      SELECT bookID, placeID FROM pub.BOOKING WHERE (placeID = ?)       bind => [207]

** 经过一番调查**

看来 sybase 的 smallint 数据类型是这里的问题。

Eclipselink 查询如下:

declare @p0 int
select @p0 = 5
select * from pub.BOOKING where placeID = @p0

如果我写声明@p0 smallint,则使用索引。 如果我写 declare @p0 int 则不使用索引。

所以我猜 JPA 正在将 Integer 映射到 int。这就是问题的根源。

我怎样才能告诉 JPA 在这个专栏中使用 smallint?

【问题讨论】:

  • persistence.xml 中添加以下属性: 然后向我们展示 Eclipselink 如何将您的 JPQL 查询转换为 SQL。
  • 我把它添加到上面的问题中
  • 很奇怪。有时优化器不使用索引,因为表太短(例如只有 15 条记录)或分布(不同的值)不适合使用索引(例如,您有一个只有 2 个不同值的列m' 和 'f' 并且它们都覆盖了约 50% 的行)。您是否为 GlassFish 和交互式 sql-editor 使用相同的数据库?如果是,我无法帮助您。
  • 你的意思只是成本计算的结果。如果表非常小,则加载整个表然后处理索引就不会那么“昂贵”。是的,:-) 它是同一个数据库和同一个表......我还测试了一个原生 sql 而不是 jpql。它的速度要快 1000 倍。意味着它与 sql 编辑器无关。它与 JPQL 有关。
  • 我可能发现了问题。但我不知道如何解决。请阅读上面的最后部分。

标签: eclipselink glassfish-3 jpql sap-ase


【解决方案1】:

问题在于 Smallint 数据类型。

我在实体类中使用了一个整数来访问它。它让 JPA 像这样查询:

declare @p0 int
select @p0 = 5
select bookID, placeID from pub.BOOKING where placeID = @p0

这让 sybase 确定“where”语句不是标准参数 (SARG)。这意味着它不能使用相应的索引,因为索引的数据类型是 2 字节,参数是 4 字节。

在实体中使用 Short 数据类型解决了这个问题。

** 我在 Sybase ASE 上进行了一些查询以找出问题所在**

您必须先安装 Sybase 的 MDA Feature。

如果你有一个表扫描,那就是这个节目:

select * 
from master.dbo.monSysPlanText 
order by SPID, BatchID, SequenceNumber

这个向你展示了 JPA 真正发送给 ASE 的查询:

select * 
from master.dbo.monSysSQLText

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-10
    • 2013-07-19
    • 2022-01-13
    • 2015-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多