Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Paulo de Tarso F. M.

Recursos de autocompletar

Recommended Posts

Pessoal, gostaria de iniciar uma discussão com vocês com o intuito de mapear novas idéias/soluções para um problema que acredito que muitos devem passar: recursos de autocompletar utilizando-se Ajax.

 

É o seguinte, é sabido que existem diversos plugins que facilitam nossa vida no que diz respeito à implementação desse tipo de recurso no client-side, principalmente com a utilização de frameworks JavaScript, como jQuery, por exemplo. Mas meu objetivo não é falar sobre eles, lógico, afinal, não teria postado aqui no fórum de PHP... http://forum.imasters.com.br/public/style_emoticons/default/assobiando.gif

 

Como eu faria (e faço) esse tipo de recurso: na terceira letra que o usuário informa o que ele quer, faço uma consulta via Ajax no banco para recuperar as palavras que casam com os critérios. Essa consulta até pode ser rápida em algumas situações, como por exemplo, um banco de dados novo, sem muitos registros. Mas o que acontece se esse banco crescer demais? Tipo, começar a ter mais de 200.000 registro? Ou ainda 2.000.000? :mellow:

 

Se analisarmos a situação descrita acima, minha pergunta de repente nem seria relacionado tanto ao PHP, mas sim à inteligência em como modelar o banco de dados... Mas, além disso, é o que eu queria saber de vocês: existe algo que possa ser feito que não exigisse tanto do banco? Ou de que forma podemos otmizar essas consultas em tabelas com milhões de registros?

 

Pensei em alguma coisa do tipo quando um usuário informar seus parâmetros iniciais, no caso, as três primeiras letras (de um serviço, de um local, enfim, qualquer coisa), o sistema não teria que fazer uma consulta SQL a cada letra digitada, mas de alguma forma armazenar as informações em sessions, cookies, sei lá... Estou viajando muito? :mellow:

 

Pergunto isso me baseando no Google: como a busca deles pode ser absurdamente otimizada levando-se em consideração a quantidade de dados armazenados em seus milhares de bancos de dados espalhados pelo mundo? Existe algo em termos de linguagem de programação (no caso, eu gostaria que fosse o PHP...) que possa ser feito para otimizar as consultas ou isso envolve apenas a otimização do banco de dados e também a questão de infra-estrutura?

 

Enfim, é isso. O que vocês podem me dizer sobre isso? O que eu poderia fazer para otimizar buscas de autocompletar em que o resultado é instantâneo assim como acontece com o Google?

 

 

Valeu!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Cara, se o desenvolvimento do código utilizar todo tipo de otimização (estou me referindo à consulta SQL), não creio que o número de registros interfira significativamente na velocidade de execução da consulta.

 

Para começarmos os testes, poderíamos inserir 500 mil registros em um bd e utilizar uma consulta com uma cláusula WHERE LIKE e ver o tempo de execução. Acredito que se passar de 2 segundos tenha algo errado.

 

Gostei da proposta, porém não acredito que tenha algum tipo de empecílho neste sentido. Lembrando que a otimização de um banco de dados não perfaz somente a consulta em si; vai desde a escolha correta dos tipos dos campos da tabela, até as funções utilizadas.

 

Espero ter contribuido, e se possível faça o teste que citei para testarmos.

 

Até mais.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá meu caro H4X0R, obrigado pela resposta. Gostei da sugestão do teste com 500.000 registros, montarei um banco para testar.

 

E de fato, 2 segundos é um absurdo! Inimaginável! rsrsrs... Mas a preocupação maior é: uma única consulta, tudo bem, a lentidão não existirá... Mas e se pensarmos em uma consulta efetuada por 100 pessoas simultaneamente? :mellow: É nessas questões mais caóticas que quero focar, quero pensar em algo que possa atender a essa situação, e abaixo disso estará coberto, obviamente...

 

No caso do banco de dados, você recomendaria alguma forma de estruturá-lo? Vamos pegar um exemplo, como esses Guias de serviços como o Guia Mais, o iLocal, etc. As consultas seriam feitas em cima dos nomes dos serviços, e temos 500.000 serviços cadastrados no Brasil inteiro. Como faria para montar esse recurso de autocompletar separando o número de serviços por Estado/cidade? :mellow: Separar em tabelas diferentes? Uma única tabela?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sugestão: Limitar a quantidade de campos retornados com a cláusula LIMIT

 

Por quê?

Porque o banco de dados vai retornar os valores assim que encontrar o X registros requisitados

 

Que tal criar um contador pra toda vez que a palavra é selecionada?

Aí você mostra as mais populares, como o próprio Google faz.

 

Se o usuário insistir em procurar, disponibilize um link, como uma paginação ou um 'mostrar mais' como no Twitter, Orkut, etc...

 

Quanto ao serviço de guias, o que eu recomendo é manter tudo em uma tabela só, relacionando cidades e estados por Foreign Keys pra evitar dor de cabeça...

 

Bom, minhas idéias acabam por aqui...

 

Boa sorte aí http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sobre o LIMIT, obviamente deveria ser implementado; INCLUSIVE por motivos de estética.

 

Sobre o contador de cliques, acho que o raciocínio é esse, mas não bem por aí. O sistema do google, se utilizasse isso, iriam aparecer sempre as mesmas sugestões para determinadas pesquisas, uma vez que, vamos supor que um LIMIT de 10 esteja sendo aplicado, sempre os 10 mais clicados irão aparecer. O google (ou qualquer outra aplicação bem estruturada) utiliza algoritmos sobre algoritmos para exibir as sugestões e os resultados que perfazem a consulta realizada pelo usuário.

 

Mas não se preocupe Paulo, quanto ao número de visitantes. Utilizando LIMIT, e uma infra decente, não haverão problemas quanto à isso; porém, se você inserir um site com um número razoavelmente alto de hits/visualizações únicas diárias em um host compartilhado ou de de baixa performance, certamente, independentemente de você utilizar este sistema de auto-sugestões ou não, haverá instabilidades.

 

Até mais.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá pessoal, obrigado pelas contribuições.

 

Be, de fato, se um site se torna razoavelmente "popular" e o número de requisições aumenta cada vez mais com o passar do tempo, não adianta apenas focarmos na questão lógica: de nada adiantaria termos uma aplicação linda e maravilhosa se a parte de infra estrutura não ajudar... Logicamente que o investimento em infra é algo que deve ser muito bem planejado, pois a escolha de um servidor robusto, que consiga processar as requisições simultâneas sem que a aplicação "caia", tem seu preço, e não precisa ser feito no começo, obviamente, mas é importante saber que a possibilidade existe e então passaria a ser uma necessidade.

 

Quanto ao LIMIT, sim, como o H4X0R disse, obviamente ele deve ser implementado, e ele sempre é implementado em casos como este. Mas eu não penso em algo que seja relacionado à popularidade dos termos pesquisados. Procuro algo que seja genérico, sem esse tipo de classificação. Um limitador inicial talvez seja exibir as sugestões apenas na terceira letra informada, ou dependendo da necessidade, até com duas. Mas eu ainda penso em algo que não seja feito com Ajax...

 

Sei lá, o que acham de se criar algo que utilize cookies, session, ou alguma coisa que pudesse armazenar alguns dados pré-selecionados, e então os filtros da aplicação trabalhariam nesses dados já pré-carregados... Talvez no momento em que o usuário acessasse a aplicação esses termos principais, considerados como elementos-chave das consultas, já estariam carregados e então esse autocompletar atuaria com base nesses dados e não mais dependendo das consultas via Ajax... Dependendo da necessidade, esses termos principais seriam sempre atualizados de hora em hora...

 

Fui muito longe? :mellow: O que acham?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sei lá, o que acham de se criar algo que utilize cookies, session, ou alguma coisa que pudesse armazenar alguns dados pré-selecionados, e então os filtros da aplicação trabalhariam nesses dados já pré-carregados... Talvez no momento em que o usuário acessasse a aplicação esses termos principais, considerados como elementos-chave das consultas, já estariam carregados e então esse autocompletar atuaria com base nesses dados e não mais dependendo das consultas via Ajax... Dependendo da necessidade, esses termos principais seriam sempre atualizados de hora em hora...

Não ententendi muito bem, mas até onde entendi, poderia-se fazer da seguinte forma:

 

Cria-se uma lista de N palavras-chave mais pesquisadas e insere-as em uma sessão ou outro tipo de variável com seus respectivos arrays de possíveis resultados. Então, quando o usuário começar a digitar o sistema verifica se a palavra-chave já existe neste 'atalho', e se sim, exibe as sugestões, do contrário, faz a consulta no MySQL. Isso pode ser adaptado com PHP e jQuery, objetivando o acesso instantâneo às palavras-chave mais pesquisadas.

 

Mas, sinceramente, todo esse sistema é inútil se você possui um site com menos de 50 mil visitas diárias, na minha opinião. A simples query, bem estruturada, já é mais que suficiente para boa parte das aplicações disponíveis na internet.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pensei em alguma coisa do tipo quando um usuário informar seus parâmetros iniciais, no caso, as três primeiras letras (de um serviço, de um local, enfim, qualquer coisa), o sistema não teria que fazer uma consulta SQL a cada letra digitada, mas de alguma forma armazenar as informações em sessions, cookies, sei lá... Estou viajando muito?

 

acho que no lugar de session e/ou cookie, seria melhor um temp tipo cache

eu tenho, pelo meu painel interno administrativo, algumas funções que rodam diariamente

 

você poderia fazer uma checagem dos termos mais consultados e jogar num temp, por exemplo

você roda o sistema e cria um temp -> itens_a_cache.txt que recebe um array com os itens mais 'populares', assim quando o fulano digitar no input a+v+o+r+e, a consulta será no arquivo itens_a_cache.txt, se não retornar nada, ai você pode fazer uma busca mais detalhada no banco

 

se o fulando buscar b+o+l+a, a consulta vai ser no arq. itens_b_cache.txt

e por ai vai

 

 

estou trabalhando massivamente com itens de cache justamente pela performance/consumo

tenho cache diario, semanal, mensal... todos atualizados pelo sistema administrativo, e a performance foi bem significante, pois tenho paginas que fazem varias consultas

Compartilhar este post


Link para o post
Compartilhar em outros sites

Então H4X0R, eu sei que a query bem estruturada é suficiente para atender à necessidade quando o número de visitas for inferior a 50.000 diariamente... Mas é como eu falei, quero pensar em uma situação caótica, como se esse número de acesso fosse maior do que isso, por exemplo. Não que eu vá criar um sistema assim, não é isso, meu objetivo aqui é apenas discutir o que poderia ser feito em uma situação como essa... Se (sempre temos um "se") amanhã ou depois esse número de acessos realmente aumentar, uma melhoria será necessária, mas ela deverá ser implementada o mais rápido possível, pois o site estará no ar e não poderia demorar muito tempo para que essas adaptações fossem desenvolvidas.

 

 

Mas criatividade zero, qual é o ganho em fazer dessa forma? :mellow: Como posso medir e comparar o desempenho? Ah! Aqui já entramos em um outro ponto: como posso medir desempenho de requisições em bancos de dados, consultas via Ajax, utilização de arquivos (TXT ou qualquer outro tipo)? Gostaria de criar uma mini aplicação para testar vários tipos de consultas utilizando uma base com 500.000 registros, como sugerido pelo nosso amigo H4X0R. Alguém tem alguma idéia/sugestão? Eu nunca fiz algo do tipo... http://forum.imasters.com.br/public/style_emoticons/default/closedeyes.gif

 

 

Enfim, resumidamente temos a seguinte situação: inicia-se o projeto da maneira convencional, utilizando-se consultas simples no banco. Com o aumento do número de registros e do número de consultas, será necessário melhorar isso, aí partiria para um sistema com recursos de cache, arquivos TXT, etc. Mas é nessa segunda etapa que quero focar, pois é uma situação que eu nunca me deparei, mas gostaria de estar mais preparado para enfrentá-la, e é esse o objetivo do tópico...

 

Então como próximas "tarefas": gostaria de criar uma rotina que medisse consultas em banco versus utilização de arquivos externos e também criar algo semelhante ao que nosso amigo criatividade zero utiliza, que são arquivos para armazenar os termos mais consultados. E conforme eu puder criar estes recursos, vou compartilhando com vocês o que foi feito e os resultados obtidos...

 

 

http://forum.imasters.com.br/public/style_emoticons/default/joia.gif

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bancos de dados relacionais como MySQL e PgSQL têm seu próprio sistema de cache otimizado e indexado - na maioria das vezes, binário - muito mais ágil e econômico que um arquivo txt.

 

Com MySQL, existe a possibilidade de se particionar o banco, ao invés de 2Mi de registros, você teria 5 bancos com 400K, através dos índices, sabemos exatamente em qual banco procurar, o que agiliza o acesso e torna o atraso praticamente imperceptível em consultas simultâneas caso eu esteja procurando por 'Águias', você por 'Lontras', o H4x0r por 'Tatus' e o Criatividade Zero por 'Zebras'. Isso sem mencionar o fato de esse particionamento também poder ser feito fisicamente.

 

Também falando de termos de infra, física, é possível criar redundância de bancos, podendo permitir inúmeras consultas simultâneas na mesma partição do banco.

 

Passando um pouco para a parte de requisição front-end, você pode, por exemplo, ler o cabeçalho REFEREER do cliente, procurando algum termo chave que o tenha trazido até sua página e já deixar algumas consultas pré-carregadas.

 

O sistema de tags também ajuda muito. Se meu visitante procura por calçados, eu já posso deixar algumas consultas pré-carregadas como 'sapatos','tênis','sapatilhas'. Esta forma é efetivamente útil quando é possível se aplicar filtros.

 

Em MySQL também é possível definir múltiplos índices, dando a eles um tamanho máximo de caracteres. Você pode então, definir o seu índice primário, na forma como quer fazer, pelas 3 primeiras letras da categoria, depois disso você faz o índice efetivo da categoria, então as tags e etc. Seria como nós buscamos palavras em um dicionário, pelos fragmentos iniciais.

 

Encontrei um tópico antigo com muitas informações relevantes sobre a performance de bancos de dados 'parrudos'

http://forum.imasters.com.br/index.php?/topic/391625-gerenciamento-de-memoria/

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sobre como medir tempo de processamento no PHP, basta utilizar um código que meça, como abaixo:

 

$time_start = microtime(true);
//faz o que tem que fazer...
$time_end = microtime(true);
$benchmark = ($time_end - $time_start);
echo 'Tempo de execução: ' . ($benchmark) . ' ms';

Dá pra implementar ainda mais, mostrando percentual de velocidade, etc. Mas a base é essa, e dá para ser usada em qualquer parte do seu código.

 

Aproveitando, recomendo a leitura dessas dicas:

http://www.php.lt/benchmark/phpbench.php

 

Até mais.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Mas criatividade zero, qual é o ganho em fazer dessa forma? :mellow: Como posso medir e comparar o desempenho? Ah! Aqui já entramos em um outro ponto: como posso medir desempenho de requisições em bancos de dados, consultas via Ajax, utilização de arquivos (TXT ou qualquer outro tipo)? Gostaria de criar uma mini aplicação para testar vários tipos de consultas utilizando uma base com 500.000 registros, como sugerido pelo nosso amigo H4X0R. Alguém tem alguma idéia/sugestão? Eu nunca fiz algo do tipo... http://forum.imasters.com.br/public/style_emoticons/default/closedeyes.gif

 

qual o ganho???

é o que falei - desempenho puro e simples

você vai consultar arquivos 'pequenos' e não uma database com milhoes de registros

 

imagina rodar o mesmo script 500.000 vezes por hora em cima de uma logica um tanto complexa para retornar as palavras de peso

com um txt montado você so precisa abri-lo

 

 

você entra numa biblioteca e procur por todas as estantes

ou pode consultar um unico livro pra saber se na biblioteca tem o que você quer

Compartilhar este post


Link para o post
Compartilhar em outros sites

Obrigado a todos pelas respostas! Evandro, o link que me passou é ótimo! Há muitas dicas e informações que desconhecia...

 

Bom, já tenho uma noção do que fazer e o que não fazer em questão de otimizações, agora é testar...

 

Valeu pessoal!

 

 

http://forum.imasters.com.br/public/style_emoticons/default/joia.gif

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.