Ir para conteúdo
eiwes

Fazer SELECT, UPDATE e INSERT (em um mesmo método), de forma que não sobrecarregue o servidor

Recommended Posts

Olá, pessoal

 

Estou desenvolvendo uma aplicação, e dentro disso, surgiu um problema.... Preciso fazer SELECT dos dados, após dar um UPDATE nesses mesmos dados recebidos e por fim realizar um INSERT.

Seria muito fácil fazer isso, afinal, bastava fazer um encapsulamento dos dados e pronto. No entanto, queria saber se existe uma forma para não sobrecarregar o servidor com esse COMBO de "Request/Response".

 

Tentei por PROCEDURE, mas necessito verificar os dados recebidos com o que já estão cadastrados na tabela, para então realizar o UPDATE..

 

Alguém poderia me ajudar com isso?

Para resumir tudo...

Preciso, apenas, de uma maneira para fazer SELECT, UPDATE e INSERT (com verificação dos dados, por isso o SELECT) de uma forma que não sobrecarregue o servidor. Por quê? Porque seria uma rotina de uns 1.000 usuários realizando isso, quase que simultaneamente, no servidor. Com isso mau feito, acredito que iria FERRAR meu bolso com um servidor MONSTRO :(

 

PROCEDURE que tentei, mas não consegui...

DELIMITER $$
CREATE PROCEDURE `confere_qts` (id INT, opcao INT, chute INT, cron INT, id_usus INT)
BEGIN
	SELECT `correta_qts`, `resolucao_qts`, `qtd_res_qts`, `qtd_chutes_qts`, `qtd_acertos`, `a_qtd_qts`,
                                     `b_qtd_qts`, `c_qtd_qts`, `d_qtd_qts`, `e_qtd_qts`, `tempo_qts`
    FROM qts_cad
    WHERE id_qts = id;
    
    UPDATE qts_cad SET qtd_res_qts = +1, tempo_qts = cron WHERE id_qts = id;
    
    INSERT INTO respostas_qts_resp(`idUsus_resp`, `idQts_resp`, `alternativa_resp`, `correta_resp`, `tempo_resp`, `date_resp`, 												`chute_resp`, `revisar_resp`)
            VALUES(id_usus, id, opcao, correta_qts, cron, NOW(), chute, 0);
    
    IF chute = 1
        BEGIN
			UPDATE qts_cad SET qtd_chutes_qts = +1 WHERE id_qts = id;
        END
      
    IF opcao = correta_qts
    	BEGIN
        	UPDATE qts_cad SET qtd_acertos_qts = +1 WHERE id_qts = id;
        END
     
     IF opcao = 1
    	BEGIN
        	UPDATE qts_cad SET a_qtd_qts = +1 WHERE id_qts = id;
        END
     
     IF opcao = 2
    	BEGIN
        	UPDATE qts_cad SET b_qtd_qts = +1 WHERE id_qts = id;
        END
        
     IF opcao = 3
    	BEGIN
        	UPDATE qts_cad SET c_qtd_qts = +1 WHERE id_qts = id;
        END
       
     IF opcao = 4
    	BEGIN
        	UPDATE qts_cad SET d_qtd_qts = +1 WHERE id_qts = id;
        END
        
     IF opcao = 5
    	BEGIN
        	UPDATE qts_cad SET e_qtd_qts = +1 WHERE id_qts = id;
        END
        
END $$

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Oi,

 

Geralmente quando a aparente solução é um problema desse tipo, a origem real do problema é a modelagem.
Pelo o que vi, os cases existem para indicar a coluna correta do update, só isso já evidencia que as tabelas poderiam ser modeladas de outra forma melhor, o que evitaria toda essa confusão.

 

Se as colunas a_qtd_qts, b_qtd_qts, c_qtd_qts fossem linhas, ai você teria um simples update, com WHERE da questão escolhida, em vez de case.

E no lugar do select, seria possível também um update, onde mais uma vez um outro WHERE talvez com subquery resolveria.

 

Basicamente com outra modelagem trocaria essas linhas por 2 updates e um insert, sem necessidade de select.

E o select no pior dos casos é que ocasionaria um lock, já que outro usuário vai estar concorrendo para fazer o update dele.

 

 

Algumas colunas como `qtd_acertos_qts` vão contra as boas práticas de modelagem (vide Formas Normais).

Enfim, creio que para melhorar mesmo, só remodelando esse banco.

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Concordo com o @William Bruno !

Sendo uma estrutura monstro, poderia pensar em remodelar esse banco ! 

A sua estrutura atual parece não ser viável para tal execução, mas temos que pensar não só em 1.000 usuários ativos ao mesmo tempo, mas também em quantas vezes ela seria requisitada em um minuto, se a frequência não for imensa, essa execução não seria considerada tão pesada ao servidor.

Para podermos definir melhor o que acontece ai, precisaríamos ver quais suas index de chave primaria e estrangeira, dessa forma ai fica difícil apontar uma execução SQL que seja correta !

Assumindo que possa usar o phpmyadmin para verificar os dados, poderia usar o desenhador para verificar a ligação entre as foreign key e primary key, postando um print desse desenhador poderíamos chegar a um resultado melhor!

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Oi, Bruno

 

Obrigado pela resposta.

 

Para explicar o raciocínio:

As colunas existem, pois preciso ter a quantidade de respostas em cada uma (qtd), quando coloquei A,B,C,D e E é devido a isso, mas também preciso da qtd de acertos, com isso eu consigo saber quantas pessoas erraram e acertaram aquela questão.

 

Mesmo assim haveria uma modelagem melhor?(sei que existe, só quero uma confirmação mesmo uaheua)

Mediante a sua resposta, irei raciocinar mais para chegar a uma saída.

 

Novamente, agradeço pela resposta.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Então, @William Barreto

 

Na verdade, essa parte seria a mais usada do site. Praticamente vários requests a todo instante, pois é onde verifico se usuário acertou a questão ou não, por isso o SELECT.

 

Nunca usei o "desenhador", poderia me explicar, mesmo que pouco, o que seria isso?

 

Obrigado pelo comentário.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sim, existe.
Para saber quantos acertos, ai você usa um select com join, e não uma coluna cacheada.

 

id_qts é o ID da Questão, certo?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Certo, @William Bruno.

 

O id_qts se refere ao id da questão. Eu pensei em colocar na linha da questão porque eu preciso saber os acertos em cada (pensei que ficaria pesado fazer um INNER JOIN para compilar todos os dados). Entretanto, se você me falar que fazer isso não ficaria, confio completamente.

Compartilhar este post


Link para o post
Compartilhar em outros sites

O certo é usar o join mesmo, meu amigo !

Na verdade o join costuma reduzir a quantidade de dados obtidos do banco. Por mais que sejam múltiplas tabelas, ao aplicar o "ON" para definir as chaves que se ligam, ele costuma reduzir drasticamente os dados obtidos, ai depende do que tiver no seu "SELECT", se for bem feito, o peso será muito menor.

Compartilhar este post


Link para o post
Compartilhar em outros sites

@eiwes, sabe que qualquer dúvida que tiver pode postar, estaremos aqui para ajudar !

E eu acabei esquecendo de tirar uma dúvida sua sobre o desenhador ...

Eu não tenho certeza se ele existe em outros tipos de gerenciador de dados, eu uso somente o phpmyadmin !
Ao selecionar o banco, da forma que esta na seguinte imagem anexada (deixei marcado na imagem onde deverá estar selecionado)

bancos.png.e836c3012c5f62419b66051247352bd1.png


Será liberado uma série de opções, assim como no menu da segunda imagem anexada, poderá ver lá na direita do menu a opção Desenhador (o meu existe a opção mais por não ter como mostrar todo conteúdo do menu na tela, mas o seu desenhador pode estar posicionado diferente do meu).bancos2.thumb.png.1ea769cc7c70d97752fea2deb269b229.png

 

Ao clicar no desenhador, teremos o conteúdo apresentado na terceira imagem, essa é minha relação completa referente as tabelas desse banco que usei como exemplo.

relacao.thumb.png.cadf3e2f837ea0b45af323fb4462c2cc.png

 

Ele mostra todas as foreing keys e primary keys que são interligadas, nesse caso para dar um delete em um, eu apenas do um delete na chave principal, e todos os dados relacionados serão deletados também (claro, ela acontece isso por que eu determinei que assim seria, esse modo de execução é chamada de CASCADE, existe outros modos, mas ai você poderá estudar por conta própria).

Existe também um menu a esquerda dessas tabelas, o que irá usar para poder fazer as relações da chave se chama Create relationship, recomendo que estude ele para poder fazer as ligações corretas.

O desenhador seria basicamente a interface amigável do banco de dados, eu costumo usar ele somente para as relações, acho muito útil !

 

Bons estudos, amigo !

Qualquer dúvida sabe que é só falar !

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora

  • Conteúdo Similar

    • Por João Teixeira
      Olá pessoal, boa noite!

      Desculpem se estou direcionando minha dúvida para tópico errado, pois sou novo no mundo da programação e no forum tbm, porem acho que vou precisar do php para resolver o problema, por isso postei aqui!

      Bom vamos lá!

      tenho o seguinte documento com uma estrutura html e um script para selecionar múltiplos campos provenientes de uma <li>

      esse script renderiza os resultados selecionados em uma div!

      a partir daí que começa o enrosco, eu gostaria de inserir esses dados selecionados no meu banco de dados todos de uma vez, porem uma linha para cada item selecionado!

      logo a baixo deixo o código em questão para você darem uma olhada, caso seja possível alguém me dar uma força eu fico grato pela ajuda!
       
      desculpem se me referi errado na explicação pois ainda sou inexperiente em mesclar javascript e php!
      obrigado pela atenção!
       
      Vide Código:

       
      ***

      <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script src="//code.jquery.com/jquery-1.10.2.js"></script> <script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script> <script type="text/javascript">
      $(document).ready(function () { $('#selectable').selectable({ stop: function () {
      var result = '';
      $('.ui-selected').each(function (){ result += $(this).text() + ', '; });
      //coloca o resultado na div $('#result').html(result); } }); }); </script> <style> li{ display:inline-block; padding:7px; border:1px solid black; cursor:pointer; margin-bottom:3px; } .ui-selected{ background-color:green; color:white } .ui-selecting{ background-color:grey; color:white } </style> </head> <body style="font-family: Arial"> <form id="form1" runat="server">
      <ul id="selectable"> <li>01</li> <li>02</li> <li>03</li> <li>04</li> <li>05</li> <li>06</li> <li>07</li><br> <li>08</li> <li>09</li> <li>10</li> <li>11</li> <li>12</li> <li>13</li> <li>14</li><br> <li>15</li> <li>16</li> <li>17</li> <li>18</li> <li>19</li> <li>20</li> <li>21</li><br> <li>22</li> <li>23</li> <li>24</li> <li>25</li> <li>26</li> <li>27</li> <li>28</li><br> <li>29</li> <li>30</li> </ul> Consultar Data: <div id="result"></div> </form> </body> </html>




×

Informação importante

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