Our company has been using PostgreSQL for a very long time and has found it a very solid product for our needs. One thing that we’ve run into is that as our database grows (1mil+
records), there is a major slowdown on page loads due to a PostgreSQL bug.
To resolve this, I had to re-create a new paginator that didn’t rely on the count(*) sql call. I changed it to work similar to how Google performs their queries relying solely on the offset and max to determine which pagination buttons to show.
packagecom.exampleimportorg.springframework.web.servlet.support.RequestContextUtilsasRCUclassPagerTagLib{/** * Creates next/previous links to support pagination for the current controller * This is developed to avoid problems with the PostgreSQL count(*) bug. * http://sql-info.de/postgresql/postgres-gotchas.html#1_7 * * <g:pager total="${accountListInstance.size()}" params="${params}" /> */defpager={attrs->defwriter=outif(attrs.total==null){throwTagError("Tag [pager] is missing required attribute [total] which is the total showing for the current page")}defmessageSource=grailsAttributes.messageSourcedeflocale=RCU.getLocale(request)deftotal=attrs.int('total')?:0defaction=(attrs.action?attrs.action:(params.action?params.action:"list"))defoffset=params.int('offset')?:0defmax=params.int('max')if(!offset)offset=(attrs.int('offset')?:0)if(!max)max=(attrs.int('max')?:10)deflinkParams=[:]if(attrs.params)linkParams.putAll(attrs.params)linkParams.offset=offset-maxlinkParams.max=maxif(params.sort)linkParams.sort=params.sortif(params.order)linkParams.order=params.orderdeflinkTagAttrs=[action:action]if(attrs.controller){linkTagAttrs.controller=attrs.controller}if(attrs.id!=null){linkTagAttrs.id=attrs.id}linkTagAttrs.params=linkParams// determine paging variablesdefisFirstStep=(offset==0)defisLastStep=(total<max)// display previous link when not on firststepif(!isFirstStep){linkTagAttrs.class='prevLink'linkParams.offset=offset-maxwriter<<link(linkTagAttrs.clone()){(attrs.prev?attrs.prev:messageSource.getMessage('paginate.prev',null,messageSource.getMessage('default.paginate.prev',null,'Previous',locale),locale))}}// display next link when not on laststepif(!isLastStep){linkTagAttrs.class='nextLink'linkParams.offset=offset+maxwriter<<link(linkTagAttrs.clone()){(attrs.next?attrs.next:messageSource.getMessage('paginate.next',null,messageSource.getMessage('default.paginate.next',null,'Next',locale),locale))}}}}