Otimização query SQL e Sugestão para os moderadores

Como vocês otimizam suas query SQL?Existem boas práticas na construção de querys pesadas?
Por que não criar um forum sobre Banco de dados?

[quote=antoniopopete]Como vocês otimizam suas query SQL?Existem boas práticas na construção de querys pesadas?
Por que não criar um forum sobre Banco de dados?[/quote]

Dá uma olhada aqui: [quote]http://www.devmedia.com.br/canais/default.asp?site=37[/quote]
Otimizar uma query é complicado, n tem nenhum DBA pra te auxiliar não? tem mtos fatores para ver antes de sair mexendo.

É isso cara,mas queria o relato de alguém sobre quais são esses aspectos que devemos analisar antes de mudarmos uma query.
Sei que posição da tabela na chamada do from influencia.Mas queria saber outros fatore.s…

1º se vc ta dando full table scan…
2º está rodando na aplicação ou no banco…
3º se for na aplicação, tem q ver se não é mto custoso, talvez fazer uma proc.
4º se já estiver no banco, veja os passos dela e tente simplificar, algumas vezes as pessoas fazem rapido e de qq forma apenas para entregar algo q tao enchendo o saco, dai já viu… :frowning:

Analise começando por isso :smiley:

Otimização de queries?
Normalmente você precisa usar alguma ferramenta do seu banco de dados para ver se você não está precisando usar algum índice.

Coisas que tornam suas aplicações lentas:

  • Índices inadequados ou falta de índices.
  • Excesso de índices se sua aplicação faz muitos INSERTS ou DELETES nessa tabela.
  • Falta de chaves primárias nas tabelas.
  • LIKE - evite “%XXX%” como a peste. Se precisar de LIKE por algum motivo, ponha o “%” apenas no final, ou seja, “XXX%” (que será convertido pela maioria dos bancos em algo parecido com “BETWEEN XXX AND XXX_”. Se isso não puder ser evitado, então veja se a tabela vai ser muito grande. Se for muito grande, use alguma solução de “full text search” do seu banco - isso vai envolver o uso de algum SQL específico do banco para efetuar as queries de “full text search”.
  • Criação de SELECTs dinâmicos - é preferível usar PreparedStatements para os SELECTs, pois aí o banco pode criar um plano de execução para o SELECT. (Alguns bancos são mais espertos e reconhecem os selects dinâmicos, mas não conte com isso)
  • Acessar o banco sem saber o que está fazendo.
  • Se estiver usando Hibernate, tente usar LAZY em vez de EAGER.

Coisas que parecem que ajudam mas não muito:

  • Mexer na ordem das condições do WHERE ou dos JOINs - normalmente os bancos de dados (exceto aqueles muito simples, como o HSQLDB) ignoram a ordem das condições do WHERE ou dos JOINs e usam alguma estatística do banco de dados e alguma heurística. Você precisa fazer alguma reza braba (como aqueles comentários /+/ do Oracle) para fazer com que ele faça do jeito que você acha que deve ser melhor (normalmente o banco é melhor nesse ponto).
  • Deixar todas as colunas com tamanhos fixos (CHAR em vez de VARCHAR) - isso só ocupa espaço em disco e não acelera o acesso; muitas vezes até deixa mais lento porque o banco fica maior e menos dados cabem no cache.

Banco de dados já foge bastante do tema do GUJ, além de não ter tanta demanda assim por aqui.

Rafael

Banco de dados já foge bastante do tema do GUJ, além de não ter tanta demanda assim por aqui.

Rafael[/quote]
Beleza Rafael.

Em relação ao que o thingol falou, achei que a ordem das chamadas no From e na condição where influenciasse de alguma forma o desempenho.Nem a ordem do from interessa?No caso do Oracle (o melhor dos melhores), ele deve organizar isso, concorda?
O que você chama de select dinâmicos? :oops:

SELECT dinâmico (na falta de um melhor nome) é aquele que você monta “no braço” e que você vê aqui no fórum em 99% dos casos em que o cara montou incorretamente a string e está com problemas de sintaxe ou outras coisas mais sutis:

String sql = "SELECT " + campo1 + "," + campo2";
sql += "FROM " + tabela1";
sql += "WHERE " + campo1 + " = " valor1";
...

[code]StringBuilder sql = new StringBuilder();

sql.appen("SELECT ID,DESCRICAO FROM TESTE WHERE ID = ?);

setParametro[/code]

É isso???
E como seria não dinâmico?

acho que seria algo como

sql.appen("select id, descricao from teste where id = 1");

[quote=mendigosujo]acho que seria algo como

sql.appen("select id, descricao from teste where id = 1"); [/quote]

os parametros não necessitam serem fixos

[quote]antoniopopete wrote:
Como vocês otimizam suas query SQL?Existem boas práticas na construção de querys pesadas?
Por que não criar um forum sobre Banco de dados?[/quote]

Creio que na net já existam fóruns mais especializados só com o tema BD, no GUJ você vai encontrar auxilio com BD voltando para o Java. Mesmo porque o que você deseja é o que chamamos de “turning no banco de dados”, e realmente pelo que conheço, isso é feito por um analista ou programador só voltado para o ambiente de SGBD, capaz de realizar análise minuciosa da performance das consultas e transações, e não um profissional que tenha também contato com o desenvolvimento de aplicações de negócio.

Aí vai o que os acadêmicos ensinam para otimizar uma query:

Primeiro - Construir a árvore canônica da query
Segundo - Selecionar o mais rápido possível
Terceiro - substituir as seleções de junção por JOIN
Quarto - Fazer as melhores escolhas quanto aos dados que serão selecionados/juntados primeiro
Quinto - Projetar somente os dados necessários
Sexto - transformar a árvore resultante na query otimizada

Se você não entende algum desses termos, sugiro que pesquise em algum fórum de BD. Porque mal mal eu entendo heheehheeh

Banco de dados já foge bastante do tema do GUJ, além de não ter tanta demanda assim por aqui.

Rafael[/quote]
Beleza Rafael.

Em relação ao que o thingol falou, achei que a ordem das chamadas no From e na condição where influenciasse de alguma forma o desempenho.Nem a ordem do from interessa?No caso do Oracle (o melhor dos melhores), ele deve organizar isso, concorda?
O que você chama de select dinâmicos? :oops: [/quote]

Infelizmente a ordem no From afeta a consulta. Não deveria, afinal você está declarando ali todas as tabelas que devem ser usadas e cabe ao banco decidir através do plano de execução qual delas selecionar primeiro.

Boa tarde,

Vi respostas muito interessante nesse forum, o passo mais correto é analisar a query fazendo a arvore canonica, depois torcar junçoes por joins, etc (ta em qualquer livro d bd). Mas não é só isso. Esta é a forma “universal” de se otimizar uma query. Mas se quiser que a query fique “perfeita”, tem q fazer tudo isso e ainda tem q entender profundamente sobre o sgbd q vc ta utilizando.

Um exemplo do q eu disse é o classico caso do MySQL. O MySQL tem problemas para tratar operações inteiras na comparação, portanto um passo importante seria tirar todas as clausulas “or” e montar um novo select com o “union”. Mas esse é um dos casos do MySQL. Cada SGBD tem sua especialidade.

[code]
public ArrayList select() {

    ArrayList<Client> lst = new ArrayList<Client>();
    ArrayList<Car> lstCar;

    Mark m = new Mark();
    Model mo = new Model();

    ResultSet rs, rsCar;

    try {

        query.open();
        rs = query.select("select * from client order by nameClient ASC");

        while (rs.next()) {

            rsCar = query.select("SELECT car.* FROM carowner INNER JOIN car ON car.matricula = carowner.matricula WHERE nCont = " + rs.getInt("nClient"));

            lstCar = new ArrayList<Car>();

            while (rsCar.next()) {
                lstCar.add(new Car(rsCar.getString("matricula"), rsCar.getString("VIN"), m.select(rsCar.getInt("idMarca")),
                        mo.select(rsCar.getInt("idModelo")), rsCar.getDate("dataFabrico"), rsCar.getInt("yearMake"),
                        rsCar.getString("tipoMotor"), rsCar.getInt("cc"), rsCar.getString("fuel"), null));
            }

            lst.add(new Client(rs.getInt("nClient"),rs.getInt("nCont"), rs.getString("nameClient"), rs.getString("adressClient"),
                    rs.getInt("codPost1"), rs.getInt("codPost2"), rs.getString("freg"), rs.getInt("phoneClient"),
                    rs.getInt("mobileClient"), rs.getString("email"), lstCar, rs.getDate("bornDate")));
        }

        query.close();

    } catch (SQLException e) {
        query.close();
        e.printStackTrace();
    }

    return lst;
}[/code]

Pelo que pode analisar este select está bastante pesado! existe alguma forma de o melhorar?