2013-04-11 69 views
0

我有一個包含144個記錄(行)的任務表。我使用普通的select查詢來獲取所有記錄,但JProfiler報告的方法所花費的時間對於這麼少量的數據來說太多了。休眠QueryImpl.list優化

Here是JProfiler的快照。

我擔心的是org.hibernate.impl.QueryImpl.list所花費的時間。當我在數據庫工具中運行正常的sql查詢時,它需要0.016秒來獲取所有記錄,但這裏需要更多時間。

我該如何縮短這個時間,達到什麼程度?這真的可以減少嗎?或約3秒是好嗎?

使用的數據庫是MySql。

下面是一個獲取日期

public List<Backlog> findBacklogList() { 
    Query query = (Query) getSession().createQuery("from Backlog"); 
    List<Backlog> backlogList = (List<Backlog>) query.list(); 
    return backlogList; 
} 

下面的方法是積壓POJO的

public class Backlog implements Serializable { 

/** 
* 
*/ 
private static final long serialVersionUID = 1L; 
private Long taskId; 
private String taskName; 
private TaskType taskType; 
private Member createdBy; // String 
private Date createdDate; 
private Member updatedBy; // String 
private Date updatedOn; 
private Status status; 
private Priority priority; 
private String approved; 
private Member completedBy; 
private Member ownedBy; 
private BacklogGroup group; 
private Set<OtherPeople> otherPeople; 
private String activeStatus; 
private String statusChanged; 
private String description; 
private Date expectedEndDate; 

/** 
* @return the taskId 
*/ 
@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
@Column(name = "taskid", nullable = false, unique = true, insertable = false) 
public Long getTaskId() { 
    return taskId; 
} 

/** 
* @param taskId 
*   the taskId to set 
*/ 
public void setTaskId(Long taskId) { 
    this.taskId = taskId; 
} 

/** 
* @return the taskName 
*/ 
@Column(name = "taskname", nullable = false, unique = true) 
public String getTaskName() { 
    return taskName; 
} 

/** 
* @param taskName 
*   the taskName to set 
*/ 
public void setTaskName(String taskName) { 
    this.taskName = taskName; 
} 

/** 
* @return the taskType 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "tasktype", referencedColumnName = "id", nullable = false) 
public TaskType getTaskType() { 
    return taskType; 
} 

/** 
* @param taskType 
*   the taskType to set 
*/ 
public void setTaskType(TaskType taskType) { 
    this.taskType = taskType; 
} 

/** 
* @return the createdDate 
*/ 
@Column(name = "createdDate", nullable = false) 
public Date getCreatedDate() { 
    return createdDate; 
} 

/** 
* @param createdDate 
*   the createdDate to set 
*/ 
public void setCreatedDate(Date createdDate) { 
    this.createdDate = createdDate; 
} 

/** 
* @return the updatedBy 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "updatedBy") 
public Member getUpdatedBy() { 
    return updatedBy; 
} 

/** 
* @param updatedBy 
*   the updatedBy to set 
*/ 
public void setUpdatedBy(Member updatedBy) { 
    this.updatedBy = updatedBy; 
} 

/** 
* @return the updatedOn 
*/ 
@Column(name = "updatedOn") 
public Date getUpdatedOn() { 
    return updatedOn; 
} 

/** 
* @param updatedOn 
*   the updatedOn to set 
*/ 
public void setUpdatedOn(Date updatedOn) { 
    this.updatedOn = updatedOn; 
} 

/** 
* @return the status 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "status", referencedColumnName = "id", nullable = false) 
public Status getStatus() { 
    return status; 
} 

/** 
* @param status 
*   the status to set 
*/ 
public void setStatus(Status status) { 
    this.status = status; 
} 

/** 
* @return the priority 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "priority", referencedColumnName = "id", nullable = false) 
public Priority getPriority() { 
    return priority; 
} 

/** 
* @param priority 
*   the priority to set 
*/ 
public void setPriority(Priority priority) { 
    this.priority = priority; 
} 

/** 
* @return the approved 
*/ 
@Column(name = "approved") 
public String getApproved() { 
    return approved; 
} 

/** 
* @param approved 
*   the approved to set 
*/ 
public void setApproved(String approved) { 
    this.approved = approved; 
} 

/** 
* @return the completedBy 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "completedBy") 
public Member getCompletedBy() { 
    return completedBy; 
} 

/** 
* @param completedBy 
*   the completedBy to set 
*/ 
public void setCompletedBy(Member completedBy) { 
    this.completedBy = completedBy; 
} 

/** 
* @return the otherPeople 
*/ 
@OneToMany(mappedBy = "task", cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
public Set<OtherPeople> getOtherPeople() { 
    return otherPeople; 
} 

/** 
* @param otherPeople 
*   the otherPeople to set 
*/ 
public void setOtherPeople(Set<OtherPeople> otherPeople) { 
    this.otherPeople = otherPeople; 
} 

/** 
* @return the group 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "groupid", referencedColumnName = "id", nullable = false) 
public BacklogGroup getGroup() { 
    return group; 
} 

/** 
* @param group 
*   the group to set 
*/ 
public void setGroup(BacklogGroup group) { 
    this.group = group; 
} 

/** 
* @return the createdBy 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "createdBy", nullable = false) 
public Member getCreatedBy() { 
    return createdBy; 
} 

/** 
* @param createdBy 
*   the createdBy to set 
*/ 
public void setCreatedBy(Member createdBy) { 
    this.createdBy = createdBy; 
} 

/** 
* @return the activeStatus 
*/ 
@Column(name = "activeStatus") 
public String getActiveStatus() { 
    return activeStatus; 
} 

/** 
* @param activeStatus 
*   the activeStatus to set 
*/ 
public void setActiveStatus(String activeStatus) { 
    this.activeStatus = activeStatus; 
} 

/** 
* @return the statusChanged 
*/ 
@Column(name = "statusChanged") 
public String getStatusChanged() { 
    return statusChanged; 
} 

@Column(name = "expectedEndDate") 
public Date getExpectedEndDate() { 
    return expectedEndDate; 
} 

public void setExpectedEndDate(Date expectedEndDate) { 
    this.expectedEndDate = expectedEndDate; 
} 

/** 
* @param statusChanged 
*   the statusChanged to set 
*/ 
public void setStatusChanged(String statusChanged) { 
    this.statusChanged = statusChanged; 
} 

/** 
* @return the description 
*/ 
@Column(name = "description", length = 5000) 
public String getDescription() { 
    return description; 
} 

/** 
* @param description 
*   the description to set 
*/ 
public void setDescription(String description) { 
    this.description = description; 
} 

/** 
* @return the ownedBy 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "ownedBy", nullable = false) 
public Member getOwnedBy() { 
    return ownedBy; 
} 

/** 
* @param ownedBy the ownedBy to set 
*/ 
public void setOwnedBy(Member ownedBy) { 
    this.ownedBy = ownedBy; 
} 

/* 
* (non-Javadoc) 
* @see java.lang.Object#hashCode() 
*/ 
@Override 
public int hashCode() { 
    final int prime = 31; 
    int result = 1; 
    result = prime * result + ((taskId == null) ? 0 : taskId.hashCode()); 
    return result; 
} 

/* 
* (non-Javadoc) 
* @see java.lang.Object#equals(java.lang.Object) 
*/ 
@Override 
public boolean equals(Object obj) { 
    if (this == obj) { 
     return true; 
    } 
    if (obj == null) { 
     return false; 
    } 
    if (!(obj instanceof Backlog)) { 
     return false; 
    } 
    Backlog other = (Backlog) obj; 
    if (taskId == null) { 
     if (other.taskId != null) { 
      return false; 
     } 
    } else if (!taskId.equals(other.taskId)) { 
     return false; 
    } 
    return true; 
} 

}

+0

發佈需要0.016秒才能獲取所有數據的正常查詢。 – 2013-04-11 05:57:20

+0

select * from backlog – 2013-04-11 05:58:59

+1

正如koljaTM所說,您的Backlog類有各種相關的pojos,這些pojos被設置爲熱切地獲取。所以當你獲取這個查詢來獲取這個關聯的數據也會被執行。將相關屬性延遲加載的良好做法會減少獲取Backlog數據所需的時間。 – 2013-04-11 06:02:03

回答

0

我的猜測是,該查詢獲得所有相關的數據,以及,例如其他人集,可能很大。嘗試激活hibernate sql日誌以查看哪些語句實際執行。如果您爲每個結果行(或甚至多個)獲取單獨的子查詢,則可能有問題。考慮不要急於獲取或將某些關係設置爲FetchJoin,以便數據立即連接,如果您知道您將需要它。 如果您不需要數據,請不要選擇它。如果您對大量結果感興趣,但僅對其中的較小數據子集(例如,對於概覽列表)有時,建立一個僅用於查詢的額外對象也是一個好主意。

+0

感謝koljaTM,懶惰的抓取做到了把戲,並將時間縮短到了1205ms,但是再一次,** org.hibernate.PersistentSet.isEmpty **正在被調用,另外需要1705ms的時間加上該方法的總時間爲3秒。在這種情況下還能做些什麼? – 2013-04-11 06:39:42

+0

[jprofiler快照](https://lh3.googleusercontent.com/-E0KW_zFELGo/UWZW7yH2edI/AAAAAAAAAoE/5UW83-unOS4/s555/jprofiler2.png) – 2013-04-11 06:40:38

0

爲了減少在使用Hibernate時獲取數據所需的時間,首先要儘可能使用Lazy加載。

@ManyToOne(fetch = FetchType.EAGER)// This will take more time 

在您的pojo改變EAGER加載到LAZY如果可能的話。

@ManyToOne(fetch = FetchType.LAZY) 

另一件事是使印刷Hibernate執行查詢,那裏你可以看到很多實際的查詢是如何得到執行,以獲取單個對象。

您可以通過在休眠配置中將hibernate.show_sql屬性設置爲true來完成此操作。

<property name="show_sql">true</property> 

您可以在here瞭解更多關於休眠優化的信息。

+0

您好code13,我已經做到了這一點,減少了時間,但作爲你可以請參閱上面的註釋,PersistentSet類有一個新的問題。請參閱[快照](https://lh3.googleusercontent.com/-E0KW_zFELGo/UWZW7yH2edI/AAAAAAAAAoE/5UW83-unOS4/s555/jprofiler2.png) – 2013-04-11 07:07:15