English readers and other languages: Many posts are in portuguese, you can use the Translate button at left side.

Clique nas imagens dos artigos! Elas levam você para o site do artista que a criou e muitas
vezes tem assuntos relacionados ou outras imagens para expandir seus horizontes!

sexta-feira, 4 de setembro de 2009

No SEO site ou no meu?

O Gustavo Loureiro (SEO) escreveu uma matéria onde comenta sobre uma grande empresa que desejava melhorar a visibilidade de seu site, mas descobriu-se que não queriam modificar a maior parte das coisas do seu site porque "não seria possível nem adequado..."
Liberté, Egalité, Fraternité
http://imasters.uol.com.br/artigo/14095/seo/liberte_egalite_fraternite/

Minha resposta é dizer: "SEO Incompentente!" (risos)
A culpa obviamente é dos SEOs, pois obviamente seu trabalho deve ser mexer nos buscadores, ora bolas! Gente mimada não deve ser contrariada, afinal, eles obviamente tem razão.
Obviamente todo mundo sabe que o Google e outros, tem APIs, interfaces e comandos de controle.
Então obviamente deve ser fácil fazer um "programinha" que telepaticamente mude a maneira como funcionam os servidores deles para colocar todos sites desejados nas melhores posições.
Obviamente deve ser óbvio que esta mania de que SEOs e todo esse pessoal de TI tem de querer mudar as coisas, é obviamente desnecessária e obviamente inadequada.
Só porque eles querem mudar e ter uma imagem diferente, isto de forma alguma significa que eles tenham que mudar algo!
É óbvio!
Ao invés disto, deve ter uma maneira de reprogramar o mundo para que o mundo mude. E de preferência, bem baratinho ou free.
Que atire a primeira pedra quem nunca pegou um cliente assim.

Ainda sobre a DM9 e o WWF

O problema pela infeliz divulgação de uma peça de mau gosto, segue, e o Sérgio Valente, presidente da DM9 declarou que a mesma foi feita por pessoal "junior":

Fonte: http://portalexame.abril.com.br/blogs/4p/listar1.shtml

Com certeza muitos vão achar que isto é tirar o corpo fora. Acho que não. Todo dia vejo responsabilidades serem transferidas para novatos, sujeito portanto, a que algo assim ocorra.


Meu comentário lá na matéria: 

 
Acho bem plausível sim, que o Sérgio Valente, presidente da DM9, esteja sendo claro sobre um problema que é crescente em diversas áreas: a transferência excessiva de deveres, responsabilidades e também de oportunidades, para o que se generalizou chamar de "jovens talentos".

Sou da área de TI, temos o mesmo problema. E observo isto nas mais diversas atividades.

A toda hora surge mais uma matéria numa destas revistas de carreira, até nos tele-jornais da TV, reclamando que existem "milhares de vagas" porque faltam "jovens talentos".

O que procuram, são jovens extremamente brilhantes, que tenham a bagagem de conhecimento de um profissional veterano com no mínimo 10 a 15 anos, e claro, sem as preocupações que um adulto tem, como sustentar família, seus estudos, vida pessoal.

Tenho comentado sobre este problema e repito: o estoque de super-gêniozinhos, que fazem o trabalho do Einstein, e de quebra, ainda podem estar sendo sustentados pela família e não vão reclamar do salário baixo, é realmente limitado. Apenas uma pessoa entre centenas é um talento. E só um talento entre centenas, é um grande talento.

A DM9 revelou apenas o que acontece nas mais diversas empresas. É só olhar como são as equipes de muitas empresas e procurar aonde estão os profissionais com mais experiência.

Vocês confiariam a saúde de sua família inteiramente a uma clínica que só tenha estagiários, de muito talento é claro (rsss)???

Talento, capacidade criativa, inovação, engenhosidade, não são coisas só de novatos. Pelo contrário. a nova geração tem se mostrado mais comportada, mais tradicional, mais apegada a valores puramente materiais.

O pouco que sobra para renovação de idéias e atitudes, fica mais por conta de um pouco de hormônios, ou pela sorte em conseguir encontrar algo para copiar na internet. Criatividade mesmo, falta bastante. De nada adianta fazer um curso qualquer, numa faculdadezinha qualquer, e saber a decoreba de muitas siglas e nomes de ferramentas. Pode-se decorar o nome e composição química de todas as tintas, mas nada disto vai fazer da pessoa um pintor no mínimo, razoável.

E falta experiência de vida e consciência social de que não somos seres isolados. O direito de um começa quando este reconhece que os demais também tem direitos.

Picasso comentou certa vez, alegremente, que quando era criança, já pintava como um grande mestre. Mas foi só quando envelheceu que finalmente conseguiu aprender a pintar como um menino.

.'.

quinta-feira, 3 de setembro de 2009

Feliz Aniversário Internet

Neste dia 02 de Setembro, a internet completa 40 anos.

Em 1969, num laboratório da Universidade da Califórnia em Los Angeles, dois computadores transmitiram dados de teste por um cabo cinza, com cerca de 5 metros.

Um mes depois, o Instituto de Pesquisa Stanford aderiu a nascente ARPANET seguidas naquele ano pela Universidade Catolica de Santa Barbara e pela Universidade de Utah.

Ver matéria no site da National Geographic.

quarta-feira, 2 de setembro de 2009

Caminho do Aprendizado

Se quer ser bom na sua profissão, estude suas ferramentas, aprimore-se, domine o assunto.

Se quer ser um mestre da profissão, estude as pessoas.


.'.

DM9 dá uma escorregada, mas logo passa


"Vazou" um trabalho da DM9, com aviões sobre Nova York, o que com certeza incomodou o pessoal do Onze de Setembro. Quer dizer, publicaram mesmo e depois disseram que foi por engano.

Link para a matéria:
http://portalexame.abril.com.br/blogs/4p/20090902_listar_dia.shtml?permalink=193324


Meu comentário:

Um trabalho tecnicamente bem feito. Claro que não deveria ter vindo a público, pois as demais pessoas do mundo, nem sempre ficariam muito contentes em descobrir como alguns pensam.

Sobre o tema, bem, típico alarde ecochato da pregação da verdade única batendo com o livro na cabeça dos outros para conversão na marra.

Só esquecendo, ao meu ver, que naquela situação, conta menos a quantidade do que a causa (ação da natureza Versus ação de um).

De resto, a DM9 e uma ótima agência, e uns deslizes acontecem, mesmo que machucando uma perna para aprender a usar o calçado correto, quando necessário ;)


Vide também: Ainda sobre a DM9 e o WWF

.'.

Performance: Quando A Culpa Não é do Banco de Dados

The IBM Stretch supercomputer.
Photo: IBM

Performance: Quando A Culpa Não é do Banco de Dados
02/09/2009

Otizimizando a performance em SQL com Join e Subquerys


Com frequência temos casos em que uma determinada seleção de registros, apesar de parecer atender as necessidades iniciais, não é satisfatória devido a demora do processamento.

Uma das causas, é pela utilização apenas de dados de teste, em tabelas pequenas. Com isto, o tempo real de execução deixa de ser avaliado e, como resultado, o coitado do DBA vai ter que ouvir mais uma vez que “minha Select funcionou, então é o banco de dados é que tem problema”. Ou então, será alegado culpa do usuário...

Mas existem muitas diferenças entre simplesmente “funcionar”, e funcionar de forma eficiente.

A complexidade de uma seleção de dados, vai levar em conta, o tempo de que dispomos para sua codificação é claro, mas também, é preciso ponderar no ganho de tempo, mesmo na fase de testes com dados reais, e os recursos utilizados em produção. Na maior parte das vezes, o tempo ganho estudando a otimização compensa largamente e geralmente diminui o tempo de programação e testes.

Outra falha, é confiar excessivamente nos recursos de otimização automática dos gerenciadores de banco de dados. Nem sempre estes farão a melhor escolha. Como por exemplo, ao avaliar a disponibilidade de outros índices, neste caso, mudando as chaves de seleção de alguma forma, que poderá ter um impacto significante. Também a hierarquia como serão processadas as condições de seleção e até mesmo, transferir parte dos recursos para outra tabela, ainda assim de forma mais eficiente no resultado geral, pelo aproveitamento de dados em cache.

Tomei para este exemplo, uma seleção de dados numa tabela real, mudando é claro os nomes para o exemplo, com cerca de 60 milhões de registros de movimentos relativos a um conjunto de setores, relacionadas noutra tabela.

Esta transação era utilizada diariamente numa consulta pelo usuário final, os diretores da empresa para decisões de mudanças estratégicas em tempo real para ofertas nas suas lojas, mas demorava até absurdamente 2 horas! Imagine alguém da diretoria precisando tomar decisões de enorme valor financeiro a nível nacional, literalmente milhões de $ e tendo que esperar este tempo todo! Certamente era desejável obter uma boa performance.

É importante observar, que mesmo que fosse o caso de um programa de execução única ou eventual, a enorme perda de tempo durante a fase de testes compensa largamente que se faça um código melhor.
Veja bem: como é que vou trabalhar se entre um teste e outro preciso esperar horas? Estamos no Século XXI, é hora das coisas funcionarem melhor e serem melhor feitas. 
Desta forma, teremos nosso trabalho pronto mais rápido, e também, estaremos economizando os recursos do sistema e da empresa que também são utilizados pelos demais usuários.
E também muito importante, é lembrar que geralmente, não teremos exclusividade de uso do servidor. Existem outros programas disputando recursos. No caso do exemplo atual, eram mais de 5000 estações fazendo todo tipo de transação acessando exatamente a tabela principal desta pesquisa, além de uma grande quantidade de processamento batch realmente volumosos.

O sistema gerenciador de banco de dados (SGBD) neste caso, era o Sybase AES (Adaptative Server Enterprise) 12.5. Usei os comandos sp_showplan e sp_statistics para listar resumos das execuções.
Os conceitos aqui mostrados servem para qualquer outro SGBD Relacional, como Oracle, Sql Server, etc.


A Select original que está abaixo, vai retornar a soma para quatro condições diferentes em cada setor existente.
Para nosso exemplo temos duas tabelas: Setores e Movimentos. Precisamos selecionar os Setores de Tipo = 'X', e os movimentos dentro de um periodo de datas, que tenham um determinado CodigoTeste igual ou diferente de zero e, que poderá ter uma segunda condição a ser testada. Ainda, precisamos o total geral de registros.

Neste modelo, em que a tabela de setores é a principal, simplesmente fizeram quatro varreduras na tabela de movimentos para cada um dos setores dentro do período selecionado. Uma leitura para cada um dos campos a ser somado! O tempo de execução foi obviamente bastante longo.

Logo abaixo estão as estatísticas de execução.

Select Original:

select Setores.codigoSetor,
       (select count(*) from Movimentos b
               where Setores.codigoSetor = b.codigoSetor and
                     dataOperacao between '04/01/2009' and '04/30/2009'),
       (select count(*) from Movimentos c
               where Setores.codigoSetor = c.codigoSetor and
                     dataOperacao between '04/01/2009' and '04/30/2009' and
                     codigoFlagTeste 0),
       (select count(*) from Movimentos d
               where Setores.codigoSetor = d.codigoSetor and
                     dataOperacao between '04/01/2009' and '04/30/2009' and
                     codigoFlagTeste = 0 and tipoABCDE in (1, 2, 3, 4)),
       (select count(*) from Movimentos e
               where Setores.codigoSetor = e.codigoSetor and
                     dataOperacao between '04/01/2009' and '04/30/2009' and
                     codigoFlagTeste = 0 and tipoABCDE not in (1, 2, 3, 4))
  from Setores (index indiceSetores01)
  where (tipoSetor = 'X' or Setores.codigoSetor = 999)
  order by Setores.codigoSetor


Estatística da Execução:
----------------------------------
Table: Movimentos scan count 121, logical reads: (regular=124152 apf=0 total=124152), physical reads: (regular=1129 apf=123023 total=124152), apf IOs used=123023

Table: Movimentos scan count 121, logical reads: (regular=6949399 apf=10100 total=6959499), physical reads: (regular=843310 apf=5103725 total=5947035), apf IOs used=5090713

Table: Movimentos scan count 121, logical reads: (regular=1003943 apf=2237 total=1006180), physical reads: (regular=37563 apf=261910 total=299473), apf IOs used=262198

Table: Movimentos scan count 121, logical reads: (regular=1003943 apf=0 total=1003943), physical reads: (regular=0 apf=0 total=0), apf IOs used=0

Table: Setores scan count 1, logical reads: (regular=51 apf=0 total=51), physical reads: (regular=47 apf=16 total=63), apf IOs used=1


===> Total actual I/O cost for this command: 132.860.664... !!!
Total writes for this command: 125

Execution Time 749.
SQL Server cpu time: 74900 ms. SQL Server elapsed time: 1.471.296 ms.

(121 rows affected)
----------------------------------


Vemos que houve um processamento bastante repetitivo e bem pesado. Para cada linha selecionada na tabela Setores, são feitos quatro leituras na tabela de Movimentos, que neste caso, pelo menos tinha um Indice por data. Mas ainda assim, é demais.

Podemos melhorar isto em duas partes principais.
  1. Fazer apenas um ciclo de leitura na tabela de Movimentos eliminando as subconsultas. 
  2. Otimizar a forma como vamos validar quais código de setor serão validados.

Para aproveitar melhor o ciclo de leitura, fazendo a contagem das condições que precisamos verificar, utilizamos o comando CASE WHEN, que é semelhante a do SQL Server. A maioria dos SGBDs possui uma condição de critério.
A tabela de Movimentos passa a ser o principal e não mais o de Setores, também temos no mesmo um índice por setor e data.
E usamos o Join que não era usado!

Assim teremos:

  select codigoSetor, count(*),
        sum ( case
                when b.codigoFlagTeste 0 then 1 else 0 end ),
        sum ( case
                when b.codigoFlagTeste = 0 and
                     tipoABCDE in (1, 2, 3, 4) then 1 else 0 end ),
        sum ( case
                when b.codigoFlagTeste = 0 and
                     tipoABCDE not in (1, 2, 3, 4) then 1 else 0 end )
   from Movimentos b
   join Setores (index indiceSetores01)
     on Setores.codigoSetor = b.codigoSetor
   where dataOperacao between '04/01/2009' and '04/30/2009' and
        (tipoSetor = 'X' or Setores.codigoSetor = 999)
   group by codigoSetor
  

Estatística da Execução:
----------------------------------
Table: Movimentos scan count 1, logical reads: (regular=60523 apf=53 total=60576), physical reads: (regular=48421 apf=6249 total=54670), apf IOs used=6173

Table: Setores scan count 95560, logical reads: (regular=99289 apf=0 total=99289), physical reads: (regular=10 apf=0 total=10), apf IOs used=0

Table: Worktable1 scan count 1, logical reads: (regular=6545 apf=0 total=6545), physical reads: (regular=0 apf=0 total=0), apf IOs used=0


===> Total actual I/O cost for this command: 1.317.060... (apenas 1% do anterior)


Execution Time 15.
SQL Server cpu time: 1500 ms. SQL Server elapsed time: 83.800 ms.


Basta uma rápida olhada para perceber imediatamente que a diferença na quantidade de I/Os e no tempo de processamento é impressionante, próximo de apenas 1% da select original!

Mas ainda podemos mudar um pouco isto para explorar alternativas.

Observem que utilizamos um Join para validar a tabela de setores. Mas neste caso, poderemos ter várias releituras da mesma.

Também seria possível a condição 'where... IN' para validar o setor, ao invés de Join. Mas neste caso, pode ocorrer um aumento no número de I/Os, que é pequeno em relação ao problema original, mas que deverá ser estudado se for noutra implementação

Assim teremos:

select codigoSetor, count(*),
       sum ( case
               when b.codigoFlagTeste 0 then 1 else 0 end ) ,
       sum ( case
               when b.codigoFlagTeste = 0 and tipoABCDE in (1, 2, 3, 4) then 1 else 0 end ) ,
       sum ( case
               when b.codigoFlagTeste = 0 and tipoABCDE not in (1, 2, 3, 4) then 1 else 0 end )
  from Movimentos b
  where dataOperacao between '04/01/2009' and '04/30/2009' and
        codigoSetor in (select codigoSetor
                          from Setores (index indiceSetores01)
                          where tipoSetor = 'X' or Setores.codigoSetor = 999)
  group by codigoSetor  

Estatística da Execução:
----------------------------------
Table: Movimentos scan count 1, logical reads: (regular=60523 apf=26 total=60549), physical reads: (regular=51955 apf=4993 total=56948), apf IOs used=4822

Table: Setores scan count 95560, logical reads: (regular=99627 apf=0 total=99627), physical reads: (regular=27 apf=0 total=27), apf IOs used=0

Table: Worktable1 scan count 1, logical reads: (regular=6545 apf=0 total=6545), physical reads: (regular=0 apf=0 total=0), apf IOs used=0


===> Total actual I/O cost for this command: 1.358.992.
Total writes for this command: 6884

Execution Time 18.
SQL Server cpu time: 1800 ms. SQL Server elapsed time: 107.326 ms.

(113 rows affected)
----------------------------------


Portanto vemos que a Alternativa A ainda foi uma melhor modificação.

Uma observação adicional, é que ao mudarmos a select original, também foram eliminados alguns resultados desnecessários, que precisariam processamento posterior, daí a diferença na quantidade de registros resultante ter baixado de 121 para 113.


Comparativo


Custo Total
I/O
Tempo Execução
Tempo CPU
SQL Server elapsed time
Original
132.860.664
749
74900 ms
1.471.296 ms
Alternativa A
1.317.060
15
1500 ms
83.800 ms
Alternativa B
1.358.992
18
1800 ms
107.326 ms



Conclusão:

Obtive para a empresa uma redução aproximada de 99% na quantidade de I/Os necessários e de 98% no tempo de execução.

Alguns pontos podem ser melhorados, mas em face do ganho obtido, já ficou num nível mais satisfatório, especialmente considerando a cultura local da empresa. 

Assim, passaram a tomar decisões mais rápidas, negócios de milhões $ que puderam agilizar de maneira melhor e certamente maiores lucros. 


Resultados:

  • Enorme economia de recursos.
  • Maior disponibilidade do servidor para atender outras transações.
  • Maior satisfação do usuário final que passou a ter muito mais agilidade.
  • Ciclo de desenvolvimento e testes do programa foram reduzidos a uma fração do previsto.
  • Ganhos de milhões de $ para a empresa diariamente. 


Gostaram do exemplo? 

Apenas para citar, que tal outro caso de uma aplicação chave para a empresa, novamente envolvendo muitos milhões de $ e demorava 16-18h. Só podiam executar no fim de semana e tinham que cortar os servidores da rede. Consegui reduzir para menos de 2h e sem afetar a rede. Neste caso, além de otimizar o SQL também foram utilizadas soluções de lógica complexa necessarios para melhor uso da CPU e obter melhores resultados. 

Quanto sua empresa ganha com serviço bem feito


Se precisam de um profissional de longa experiência que sabe o que fazer, aceito convites que sejam realmente sérios. Só falo diretamente com o responsável pela contratação, não entro em fila e nem preencho ficha em site.  




Leia também:



..