我使用Spring + hibernate对我的数据库进行查询。数据库大小约为101k行。
我做了以下规范
Predicate predicate = cb.notEqual(root.get("trscnStatus").as(String.class),
TradeTransactionStatus.DELETED.name());
predicate = cb.and(predicate, cb.equal(root.get("portfolioName"),
searchCriteria.getPortfolioName()));
我做了
transactionRepository.findAll(transactionsSearchCriteria, sort);
其中是transactionsSearchCriteria我的规范与上面提到的谓词!
我的域名模型是下一个:
@Entity(name="TradeTransactional")
@Table(name="TRANSACTIONS")
public class TradeTransaction implements Serializable, Cloneable{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* The id.
*/
@Id
@GeneratedValue
private long id;
/**
* The description.
*/
private String description = "";
/**
* The comments.
*/
private String comments = "";
/**
* The mv inv ccy.
*/
@Column(name="mv_inv_ccy")
private double mvInvCcy;
/**
* The mv inv ccy eur.
*/
@Column(name="mv_inv_ccy_eur")
private double mvInvCcyEur;
/**
* The mv inv ccy usd.
*/
@Column(name="mv_inv_ccy_usd")
private double mvInvCcyUsd;
/**
* The portfolio name.
*/
@Column(name="portfolio_name")
private String portfolioName = "";
/**
* The bbticker.
*/
@Column(name="ticker")
private String ticker = "";
/**
* The pershing ref.
*/
@Column(name="brg_ref")
private String portfolioRef = "";
/**
* The trade ref.
*/
@Column(name="trade_ref")
private String uniqueRef = "";
/**
* The b2b ref.
*/
@Column(name="b2b_ref")
private String b2bRef = "";
/**
* The sedol ticker.
*/
@Column(name="sedol_ticker")
private String sedolTicker = "";
/**
* The security number.
*/
@Column(name="id_isin")
private String securityNumber="";
/**
* Aggregate
*/
@Column(name="aggregate")
private boolean aggregate = false;
/**
* The purchase date.
*/
@Column(name="purchase_date")
private Date purchaseDate;
/**
* The settl date.
*/
@Column(name="settl_date")
private Date settlDate;
@Column(name="effect_date")
private Date effectDate;
private Date timestamp = new Date();
@Column(name="conf_timestamp")
private Date conftimestamp = new Date();
/**
* The purchase price.
*/
@Column(name="purchase_price")
private double purchasePrice;
/**
* The number of shares.
*/
@Column(name="number_of_shares")
private double numberOfShares;
/**
* The number of shares nominal
*/
@Column(name="number_of_shares_nominal")
private double numberOfSharesNominal=0;
/**
* The pdf confirmation link.
*/
@Column(name="pdf_confirmation_link")
private String confirmationFileName;
/**
* The reference number.
*/
@Column(name="reference_number")
private String referenceNumber;
@Transient
private double contractSize = 1;
@Transient
private String globalId;
/**
* The name.
*/
private String name = "";
/**
* The ccy.
*/
@Column(name="crncy")
private String ccy = "";
/**
* The ccy settl.
*/
@Column(name="crncy_settl")
private String ccySettl = "";
/**
* The custody.
*/
private String custody="";
/**
* The exch code.
*/
@Column(name="exch_code")
private String exchCode="";
/**
* The country of risk.
*/
@Column(name="cntry_of_risk")
private String countryOfRisk="";
/**
* The stl sts.
*/
@Column(name="stl_sts")
private String stlSts;
/**
* The stl amt base.
*/
@Column(name="stl_amt_base")
private double stlAmtBase;
private double accrued;
@Column(name="reconciled")
private boolean reconciled = false;
@Column(name="cntrprty")
private String counterpartyName = "";
@Enumerated(EnumType.STRING)
@Column(name="trscn_status")
private TradeTransactionStatus trscnStatus = TradeTransactionStatus.ACTIVE;
@Column(name="cash_account")
private String cashAccount;
@Column(name="counterparty")
private String counterpartyAccount="";
@Enumerated(EnumType.STRING)
@Column(name="trade_type")
private TradeTransactionType tradeType = TradeTransactionType.UNKNOWN;
@Column(name="allocated")
private boolean allocated = true;
@Column(name="market_sector_des")
private String marketSectorDes = "";
@Column(name = "trader_uuid")
private String traderUUID;
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getDescription()
*/
public String getDescription() {
return description;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getId()
*/
public long getId() {
return id;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getMvInvCcy()
*/
public double getMvInvCcy() {
return mvInvCcy;
}
/**
* Sets the id.
*
* @param id
* the new id
*/
public void setId(long id) {
this.id = id;
}
/**
* Sets the description.
*
* @param description
* the new description
*/
public void setDescription(String description) {
this.description = description;
}
/**
* Sets the mv inv ccy.
*
* @param mvInvCcy
* the new mv inv ccy
*/
public void setMvInvCcy(double mvInvCcy) {
this.mvInvCcy = mvInvCcy;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getPortfolioName()
*/
public String getPortfolioName() {
return portfolioName;
}
/**
* Sets the portfolio name.
*
* @param portfolioName
* the new portfolio name
*/
public void setPortfolioName(String portfolioName) {
this.portfolioName = portfolioName;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getBbticker()
*/
public String getTicker() {
return ticker;
}
/**
* Sets the bbticker.
*
* @param bbticker
* the new bbticker
*/
public void setTicker(String ticker) {
this.ticker = ticker;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getAggregate()
*/
public boolean getAggregate() {
return aggregate;
}
/**
* Sets the index.
*
* @param index
* the new aggregate
*/
public void setAggregate(boolean aggregate) {
this.aggregate = aggregate;
}
/**
* @return the allocated
*/
public boolean getAllocated() {
return allocated;
}
/**
* @param allocated the allocated to set
*/
public void setAllocated(boolean allocated) {
this.allocated = allocated;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getName()
*/
public String getName() {
return name;
}
/**
* Sets the name.
*
* @param name
* the new name
*/
public void setName(String name) {
this.name = name;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getCcy()
*/
public String getCcy() {
return ccy;
}
/**
* Sets the ccy.
*
* @param ccy
* the new ccy
*/
public void setCcy(String ccy) {
this.ccy = ccy;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getMvInvCcyEur()
*/
public double getMvInvCcyEur() {
return mvInvCcyEur;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getMvInvCcyUsd()
*/
public double getMvInvCcyUsd() {
return mvInvCcyUsd;
}
/**
* Sets the mv inv ccy eur.
*
* @param mvInvCcyEur
* the new mv inv ccy eur
*/
public void setMvInvCcyEur(double mvInvCcyEur) {
this.mvInvCcyEur = mvInvCcyEur;
}
/**
* Sets the mv inv ccy usd.
*
* @param mvInvCcyUsd
* the new mv inv ccy usd
*/
public void setMvInvCcyUsd(double mvInvCcyUsd) {
this.mvInvCcyUsd = mvInvCcyUsd;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getSecurityNumber()
*/
public String getSecurityNumber() {
return securityNumber;
}
/**
* Sets the security number.
*
* @param securityNumber
* the new security number
*/
public void setSecurityNumber(String securityNumber) {
this.securityNumber = securityNumber;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getPershingRef()
*/
public String getPortfolioRef() {
return portfolioRef;
}
/**
* Sets the pershing ref.
*
* @param pershingRef
* the new pershing ref
*/
public void setPortfolioRef(String portfolioRef) {
this.portfolioRef = portfolioRef;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getSedolTicker()
*/
public String getSedolTicker() {
return sedolTicker;
}
/**
* Sets the sedol ticker.
*
* @param sedolTicker
* the new sedol ticker
*/
public void setSedolTicker(String sedolTicker) {
this.sedolTicker = sedolTicker;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getPurchaseDate()
*/
public Date getPurchaseDate() {
return purchaseDate;
}
/**
* Sets the purchase date.
*
* @param purchaseDate
* the new purchase date
*/
public void setPurchaseDate(Date purchaseDate) {
this.purchaseDate = purchaseDate;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getNumberOfShares()
*/
public double getNumberOfShares() {
return numberOfShares;
}
/**
* Sets the number of shares.
*
* @param numberOfShares
* the new number of shares
*/
public void setNumberOfShares(double numberOfShares) {
this.numberOfShares = numberOfShares;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getPurchasePrice()
*/
public double getPurchasePrice() {
return purchasePrice;
}
/**
* Sets the purchase price.
*
* @param purchasePrice
* the new purchase price
*/
public void setPurchasePrice(double purchasePrice) {
this.purchasePrice = purchasePrice;
}
/**
* Sets the string purhcase date to date.
*
* @param purchaseDate
* the purchase date
* @param parsePatterns
* the parse patterns
* @throws Exception
* the exception
*/
@Transient
public void setStringPurhcaseDateToDate(String purchaseDate, String... parsePatterns) throws Exception{
Date date = DateUtils.parseDate(purchaseDate, parsePatterns);
setPurchaseDate(date);
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getCustody()
*/
public String getCustody() {
return custody;
}
/**
* Sets the custody.
*
* @param custody
* the new custody
*/
public void setCustody(String custody) {
this.custody = custody;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getExchCode()
*/
public String getExchCode() {
return exchCode;
}
/**
* Sets the exch code.
*
* @param exchCode
* the new exch code
*/
public void setExchCode(String exchCode) {
this.exchCode = exchCode;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getComments()
*/
public String getComments() {
return comments;
}
/**
* Sets the comments.
*
* @param comments
* the new comments
*/
public void setComments(String comments) {
this.comments = comments;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getPdfConfirmationLink()
*/
public String getConfirmationFileName() {
return this.confirmationFileName;
}
/**
* Sets the pdf confirmation link.
*
* @param pdfConfirmationLink
* the new pdf confirmation link
*/
public void setConfirmationFileName(String confirmationFileName) {
this.confirmationFileName = confirmationFileName;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getReferenceNumber()
*/
public String getReferenceNumber() {
return referenceNumber;
}
/**
* Sets the reference number.
*
* @param referenceNumber
* the new reference number
*/
public void setReferenceNumber(String referenceNumber) {
this.referenceNumber = referenceNumber;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getStlSts()
*/
public String getStlSts() {
return stlSts;
}
/**
* Sets the stl sts.
*
* @param stlSts
* the new stl sts
*/
public void setStlSts(String stlSts) {
this.stlSts = stlSts;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getStlAmtBase()
*/
public double getStlAmtBase() {
return stlAmtBase;
}
/**
* Sets the stl amt base.
*
* @param stlAmtBase
* the new stl amt base
*/
public void setStlAmtBase(double stlAmtBase) {
this.stlAmtBase = stlAmtBase;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getSettlDate()
*/
public Date getSettlDate() {
return settlDate;
}
/**
* Sets the settl date.
*
* @param settlDate
* the new settl date
*/
public void setSettlDate(Date settlDate) {
this.settlDate = settlDate;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getCcySettl()
*/
public String getCcySettl() {
return ccySettl;
}
/**
* Sets the ccy settl.
*
* @param ccySettl
* the new ccy settl
*/
public void setCcySettl(String ccySettl) {
this.ccySettl = ccySettl;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getTradeRef()
*/
public String getUniqueRef() {
return uniqueRef;
}
/**
* Sets the trade ref.
*
* @param tradeRef
* the new trade ref
*/
public void setUniqueRef(String uniqueRef) {
this.uniqueRef = uniqueRef;
}
/* (non-Javadoc)
* @see com.meritservus.domain.TradeTransaction#getB2bRef()
*/
public String getB2bRef() {
return b2bRef;
}
/**
* Sets the b2b ref.
*
* @param b2bRef
* the new b2b ref
*/
public void setB2bRef(String b2bRef) {
this.b2bRef = b2bRef;
}
public Date getTimestamp() {
return timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
public TradeTransactionStatus getTrscnStatus() {
return trscnStatus;
}
public void setTrscnStatus(TradeTransactionStatus trscnStatus) {
this.trscnStatus = trscnStatus;
}
public String getCashAccount() {
return cashAccount;
}
public void setCashAccount(String cashAccount) {
this.cashAccount = cashAccount;
}
/**
* @return the counterparty
*/
public String getCounterpartyAccount() {
return counterpartyAccount;
}
/**
* @param counterparty the counterparty to set
*/
public void setCounterpartyAccount(String counterpartyAccount) {
this.counterpartyAccount = counterpartyAccount;
}
/**
* @return the effectDate
*/
public Date getEffectDate() {
return effectDate;
}
/**
* @param effectDate the effectDate to set
*/
public void setEffectDate(Date effectDate) {
this.effectDate = effectDate;
}
public double getNumberOfSharesNominal() {
return numberOfSharesNominal;
}
public void setNumberOfSharesNominal(double numberOfSharesNominal) {
this.numberOfSharesNominal = numberOfSharesNominal;
}
/**
* @return the tradeType
*/
public TradeTransactionType getTradeType() {
return tradeType;
}
/**
* @param tradeType the tradeType to set
*/
public void setTradeType(TradeTransactionType tradeType) {
this.tradeType = tradeType;
}
/**
* @return the confTimestamp
*/
public Date getConftimestamp() {
return conftimestamp;
}
/**
* @param confTimestamp the confTimestamp to set
*/
public void setConftimestamp(Date confTimestamp) {
this.conftimestamp = confTimestamp;
}
/**
* @return the countryOfRisk
*/
public String getCountryOfRisk() {
return countryOfRisk;
}
/**
* @param countryOfRisk the countryOfRisk to set
*/
public void setCountryOfRisk(String countryOfRisk) {
this.countryOfRisk = countryOfRisk;
}
/**
* @return the reconciled
*/
public boolean isReconciled() {
return reconciled;
}
/**
* @param reconciled the reconciled to set
*/
public void setReconciled(boolean reconciled) {
this.reconciled = reconciled;
}
/**
* @return the cntrprty
*/
public String getCounterpartyName() {
return counterpartyName;
}
/**
* @param cntrprty the cntrprty to set
*/
public void setCounterpartyName(String counterpartyName) {
this.counterpartyName = counterpartyName;
}
public String getMarketSectorDes() {
return marketSectorDes;
}
public void setMarketSectorDes(String marketSectorDes) {
this.marketSectorDes = marketSectorDes;
}
public String getTraderUUID() {
return traderUUID;
}
public void setTraderUUID(String traderUUID) {
this.traderUUID = traderUUID;
}
/**
* @return the accrued
*/
public double getAccrued() {
return accrued;
}
/**
* @param accrued the accrued to set
*/
public void setAccrued(double accrued) {
this.accrued = accrued;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public double getContractSize() {
return contractSize;
}
public void setContractSize(double contractSize) {
this.contractSize = contractSize;
}
public String getGlobalId() {
return globalId;
}
public void setGlobalId(String globalId) {
this.globalId = globalId;
}
}
我的Hibernate配置是下一个:
properties.put("hibernate.dialect","org.hibernate.dialect.MySQL5Dialect" );
properties.put( "hibernate.autocommit", "false" );
properties.put( "hibernate.jdbc.batch_size", "1000" );
properties.put( "hibernate.jdbc.fetch_size", "1000" );
properties.put( "hibernate.connection.autocommit", "false" );
properties.put( "hibernate.cache.use_second_level_cache", "false" );
properties.put("hibernate.cache.provider_class","org.hibernate.cache.NoCacheProvider");
properties.put( "hibernate.connection.CharSet", "utf8" );
properties.put( "hibernate.connection.characterEncoding", "utf8" );
properties.put( "hibernate.connection.useUnicode", "true" );
properties.put( "hibernate.enable_lazy_load_no_trans", "true" );
当我查询时,我的下一个hibernate统计信息:
09:45:08.694 [http-nio-8182-exec-4] INFO o.h.e.i.StatisticalLoggingSessionEventListener - Session Metrics {
47217 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
444974 nanoseconds spent preparing 1 JDBC statements;
8947089681 nanoseconds spent executing 1 JDBC statements;
0 nanoseconds spent executing 0 JDBC batches;
0 nanoseconds spent performing 0 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
8725 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}
这个查询带我20SEC!从我的数据库中获取30k行(内部包含20个字段的普通Transaction对象列表)。我认为这太慢了。如何加快查询速度?
答案 0 :(得分:1)
首先,我必须做出免责声明,Hibernate的性能取决于许多不同的因素,很难给出确切的答案。特别是没有实体模型。
但我可以提出一些建议并分享一些经验。
一旦我不得不优化一个Hibernate查询,它获取了1500个对象,并且需要6秒才能完成。
首先,我通过启用SQL日志记录来检查Hibernate实际运行的查询:
How to print a query string with parameter values when using Hibernate
日志由负载所有与提取对象相关的对象的查询负担。这是因为所有字段都是序列化的,包括相关对象的字段(这是一个报告)。
事实证明这是一个众所周知的情况(虽然不是我那个时候)称为“N + 1问题”。
这是关于这个主题的问题:
What is the solution for the N+1 issue in hibernate?
那里的答案为此提供了不同的解决方案。
我最终将该查询重写为带有连接的本机查询。新查询只用了0.01秒。当然,这种方法不会自动适用于所有情况。
所以,我建议(按顺序):
答案 1 :(得分:0)
您正在查询大约30000行... Hibernate库将实例化对象,加载数据,填充表中的数据并重复此过程30000次。如果每个对象加载0.0005秒,这将是正常时间。
我认为0.0005非常好,但如果您还需要,请阅读有关优化查询的this article。