Como implementar uma API de Pesquisa ao Digitar (SAYT) mais rápida no aplicativo Rails 3

9

Eu estou tendo milhões de registros no meu banco de dados mysql. Implementei uma API REST normal para o aplicativo do iPhone no Rails 3, mas a resposta do recurso SAYT é muito lenta. Demora muito tempo para pesquisar o banco de dados e retornar os resultados. Como posso melhorar o desempenho?

Eu indexei minhas tabelas. Como todos os aspectos devem ser mais parecidos com o ajuste do MySQL, ou devo usar rails sphinx ou sunspot? Isso ajudará Por favor me ajude com todos os seus conselhos de especialistas.

    
por Amal Kumar S 24.02.2012 в 07:12
fonte

6 respostas

2

Concordo com a resposta geral: use um mecanismo de busca como o Sphinx (e limite o número de resultados retornados); eles são projetados para fazer exatamente o que você quer.

No entanto, embora milhões de registros possam parecer muito, você deve primeiro determinar o que está demorando. Eu tenho grande amor por Sphinx e ThinkingSphinx - eles tomam o que é um processo bastante complexo e o tornam bastante simples e fácil. Mas, no final, um mecanismo de busca é outro sistema para gerenciar, configurar, aprender e conhecer. Se você não tem que ir lá, é mais fácil não, né?

Pode ser a consulta, pode ser o tempo gasto retornando os dados ( limit é seu amigo!). Ou pode ser que você receba centenas de solicitações por segundo, talvez porque o atraso no preenchimento automático seja muito curto - se ocorrer uma pesquisa em todos os caracteres, digitadores rápidos ou vários usuários podem facilmente invadir o servidor com consultas que não fornecem utilidade para o usuário.

Assista os logs do Rails e veja o que realmente está acontecendo. Se é um problema de desempenho de consulta simples, fazendo uma pesquisa de texto completo complicada, então, sim, isso vai ser lento e o Sphinx valerá o esforço. Seu banco de dados possui uma ferramenta explain que, com algum trabalho, pode ajudá-lo a entender o que o banco de dados está fazendo para obter o resultado. Não é incomum que um índice não seja usado.

E quanto ao armazenamento em cache? O Memcached é uma ferramenta fantástica. Ou talvez até mesmo suas configurações de tamanho de buffer para o banco de dados possam permitir que ele use mais memória para armazenamento em cache.

    
por Tom Harrison Jr 14.03.2012 / 20:28
fonte
1

Não sei ao certo o que você quer dizer ao adicionar uma pesquisa mais rápida, mas é bom limitar os resultados da pesquisa a 100, já que ela afeta a usabilidade. Poucos usuários passarão por 100 registros para a pesquisa.

Para alcançar essa pesquisa, sugiro que você inclua a tabela de palavras-chave. A tabela de palavras-chave deve consistir no ID do registro e na palavra-chave associada a ela e quantas vezes a palavra-chave foi transacionada no banco de dados.

Assim, ele ajudará você a determinar os cem melhores registros e a pesquisa mais precisa.

Existem muitos algoritmos que também pesquisam como Map Reduce, que é executado simultaneamente. Eu não acho que a tecnologia do seu dispositivo móvel possa lidar com a redução de mapas.

    
por madi 25.02.2012 / 19:24
fonte
1

Também recomendo usar um mecanismo de pesquisa de texto completo como o Sphinx.

Há um bom screencast sobre como usar o Sphinx e os rails com a gem thinking_sphinx:

Railscast thinking_sphinx gem

Com essa gema, você também pode afetar o resultado da pesquisa em relação à importância, por exemplo, adicionando pesos de campo:

Documentação do Sphinx em Pensamento

Como é um dispositivo móvel, eu também manteria a quantidade de resultados enviados para o celular em um mínimo, já que o madi já mencionou isso.

Divirta-se

    
por holger81 01.03.2012 / 18:12
fonte
1

Para pesquisar milhões de registros rapidamente, provavelmente você vai querer usar uma estrutura de dados do tipo trie. O link tem código de amostra do ruby se você quiser ajuda.

Simplificado um pouco, o trie é um método altamente eficiente de rastrear o que as crianças pertencem à lista inicial de caracteres.

Essencialmente, o seu técnico SAYT usaria uma string e retornaria os 15 ou mais resultados da entrada da trie para essa string.

Dependendo de como suas linhas são semelhantes, isso terá impacto no uso de sua RAM, é claro.

    
por Peter V 13.03.2012 / 18:50
fonte
0

Dependendo de qual consulta você faz, LIKE consultas correspondentes no início da coluna podem usar índices (no Postgres eu sei com certeza que eles fazem isso; no MySQL eu não tenho certeza).

Então,

Widget.where('name LIKE ?', "#{search_term}%").all

usará um índice de banco de dados (pelo menos no Postgres), enquanto

Widget.where('name LIKE ?', "%#{search_term}%").all

não irá. Observe o % no início do termo de pesquisa. Sua milhagem também pode variar com as condições ILIKE (não diferenciar maiúsculas de minúsculas), vs LIKE (sensível a maiúsculas e minúsculas). Leia os documentos do banco de dados. Esse pode ser o fruto mais fraco.

Um mecanismo de busca, como proposto por outra resposta, é outra opção. Se você está implementado no Heroku, existem alguns complementos de pesquisa em nuvem que são fáceis de integrar, mas provavelmente ainda é uma tarefa de magnitude maior do que ajustar um pouco suas consultas.

    
por Wolfram Arnold 11.03.2012 / 06:15
fonte
0

Você poderia criar uma tabela para a maioria pesquisada e, em seguida, priorizar a pesquisa dessa maneira, talvez, espero que isso ajude.

    
por Jay Mee 14.03.2012 / 14:34
fonte