Jump to content

Melhorar velocidade de SELECT e INSERT


andrepcg
 Share

Recommended Posts

tenho este código php que criei. como não sou bom em optimizações, tenho a certeza que deve haver uma maneira muito melhor de fazer isto. por isso peço a vossa ajuda.

um utilizador pega numa lista de, imaginemos, 1000 palavras, separadas por uma linha, e submete no formulário. o que o script faz é pegar em cada linha (foreach), fazer select e verificar se está na base de dados, e se não estiver, insere na BD. portanto, com 1000 palavras tem de repetir esta acção 1000 vezes o que demora imenso e consome recursos.

foreach ($lines as $line) {
              
              if(preg_match('/^[a-f0-9]{32}.)/', $line) == 1){
           

              $parts = explode(':', $line, 2);
              $md5hash = strtolower(trim($parts[0]));
              $decrypted_pass = addslashes($parts[1]);
              
              $encoded = base64_encode($decrypted_pass);
  
              $sql = mysql_query("SELECT md5_hash, decrypted FROM hashes WHERE md5_hash='$md5hash' AND decrypted='$encoded'") or die(mysql_error());
              $sql2 = mysql_num_rows($sql);
              
              $md5_check = md5($decrypted_pass);
              
               if(($sql2 == 0) && ($md5_check == $md5hash)){
                     $total  ;
                     
                     $query_log = mysql_query("INSERT INTO hashes (md5_hash, decrypted) VALUES('$md5hash','$encoded')") or die(mysql_error());
                     
               }
               
              }
           }

qual é a melhor maneira de melhorar o codigo de modo que seja muito mais rapido e eficaz?

Manda piadas secas por telefone - Piadas.secas.club

Link to comment
Share on other sites

Há duas maneiras para ficar mais rápido:

1. usar transacções;

2. usar inserções "em massa" - bastante melhor. Verifica se este post te ajuda (tens de andar alguns para cima e para baixo para perceber de que é que se estava a falar).

"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Link to comment
Share on other sites

ok obrigado. já agora, o que sao transacçoes?

fiz este rascunho de codigo prque preciso de alguma ajuda a formatar o meu codigo para funcionar como dizes. sei que neste codigo muita coisa esta mal mas preciso de luzes a trabalhar desta nova maneira.

// divide cada linha e remove duplicados
$lines = array_unique(explode("\n", $hashes));
             
		 //verifica se cada linha confirma o preg_match
         if(preg_match('/^[a-f0-9]{32}.)/', $line) == 1){
           
			$sql_novos = "INSERT IGNORE INTO hashes ";

			$sql = $sql_novos . "(md5_hash, decrypted) VALUES ";
  
		  $parts = explode(':', $line, 2);
		  $md5hash = strtolower(trim($parts[0]));
		  $decrypted_pass = addslashes($parts[1]);

		  $encoded = base64_encode($decrypted_pass);
  
		  $md5_check = md5($decrypted_pass);

		   if($md5_check == $md5hash){

				 while(($linha = $lines) !== false)
   				 $sql .= "(" . $md5hash . ", '" . $encoded . "'), ";

			 $sql = rtrim($sql, ", ");

			$resSQL = mysql_query($sql);
			// se $resSQL == true, foram enfiados com sucesso, se não... tem gato...

		   }
               
         }

aquilo estava feito para trabalhar com o foreach e foi dificil para mim adaptar ao novo formato por isso nao alterei assim muita coisa. espero que me possam ajudar

Manda piadas secas por telefone - Piadas.secas.club

Link to comment
Share on other sites

A questão não está no foreach vs. while, podes usar o que te der mais jeito; o truque está na construção da query, que é em massa.

À partida, é isso, está correcto - excepto as linhas no while, isso era para o problema do OP do outro tópico...

"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Link to comment
Share on other sites

ah ok mas então repara:

$lines = array_unique(explode("\n", $hashes));

foreach ($lines as $line) {
             
         if(preg_match('/^[a-f0-9]{32}.)/', $line) == 1){
           

              $parts = explode(':', $line, 2);
              $md5hash = strtolower(trim($parts[0]));
              $decrypted_pass = addslashes($parts[1]);
             
              $encoded = base64_encode($decrypted_pass);

             
              $md5_check = md5($decrypted_pass);
             
               if($md5_check == $md5hash){
                     
                     $query_log = mysql_query("INSERT INTO hashes (md5_hash, decrypted) VALUES('$md5hash','$encoded')") or die(mysql_error());
				 $sql_novos = "INSERT IGNORE INTO tabela ";


				$sql = $sql_novos . "(md5_hash, decrypted) VALUES ";

				$sql .= "(" . $md5hash . ", '" . $encoded . "'), ";

				// isto serve para tirar a última vírgula e espaço da string sql
				$sql = rtrim($sql, ", ");

				$resSQL = mysql_query($sql);
                     
               }
               
         }
}

entao se o problema nao e no foreach, pelo que estou a entender então para cada linha, está a correr novamente cada query individualmente e nao em massa.

peço desculpa mas isto as vezes e complicado quando se está habituado a uma coisa. se me conseguires demonstrar nos parametros do meu script, era mais facil claro.

obrigado pela ajuda

Manda piadas secas por telefone - Piadas.secas.club

Link to comment
Share on other sites

Porque não tomaste atenção ao que era realmente importante no outro post...  :smoke:

Repara, já tens as linhas; depois, por cada linha, fazes umas coisitas e queres inserir - mas não precisas de inserir logo, podes inserir só no fim de teres feito tudo o que é suposto, desde que vás adicionando as coisas à query...

Tipo isto:

// inicializar a query string
$sql = "INSERT IGNORE INTO tabela (md5_hash, decrypted) VALUES ";

$lines = array_unique(explode("\n", $hashes));

foreach ($lines as $line)
{
    if(preg_match('/^[a-f0-9]{32}.)/', $line) == 1)
    {
        $parts = explode(':', $line, 2);
        $md5hash = strtolower(trim($parts[0]));
        $decrypted_pass = addslashes($parts[1]);

        $encoded = base64_encode($decrypted_pass);
        $md5_check = md5($decrypted_pass);

        // acrescentar os dados à query
        if($md5_check == $md5hash)
            $sql .= "(" . $md5hash . ", '" . $encoded . "'), ";
    }
}

// limpar a query
$sql = rtrim($sql, ", ");
// executar a query - repara bem: fora do ciclo!
$resSQL = mysql_query($sql);

// convem verificar, com uma flag, por exemplo, se efectivamente existe alguma coisa para inserir

Geez , limpem e tabulem o código correctamente, fica mais fácil de ler e ajudar...

Noutra nota: transacção é uma forma de manipular a BD sem, na realidade, fazer alguma coisa definitivamente, até ser explicitamente chamada a execução de tudo o que foi feito dentro da transacção.

"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Link to comment
Share on other sites

obrigado 😄 agora está a funcionar fixe, mais ou menos.

ja tenho os dados na BD, mas se fizer insert ignore, ele insere outra vez os dados, apesar de eles ja la estarem, precisamente iguais

outra coisa relacionada. qual e a melhor maneira de saber quantos dados foram precisamente inseridos na BD?

Manda piadas secas por telefone - Piadas.secas.club

Link to comment
Share on other sites

Qual é a chave primária da tabela? Ou campos únicos?

Se não se aplicar a nenhum dos dois que estás a inserir, então, sim, vai inserir duplicados; mas isso já não é um problema da PHP, mas sim de arquitectura de BD.

"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Link to comment
Share on other sites

como primario tenho apenas o ID da row que leva com um auto increment em cima. entao tenho de colocar a md5_hash como PRIMARY e ja deve funcionar, certo? vou experimentar agora

Não, metes como UNIQUE. A chave primária é a chave primária, deixa estar que está bem...

"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Link to comment
Share on other sites

ok, ja está a funcionar bem. outra coisa. no antigo codigo ele somava sempre mais um sempre que ele executava o codigo de inserir na BD. mas ele agora faz aquela cena do IGNORE. como é que posso contar agora quantas das linhas é que foram totalmente inseridas na BD, sem contar obviamente com os duplicados?

Manda piadas secas por telefone - Piadas.secas.club

Link to comment
Share on other sites

A forma mais rápida é fazeres inserção em massa pela base de dados com INSERT from SELECT (http://dev.mysql.com/doc/refman/5.1/en/insert-select.html).

Fazes INSERT INTO tabela SELECT (selecção da informação que queres inserir, obviamente incluído filtros e cláusulas de selecção).

10 REM Generation 48K!
20 INPUT "URL:", A$
30 IF A$(1 TO 4) = "HTTP" THEN PRINT "400 Bad Request": GOTO 50
40 PRINT "404 Not Found"
50 PRINT "./M6 @ Portugal a Programar."

 

Link to comment
Share on other sites

A forma mais rápida é fazeres inserção em massa pela base de dados com INSERT from SELECT (http://dev.mysql.com/doc/refman/5.1/en/insert-select.html).

Fazes INSERT INTO tabela SELECT (selecção da informação que queres inserir, obviamente incluído filtros e cláusulas de selecção).

Hmmm, como é que isso o ajuda a inserir linhas de um array é que me ultrapassa...

É que nem olhaste para o código...  :smoke:

"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Link to comment
Share on other sites

Isso é mais fácil, basta ir acrescentando à clausula WHERE do DELETE os campos que queres apagar, com OR's.

"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Link to comment
Share on other sites

Hmmm, como é que isso o ajuda a inserir linhas de um array é que me ultrapassa...

É que nem olhaste para o código...  :smoke:

A solução que dei é a solução genérica para fazer inserção em massa numa base de dados, que aliás era o problema original.

10 REM Generation 48K!
20 INPUT "URL:", A$
30 IF A$(1 TO 4) = "HTTP" THEN PRINT "400 Bad Request": GOTO 50
40 PRINT "404 Not Found"
50 PRINT "./M6 @ Portugal a Programar."

 

Link to comment
Share on other sites

A solução que dei é a solução genérica para fazer inserção em massa numa base de dados, que aliás era o problema original.

Ai era? Safa, ou tenho de trocar de óculos, ou a cafeína em excesso atingiu, por fim, a minha capacidade de raciocínio...

um utilizador pega numa lista de, imaginemos, 1000 palavras, separadas por uma linha, e submete no formulário.

Podia jurar que aqui está escrito que existe uma lista externa à base de dados que é para inserir; mas isto sou eu...

"Para desenhar um website, não tenho que saber distinguir server-side de client-side" - um membro do fórum que se auto-intitula webdesigner. Temo pelo futuro da web.

Link to comment
Share on other sites

Após rever os posts, creio que a confusão vem do meu primeiro post onde parece que não me expliquei bem.

Não estava a responder directamente à questão colocada no tópico mas sim apenas a referir a melhor forma de efectuar inserções em massa é sempre através da db, usando por exemplo insert from select.

Neste caso em particular começa-se por se fazer um insert por cada select que, por sua vez é obtido a partir de uma linha de um array. A utilização desta estratégia pode não ser possível, no entanto não quis deixar de mostrar uma forma de inserção em massa que é comummente usada em situações idênticas.

10 REM Generation 48K!
20 INPUT "URL:", A$
30 IF A$(1 TO 4) = "HTTP" THEN PRINT "400 Bad Request": GOTO 50
40 PRINT "404 Not Found"
50 PRINT "./M6 @ Portugal a Programar."

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.