I am sure I can improve the performance of the following findByName query of hibernate:
public List<User> findByName(String name) {
session.createCriteria(User.class).add(Restrictions.eq("name", name)).list();
}
The bottleneck is that findByName method and I cannot use the id instead.
In my case I know that the name is unique but adding an Index annotation to the name attribute didn't improve the performance. I did the following:
class User {
@Index(name = "nameIdx")
private String name;
}
In which way should I improve it or even more important: in which ways should I improve it first? I will need the full object with all the collections (layz or not) and deps of this class.
Or can I improve it, if I want several User objects (and know several names)?
Update1:
The @Index annotation didn't improve the performance, because the database already had an index, because of my unique constraint annotation:
@UniqueConstraint(columnNames = {"name"})
Update2:
Read the answers carefully!
With the help of the SQL logging I saw that the real issue was that a lot of update and insert statements were raised although I did not commit or flush the transaction. The reason behind that was that I did (in a loop):
User u = findByName(name); if(u == null) attach(u = new User(name));
and so hibernate needs to flush the newly created users to the db before every findByName query. I solved this with my own cache workaround (LinkedHashMap).
Another improvement I made through Jens Schauder's tip:
public Collection<User> findByNames(Collection<String> names) { return session.createCriteria(User.class). add(Restrictions.in("name", names)).list(); }
A further improvement could be made when specifying some of the user collection as not lazy:
@LazyCollection(LazyCollectionOption.FALSE)
Read this answer to get an even better option.
The last and most important one for me is: replacing my SortedSet items with a list and doing the following in the getItems method:
Set set = new LinkedHashSet(items); items.clear(); items.addAll(set); Collections.sort(items, itemComparator); return Collections.unmodifiableCollection(items);
with that, hibernate can work on the items collection (i.e. adding) without loading the entire collection from database.
@Pascal Thivent and @Jens Schauder: bunch of thanks! Sorry, that I can only accept one answer :-/
Helpful Logging settings:
log4j.logger.org.hibernate.tool.hbm2ddl=INFO, StdoutApp
log4j.logger.org.hibernate.SQL=INFO, StdoutApp
# additionally provide the information which parameters will be bound:
log4j.logger.org.hibernate.type=TRACE