• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

mAiN_iNfEcTiOn

MySQL Foreign Keys

4 mensagens neste tópico

Pessoal a minha dúvida é BÁSICA à primeira vista... Esperemos que seja de todo básica para ficar a perceber  :P

ISTO PASSA-SE COM UMA BD MYSQL!!!!  :)

Ora bem, eu tenho as seguintes tabelas (com os seguintes campos):

  • TIPOS: ID,TIPO
  • UTILIZADORES: ID,Nome,Morada,(...),IDTipo

Ora como é lógico, na teoria SQL, o campo IDTipo da tabela UTILIZADORES é uma foreign key (chave estrangeira)...

Agora digam-me qual é a diferença de desempenho entre eu definir (quando estou a criar a tabela) que aquele determinado campo é Chave Estrangeira ou NÃO O DEFINIR e apenas assumir (e especificar) isso nas queries que faço à base de dados?

Por exemplo:

eu tenho esta query SELECT UTILIZADORES.* FROM UTILIZADORES,TIPOS WHERE UTILIZADORES.IDTipo=TIPOS.ID

ora esta query especifica que o campo IDTipo da tabela utilizadores TEM que ser igual ao da tabela TIPOS... (de modo a fazer-se a relação)...

Existiria algum tipo de diferença de desempenho ou até mesmo da estrutura da query, se eu definisse o campo IDTipo como Foreign Key?

(Espero k tenham percebido  :P)

Aguardo resposta

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Pessoal a minha dúvida é BÁSICA à primeira vista... Esperemos que seja de todo básica para ficar a perceber  :P

ISTO PASSA-SE COM UMA BD MYSQL!!!!  :)

Ora bem, eu tenho as seguintes tabelas (com os seguintes campos):

  • TIPOS: ID,TIPO
  • UTILIZADORES: ID,Nome,Morada,(...),IDTipo

Ora como é lógico, na teoria SQL, o campo IDTipo da tabela UTILIZADORES é uma foreign key (chave estrangeira)...

Uma pequena correcção: Não é na teoria SQL mas sim na teoria relacional;

Agora digam-me qual é a diferença de desempenho entre eu definir (quando estou a criar a tabela) que aquele determinado campo é Chave Estrangeira ou NÃO O DEFINIR e apenas assumir (e especificar) isso nas queries que faço à base de dados?

Urge uma clarificação: uma FK só se define FK na tabela, nunca numa query. Uma query só faz uma coisa: pesquisa e recuperação de dados.

Por exemplo:

eu tenho esta query SELECT UTILIZADORES.* FROM UTILIZADORES,TIPOS WHERE UTILIZADORES.IDTipo=TIPOS.ID

O que estás a fazer aqui é uma simples query onde queres que todos os utilizadores cujo valor do campo UTILIZADORES.IDTipo seja igual ao valor do campo TIPOS.ID.

ora esta query especifica que o campo IDTipo da tabela utilizadores TEM que ser igual ao da tabela TIPOS... (de modo a fazer-se a relação)...

Essa query não especifica nada disso que dizes, essa query, como expliquei acima, retorna apenas os registos que estão de acordo com o teu filtro (cláusula where).

Se não especificares que o campo IDTipo é uma FK, não tens absolutamente garantia nenhuma de que os valores presentes em IDTipo estejam sequer presentes na coluna ID da tabela Tipo.

Existiria algum tipo de diferença de desempenho ou até mesmo da estrutura da query, se eu definisse o campo IDTipo como Foreign Key?

(Espero k tenham percebido  :P)

Aguardo resposta

Acho que já exclareci essa confusão das FKs e dos filtros nas queries (são coisas distintas).

Quanto ao desempenho, a criação de uma FK tem impacto na performance de uma BD.

Assumindo que IDTipo é uma FK para Tipo.Id, cada registo inserido em Utilizadores vai ter de verificar se o valor introduzido em IDTipo existe em Tipo.Id.

Outro impacto na performance acontece no caso em que um motor de base de dados cria um índice associado à FK (e não sei como se o MySQL faz isto mas podes consultar a documentação). Havendo um índice associado ao IDTipo, normalmente as pesquisas onde esse campo é usado como filtro numa cláusula where, vão usar esse índice e a pesquisa é mais rápida. Por outro lado, com esse índice, cada insersão e cada remoção de registos na tabela Utilizadores é normalmente mais lenta pois implica uma actualização dos índices.

Espero ter ajudado.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Desde já o meu ENORME AGRADECIMENTO por me responderes... esta minha dúvida estava mesmo a pedir para ser solucionada :biggrin:

Já agora que falaste em Índices...

Uma vez fizeram-me a seguinte pergunta: "Se os indíces melhoram o desempenho na pesquisa, porque não definir todos os campos de uma tabela como índices?"

Ora segundo o que eu percebi com a tua resposta, isso nao seria vantajoso pk cada registo que tivessemos que inserir ficaria MUITO LENTO, pk tinha que actualizar todos os índices da tabela... (Penso que até aqui td bem  :P )

Agora eu tenho 1 dúvida, imaginando que o tempo de inserção NÃO SERIA PROBLEMA (ou seja, o cliente não quer saber quanto tempo demora a inserir um registo, quer é pesquisas rápidas) as pesquisas ficariam efectivamente MAIS RÁPIDAS ou pelo contrário, sendo tudo indíces, seria como num livro com 1 índice mto extenso onde "demoramos a achar o número da página" ?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Desde já o meu ENORME AGRADECIMENTO por me responderes... esta minha dúvida estava mesmo a pedir para ser solucionada :biggrin:

Já agora que falaste em Índices...

Uma vez fizeram-me a seguinte pergunta: "Se os indíces melhoram o desempenho na pesquisa, porque não definir todos os campos de uma tabela como índices?"

Os índices melhoram a performance nas pesquisas em certas situações, como por exemplo, quando um campo referênciado num filtro possui um índice. Isto nem sempre é verdade, por vezes há indíces e eles não são usados porque tal não iria aumentar a performance da query (se quizeres saber mais investiga sobre optimizações em SGBDs).

Se declarares índices em todos os campos as queries não vão automaticamente ser mais rápidas, tal acontece por um conjunto de factores. Por exemplo: o facto de que nem todos os campos entram nos filtros é um factor; conclui-se que é mais rápido fazer um table-scan; uso de índices em campos com valores muito repetidos podem não ajudar de forma significativa; etc..

Ora segundo o que eu percebi com a tua resposta, isso nao seria vantajoso pk cada registo que tivessemos que inserir ficaria MUITO LENTO, pk tinha que actualizar todos os índices da tabela... (Penso que até aqui td bem  :P )

Os índices são bastante vantajoso quando usados como deve ser. Uma insersão ou remoção fica mais lenta, e não "muito lenta", e as pesquisa ficam (normalmente) mais rápidas. O caso normal é que o custo das insersões e remoções acabe por ser negligível em relação aos benefícios que o índice trás nas queries.

Agora eu tenho 1 dúvida, imaginando que o tempo de inserção NÃO SERIA PROBLEMA (ou seja, o cliente não quer saber quanto tempo demora a inserir um registo, quer é pesquisas rápidas) as pesquisas ficariam efectivamente MAIS RÁPIDAS ou pelo contrário, sendo tudo indíces, seria como num livro com 1 índice mto extenso onde "demoramos a achar o número da página" ?

A menos que tenhas vários milhões de registos ou a tua bd/tabela seja um "enorme molho de bróculos" (i.e., esteja mal feita), o tempo de insersão não é um problema, acredita que nem sequer vais dar por isso.

No teu caso concreto, criar um índice sobre essa FK vai aumentar a performance da tua query, mas tal só vai começar a ser visível quando a tabela passar a ter um volume "interessante" de dados (digamos que se tiveres "meia-duzia" de registos nessa tabela o índice não está ai a fazer nada).

A forma como os índices funcionam (normalemente sobre b-trees) permite que se encontrem registos de forma bastante rápida, algo que é inerente à estrutura das b-trees.

Antes de criares o índice, consulta a documentação do MySQL não vá ele já estar a criar um índice de forma implícita sem tu saberes.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora