*Claim* The loop in ParameterParser.parse(String, ParameterParser$Recognizer) uses 100% CPU core per thread that executes it since it iterates over a string char by char and calling string operations in the loop.
*Java client* {code:java ) } Query query = getEntityManager().createQuery("select articleNumber from Article where articleNumber in (:articleNumbers)"); query.setParameter("articleNumbers", articleNumbers); List<ArticleNumber> filteredArticleNumbers = (List<ArticleNumber>) query.getResultList(); {code}
*Stacktrace of involved classes/methods* {noformat} ParameterParser.parse(String, ParameterParser$Recognizer) line: 88 ParamLocationRecognizer.parseLocations(String) line: 75 HQLQueryPlan.buildParameterMetadata(ParameterTranslations, String) line: 290 HQLQueryPlan.<init>(String, String, boolean, Map, SessionFactoryImplementor) line: 121 HQLQueryPlan.<init>(String, boolean, Map, SessionFactoryImplementor) line: 80 QueryPlanCache.getHQLQueryPlan(String, boolean, Map) line: 98 SessionImpl(AbstractSessionImpl).getHQLQueryPlan(String, boolean) line: 156 SessionImpl.list(String, QueryParameters) line: 1250 QueryImpl.list() line: 102 QueryImpl<X>.getResultList() line: 241 {noformat}
*Observations* {{QueryImpl#list()}} calls {{SessionImpl#list(String, QueryParameters)}} passing the _expanded_ query: {{return getSession().list(expandParameterLists(namedParams), getQueryParameters(namedParams));}}
Hence, what is passed to {{SessionImpl#list(String, QueryParameters)}} in my case is something like: {noformat} select articleNumber from Article where articleNumber in (:articleNumbers0_, :articleNumbers1_, :articleNumbers2_, :articleNumbers3_, :articleNumbers4_, :articleNumbers5_, :articleNumbers6_, {noformat} Now imagine how long that query string is when the "where in" query has a few thousand article numbers. {{ org.hibernate.engine.query.ParameterParser.parse(String, Recognizer) }} then iterates over each character in the query string and calls {{ StringHelper.firstIndexOfChar() }} for each named parameter. Even on fast servers this operation may easily take half an hour or more (mind you it's a blocking call!) if the expanded query string has a few million characters. I don't know Hibernate well enough to propose a fix but "where in" with Hibernate is an absolute no-go as it is right now. We had switch all our "where in" queries to native :-(
|