melhorando o desempenho de suas consultas no mysql

Post on 24-May-2015

4.602 Views

Category:

Education

7 Downloads

Preview:

Click to see full reader

DESCRIPTION

Material pertencente ao mini-curso sobre MySQL aos desenvolvedores da Hipcom Informática.

TRANSCRIPT

Melhorando o desempenho de suas consultas no MySQLComo não aborrecer o DBA e ter um bom desempenho em suas consultas.

É necessária a otimização?

Grande parte da responsabilidade para que o banco de dados funcione bem é de quem modela a base de dados!

Uma Base de dados bem modelada é uma base importante para

se criar sistemas coesos e robustos!

FreeDigitalPhotos.net

É necessária a otimização?

Mas em alguns sistemas, temos uma modelagem muito particular...

Nem sempre temos uma base de dados

modelada como sonhamos...

FreeDigitalPhotos.net

É necessária a otimização?

Nestes casos, a otimização deve ser primordial!

"Não posso escolher como me sinto, mas posso escolher o que fazer a respeito".

William Shakespeare

FreeDigitalPhotos.net

Entendendo o banco de dados relacional

Resumidamente, existem duas maneiras de se trabalhar com um banco de dados relacional...

Você é livre para escolher qual utilizar!"Não é livre quem não obteve domínio sobre si".Pitágoras

FreeDigitalPhotos.netFreeDigitalPhotos.net

Entendendo o banco de dados relacional

Banco de dados relacionais são matemáticos.Eles trabalham, resumidamente, com teoria de conjuntos...● Produto cartesiano● Cardinalidade

"A matemática é o alfabeto com o qual Deus escreveu o universo". Pitágoras

FreeDigitalPhotos.net

Ferramentas úteis de análise

Podemos analisar uma função explícita, utilizando o BENCHMARK.

SELECT BENCHMARK(1000000,2+2);

O MySQL irá executar um milhão de vezes a expressão, em determinado tempo.

Ferramentas úteis de análise

Podemos entender melhor o funcionamento de nosso script usando o EXPLAIN.

EXPLAIN SELECT * FROM ctbplc;

O MySQL retornará um registro contendo uma análise do script.

Ferramentas úteis de análise

● Colunas de retorno do EXPLAIN SELECT○ ID: Número sequencial que identifica as consultas

dentro do SELECT.○ SELECT_TYPE: Tipo de cláuso SQL:

■ SIMPLE (Select simples)

■ PRIMARY (Select mais externa)

■ UNION (segunda select ou select proveniente do UNION)

■ DEPENDENT UNION (segunda select ou select proveniente do UNION)

■ SUBQUERY (primeiro select encadeado - subquery)

■ DEPENDENT SUBQUERY (primeiro select encadeado da subquery)

■ DERIVED (select de tabela derivada - Subquery da cláusula FROM)

Ferramentas úteis de análise

● Colunas de retorno do EXPLAIN SELECT○ TABLE: Tabela do registro de saída.○ TYPE: Tipo de JOIN:

■ SYSTEM (tabela que só tem uma linha, tabela de sistema)

■ CONST (tabela que tem no máximo uma linha coincidente. São constantes)

■ EQ_REF (todas as partes da chaves são usadas para combinação de registros)

■ REF (idem ao EQ_REF, mas com índices não únicos)

■ REF_OR_NULL (idem ao REF, mas com busca IS NULL)

■ RANGE (faixa de busca quando o campo é comparado a uma constante)

■ INDEX (quando a consulta só usa colunas que são parte de um índice)

■ ALL (varredura completa na tabela para a busca de registros)

Ferramentas úteis de análise

● Colunas de retorno do EXPLAIN SELECT○ POSSIBLE_KEYS: Sugestão de índices a serem

utilizados.○ KEY: Chave que está sendo utilizado na consulta.○ KEY_LEN: Tamanho da chave do campo KEY.○ REF: Colunas utilizadas pela chave do campo KEY.○ ROWS: Quantidade de linhas que será analisada

para gerar a consulta.

Ferramentas úteis de análise

● Colunas de retorno do EXPLAIN SELECT○ EXTRA: Sugestão de índices a serem utilizados.

■ Distinct (Termina a busca quando encontra o primeiro registro coincidente)

■ Not exists (idem ao Distinct, mas com LEFT JOIN)

■ Range checked for each record (index map: #) (O MySQL não encontrou um bom índice para usar)

■ Using filesort (Pesquisa extra na tabela para realizar a ordem de classificação)

■ Using index (Recuperação feita apenas com índices)

■ Using temporary (Utilização de tabelas temporárias para realizar a busca)

■ Using where (Tipo de restrição na busca de registros)

Detalhes: http://dev.mysql.com/doc/refman/5.1/en/explain-output.html

Melhorando a performance

● Dicas importantes para SELECT a que já existem:○ ANALYZE TABLE: Esta função atualizará as estatísticas sobre a

tabela. Tais estatísticas são utilizadas pelo MYSQL para seleção de como e qual índice pode ser utilizado.

● Utilize SHOW INDEX FROM para verificar se a referência de cardinalidade (coluna Cardinality) está atualizada!

● Os campos das chaves utilizadas devem ser do mesmo tipo e tamanho para que as buscas sejam mais rápidas (também influencia no Join).

Melhorando a performance

● Dicas importantes para WHERE:○ ANALYZE TABLE: Esta função atualizará as

estatísticas sobre a tabela. Tais estatísticas são utilizadas pelo MYSQL para seleção de como e qual índice pode ser utilizado.

○ Se todas colunas usadas do índice são numéricas, então somente a árvore de índice é usada para resolver a consulta.

Melhorando a performance

● Dicas importantes para WHERE:○ Se você não utiliza colunas de todas tabelas

usadas, o MySQL irá parar a varredura das tabelas não usadas logo que encontrar a primeira coincidência.

SELECT DISTINCT t1.a FROM t1,t2 WHERE t1.a=t2.a;

Melhorando a performance

● Dicas importantes para WHERE:○ Você está unindo muitas tabelas e as colunas nas

quais você está fazendo um ORDER BY não são todas da primeira tabela que não é constante.

○ O ideal é que os campos do ORDER BY sejam da primeira tabela.

Melhorando a performance

● Dica importante para WHERE:○ Tente usar campos no ORDER BY façam parte de

índices. Isso evita um processo de ordenação por parte do MySQL.

○ Internamente, o MySQL ordena as consultas GROUP BY como de fosse o ORDER BY. Para que só o agrupamento aconteça, inclua no seu script um ORDER BY NULL;

Melhorando a performance

● Dica importante para LIMIT:○ O MySQL vai buscar a quantidade de registros

estipulados no LIMIT e só depois vai executar outras funções (ORDER BY ou GROUP BY, por exemplo).

Melhorando a performance

● Dicas importantes para INSERT:○ Importação de dados: Pode-de utilizar o LOAD

DATA INFILE. A velocidade de inserção de registros pode melhorar em até 20x.

ZQuery.Close; ZQuery.SQL.Clear; ZQuery.SQL.Text:='LOAD DATA INFILE ''c:ctbplc.csv'' INTO TABLE ctbplc FIELDS TERMINATED BY '','' ENCLOSED BY ''"''LINES TERMINATED BY ''\n''ignore 1 lines;'; ZQuery.ExecSQL;

Melhorando a performance

● Dicas importantes para INSERT:○ Na importação de um volume grande de dados,

também é válido desabilitar os índices com ALTER TABLE <TABELA> DISABLE/ENABLE KEYS.

Melhorando a performance● Dicas importantes para INSERT:

○ Lotes de inserção: Pode-de utilizar o BEGIN / END / COMMIT para montar um bloco de comandos insert. A vantagem em velocidade se torna interessante com blocos de 1000 registro.

ZQuery.Close; ZQuery.SQL.Clear; ZQuery.SQL.Text:='start transaction'; ZQuery.ExecSQL; try //Comandos dos inserts ... ZQuery.Close; ZQuery.SQL.Clear; ZQuery.SQL.Text:='commit'; ZQuery.ExecSQL; except ZQuery.Close; ZQuery.SQL.Clear; ZQuery.SQL.Text:='rollback'; ZQuery.ExecSQL; end;

Melhorando a performance● Dica importante para UPDATE:

○ Deixar para alterar todo o registro de uma só vez.

Melhorando a performance● Dica importante para DELETE:

○ Se for "limpar" uma tabela, use o TRUNCATE TABLE

Melhorando a performance● Dicas importantes:

○ Dentro do possível, dê preferência para a utilização de conexões persistentes. Isso evita sobrecarga de conexões no servidor de banco de dados.

Melhorando a performance● Dicas importantes:

○ Se suas buscas usam uma determinada ordem de campos, mas na tabela esses campos estão em uma ordem diferente, mude a ordem dos campos da tabela com ALTER TABLE... ORDER BY expr1,expr2....

Melhorando a performance● Quebrando alguns paradigmas:

○ Índices com muitos campos podem ser substituidos por um único campo "hash": SELECT * FROM <nome_tabela> WHERE col_hash=MD5(concat(col1,col2)) AND col_1='constante' AND col_2='constante'.

Melhorando a performance● Quebrando alguns paradigmas:

○ Tabelas com muita alteração: evite as colunas varchar e blob. Dê preferência a registros de tamanho fixo.

Melhorando a performance● Quebrando alguns paradigmas:

○ Não tenha vergonha de quebrar, em pontos críticos, a 3ª forma normal.

Mais detalhes: http://pt.wikipedia.org/wiki/Banco_de_dados_relacional

Entendendo melhor as coisas...● Como funcionam os índices?

FreeDigitalPhotos.net

Entendendo melhor as coisas...● Onde os índices são usados:

○ Para encontrar rapidamente os registros que coincidam com uma cláusula WHERE.

○ Para recuperar registros de outras tabelas ao realizar joins.

○ Para encontrar o valor MAX() ou MIN() para uma coluna indexada especifica.

○ Para ordenar ou agrupar uma tabela.

Entendendo melhor as coisas...● Exemplos:

○ Se a tabela possuir um índice de múltiplas colunas, qualquer prefixo mais à esquerda do índice pode ser usado pelo MySQL para encontrar registros. Por exemplo, se você possui um índice de três colunas em (col1, col2, col3), você tem capacidades de busca indexada em (col1), (col1, col2) e (col1, col2, col3).

○ SELECT col3 FROM <nome_tabela> WHERE col1=1 .

○ SELECT * FROM <nome_tabela> WHERE col1=val1 AND col2=val2 .

Entendendo melhor as coisas...● Exemplos:

○ Se a tabela possuir um índice de múltiplas colunas, qualquer prefixo mais à esquerda do índice pode ser usado pelo MySQL para encontrar registros. Por exemplo, se você possui um índice de três colunas em (col1, col2, col3), você tem capacidades de busca indexada em (col1), (col1, col2) e (col1, col2, col3).

○ SELECT * FROM <nome_tabela> WHERE col1=val1;

○ SELECT * FROM <nome_tabela> WHERE col2=val2;

○ SELECT * FROM <nome_tabela> WHERE col2=val2 AND col3=val3;

Entendendo melhor as coisas...● Exemplos:

CREATE TABLE teste (id INT NOT NULL,ultimo_nome CHAR(30) NOT NULL,primeiro_nome CHAR(30) NOT NULL,PRIMARY KEY (id),INDEX nome (ultimo_nome,primeiro_nome));

○ SELECT * FROM teste WHERE ultimo_nome="Lopes";

○ SELECT * FROM teste WHERE ultimo_nome="Lopes" AND primeiro_nome="Helder";

○ SELECT * FROM teste WHERE ultimo_nome="Lopes" AND (primeiro_nome="Helder" OR primeiro_nome="Francisco");

○ SELECT * FROM teste WHERE ultimo_nome="Lopes" AND primeiro_nome >="H" AND primeiro_nome < "S";

○ SELECT * FROM teste WHERE primeiro_nome="Helder";

○ SELECT * FROM teste WHERE ultimo_nome="Lopes" OR primeiro_nome="Helder";

Entendendo melhor as coisas...● Exemplos:

○ Um índice é usado para colunas que você compara com os seguintesoperadores: =, >, >=, <, <=, BETWEEN, IS NULL ou um LIKE com um padrão que começa com um prefixo sem meta caracteres.

○ SELECT * FROM <nome_tabela> WHERE key_col LIKE "Helder%";

○ SELECT * FROM <nome_tabela> WHERE key_col LIKE "Hel%_er%"

○ SELECT * FROM <nome_tabela> WHERE key_col LIKE "%Helder%";

Entendendo melhor as coisas...● Cuidado com os AND:

○ Qualquer índice que não cobre todos os níveis de AND na cláusula WHERE não é utilizado para otimizar a consulta.

Entendendo melhor as coisas...● Índices pré-fixados:

○ Para colunas CHAR, VARCHAR, BLOB e TEXT pode-se indexar um prefixo da coluna.

○ Isto é muito mais rápido e necessita de menos espaço em disco do que indexar a coluna inteira.

CREATE TABLE teste (nome CHAR(200) NOT NULL, INDEX nome_indice (nome(10)));

Bibliografia● Baron Schwartz, Peter Zaitsev, Vadim Tkachenko, Jeremy D. Zawodny, Arjen Lentz, Derek J.

Balling. High Performance MySQL: Optimization, Backups, Replication, and More. O'Reilly Media, Inc., 2008; 2ª ed; ISBN 0596554753.

● Wikipédia. Árvore B. http://pt.wikipedia.org/wiki/%C3%81rvore_B Acessado em 18/02/2013.

top related