使用 createNativeQuery 的性能问题

performance issue using createNativeQuery

我遇到了性能问题,但是,尽管它在主题中提出了建议,但可能不是我在使用 createNativeQuery。我有一个相当大的查询,我将其作为字符串传递给 createNativeQuery。该查询包含多个 JOIN,并与 5 个实体相关联。查询平均需要 20 - 25 秒才能完成 运行。我已经尝试过,比如尝试 createQuery 方法和使用 setFlushMode(FlushModeType.COMMIT)、setMaxResults() 和 setFirstResult() 方法,但没有任何区别。

我们在 JTA 容器管理环境中使用 JBoss EAP 6.2,使用 EJB 3.0、JPA 2.1、Hibernate 4.2。我使用的 IDE 是 NetBeans 8.0.2

然而,如果我 运行 直接在 SQL 工具(如 DB Visualizer)中查询,则需要几毫秒。我怀疑它可能与 Hibernate 有关,但不确定。 Entity 类 的 None 包含一个集合,尽管表之间存在特定关系,如查询中的 JOIN 语句所示。我在下面附上了一些代码(包括查询)。

我希望按原样保留查询,但如果提出可以提高效率的建议,我愿意接受。我知道这可能很难回答,因为在不知道数据库模式的情况下可能难以分析下面的查询(这是一个公司项目,因此在某些情况下只能提供伪代码)。我也没有提供 Entity 或 Facade 类,但如有必要,稍后可以提供。任何帮助将不胜感激。谢谢!

public List<String> searchSingleView (String sourceSystem, String sourceClientId, String convertedClientId, String policyNum) {

   String sqlQuery = "SELECT DISTINCT " +
      "MDMCUST_ORS.C_BO_PARTY_XREF.ROWID_XREF, " +                                      "MDMCUST_ORS.C_BO_CONTRACT.LAST_ROWID_SYSTEM, " +
                                    "MDMCUST_ORS.C_BO_CONTRACT.SRC_POLICY_ID, " +
                                    "MDMCUST_ORS.C_BO_CONTRACT.ISSUE_DT, " +
                                    "MDMCUST_ORS.C_BO_PARTY_XREF.SRC_CLIENT_ID, " +
                                    "MDMCUST_ORS.C_BO_PARTY_XREF.PERS_FULL_NAME_TXT, " +
                                    "MDMCUST_ORS.C_BO_PARTY_XREF.PERS_SRC_NAME_TXT, " +
                                    "MDMCUST_ORS.C_BO_PARTY_XREF.ORG_LEGAL_NAME_TXT, " +
                                    "MDMCUST_ORS.C_BO_PARTY_XREF.ORG_SRC_NAME_TXT, " +
                                    "MDMCUST_ORS.C_BO_PARTY_XREF.ORG_LEGAL_SFX_TXT, " +
                                    "MDMCUST_ORS.C_BO_PARTY_XREF.ORG_NAME_TXT, " +
                                    "MDMCUST_ORS.C_BO_PARTY_XREF.SIN_BIN_TEXT, " +
                                    "MDMCUST_ORS.C_BO_PARTY_XREF.PERS_BIRTH_DT, " +
                                    "MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF.LAST_UPDATE_DATE, " +
                                    "MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF.COMPLETE_ADDRESS_TXT, " +
                                    "MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF.TOPLINE_POSTAL_ADDR_TXT, " +
                                    "MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF.CITY_NAME, " +
                                    "MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF.COUNTRY_NAME, " +
                                    "MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF.POSTAL_CD, " +
                                    "MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF.POSTAL_ADDR_PURPOSE_CD, " +
                                    "MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF.STATE_PROVINCE_NAME, " +
                                    "MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF.BAD_ADDR_IND " +
                                    "FROM MDMCUST_ORS.C_BO_PARTY_XREF " +
                                    "LEFT JOIN MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF ON " + 
                                    "(MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF.S_PARTY_ROWID = MDMCUST_ORS.C_BO_PARTY_XREF.SRC_CLIENT_ID " +
                                        "OR MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF.S_PARTY_ROWID = MDMCUST_ORS.C_BO_PARTY_XREF.CONVERTED_CLIENT_ID) " +      
                                    "LEFT JOIN MDMCUST_ORS.C_LU_CODES ON MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF.POSTAL_ADDR_PURPOSE_CD = MDMCUST_ORS.C_LU_CODES.CODE " +
                                    "LEFT JOIN MDMCUST_ORS.C_BO_PARTY_REL ON MDMCUST_ORS.C_BO_PARTY_XREF.ROWID_OBJECT = MDMCUST_ORS.C_BO_PARTY_REL.FROM_PARTY_ROWID " +
                                    "LEFT JOIN MDMCUST_ORS.C_BO_CONTRACT ON MDMCUST_ORS.C_BO_PARTY_REL.CONTRACT_ROWID = MDMCUST_ORS.C_BO_CONTRACT.ROWID_OBJECT " +
                                "WHERE MDMCUST_ORS.C_BO_CONTRACT.LAST_ROWID_SYSTEM IN ('E-CAPSIL', 'C-CAPSIL', 'INGENIUM') " +
                                    "AND (UPPER(MDMCUST_ORS.C_BO_PARTY_XREF.SRC_CLIENT_ID) = ? " +
                                    "     OR UPPER(MDMCUST_ORS.C_BO_PARTY_XREF.CONVERTED_CLIENT_ID) = ? " +
                                    "     ) " +
                                    "AND UPPER(MDMCUST_ORS.C_BO_CONTRACT.SRC_POLICY_ID) = ? " +
                                    "AND MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF.POSTAL_ADDR_PURPOSE_CD = '56|07'" +
                                    "AND MDMCUST_ORS.C_BO_PARTY_XREF.HUB_STATE_IND = '1' " +
                                    "AND MDMCUST_ORS.C_BO_CONTRACT.HUB_STATE_IND = '1' " +
                                    "AND MDMCUST_ORS.C_BO_PARTY_POSTAL_ADDR_XREF.HUB_STATE_IND = '1' " + 
                                    "AND MDMCUST_ORS.C_LU_CODES.HUB_STATE_IND = '1'" +
                                    "AND ROWNUM = 1";

try {
            querySingleView = emSingleView.createNativeQuery(sqlSingleViewQuery)
                                          .setParameter(1, sourceClientId)
                                          .setParameter(2, convertedClientId)
                                          .setParameter(3, policyNum);
            querySingleViewResult = (List<String>) querySingleView.getResultList();
        } catch (NoResultException nre) {
          // Issue a validation failure message to prevent query from continuing.
            FacesContext.getCurrentInstance().validationFailed();
            // Display error message to user
            JsfUtil.addErrorMessage(ResourceBundle.getBundle("/Bundle").getString("fatcaSearchSingleViewFailMessage"));
            // Generate log entry on server
            java.util.logging.Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, nre);
        }
        return querySingleViewResult;
    }

这个

UPPER(MDMCUST_ORS.C_BO_CONTRACT.SRC_POLICY_ID) = ? " 

很可能会阻止 Oracle 在 SRC_POLICY_ID 上使用索引。 MI 如果它是一个 ID,我希望它是一个数字,因此不需要 UPPER。如果您确实确实需要 UPPER,那么您应该在该列上创建一个基于函数的索引。

但是如果无法访问数据库,性能问题就很难解决。

P.S.: 你真的需要 DISTINCT 和 ROWNUMBER=1 吗?我认为您应该通过在 WHERE 子句中使用适当的条件来编写只获得一行的查询。