Pergunta

Eu tenho uma implementação atual do will_paginate que utiliza o paginate_by_sql método para construir a coleção para ser paginado. Temos uma consulta personalizada para total_entries que é muito complicado e coloca uma grande carga sobre o nosso DB. Por isso, gostaríamos de cortar total_entries do pagination completamente.

Em outras palavras, em vez do visor pagination típico de 'anterior [1] 2 3 4 5 seguinte', nós simplesmente como um botão - 'anterior próximo' apenas. Mas precisamos saber algumas coisas.

  1. Será que exibir o link anterior? Isso só poderia ocorrer naturalmente se registros existentes antes aqueles exibidos na seleção atual
  2. Será que exibir o próximo link? Isso não seria exibido se o último registro na coleção está sendo exibido

A partir da docs

A consulta para as linhas de contagem vai automaticamente ser gerados se não fornecer: total_entries. Se vocês problemas experiência com este SQL gerado, você pode querer realizar a contagem manualmente no seu aplicação.

Assim, em última análise, a situação ideal é o seguinte.

  • Remova os total_entries contar porque ele está causando muita carga no banco de dados
  • Mostrar 50 registros em um momento com semi-pagination usando apenas seguinte botões / anteriores de navegar e não precisar exibir todos os números de página disponível
  • Apenas exibir o botão seguinte e botão anterior em conformidade

Alguém já trabalhou com um problema semelhante ou ter pensamentos sobre uma resolução?

Foi útil?

Solução

Há muitas ocasiões em que will_paginate faz um trabalho realmente terrível de calcular o número de entradas, especialmente se houver junta envolvidos que confundem o gerador de contagem SQL.

Se tudo que você precisa é de um anterior / seguinte método simples, então tudo que você precisa fazer é tentar recuperar N + 1 entradas do banco de dados, e se você só tem N ou menos do que você está na última página.

Por exemplo:

per_page = 10
page = 2

@entries = Thing.with_some_scope.find(:all, :limit => per_page + 1, :offset => (page - 1) * per_page)

@next_page = @entries.slice!(per_page, 1)
@prev_page = page > 1

Você pode facilmente encapsular isso em algum módulo que pode ser incluído nos vários modelos que exigem-lo, ou fazer uma extensão de controlador.

Eu descobri que isso funciona muito melhor do que o método will_paginate padrão.

O único problema de desempenho é uma limitação do MySQL que pode ser um problema, dependendo do tamanho de suas tabelas.

Por alguma razão, a quantidade de tempo que leva para realizar uma consulta com um pequeno LIMIT no MySQL é proporcional ao deslocamento. Com efeito, o motor de banco de dados lê através de todas as linhas que levam até o valor de deslocamento particular, em seguida, retorna a próxima linhas Número limite, não pular à frente como você esperaria.

Para grandes conjuntos de dados, onde você está tendo valores de deslocamento no intervalo de 100.000 mais, você pode encontrar desempenho diminui significativamente. Como isso vai se manifestar é que o carregamento da página 1 é muito rápido, página 1000 é um pouco lento, mas a página 2000 é extremamente lento.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top