Fórum Otimizar SQL #253305

04/10/2004

0

Fala pessoal!
Gente fiz uma consulta SQL, mas ela esta um pouco lenta, alguem poderia me dar um help de como posso melhora-la.
Desde já agradeço.

SELECT P.PRODUTO_ID, P.DESCRICAO,P.REF_FORNECEDOR, C.COR, T.TAMANHO, M.MODELO
FROM PRODUTOS P LEFT JOIN COR C LEFT JOIN TAMANHO T LEFT JOIN MODELO M
ON C.COR_ID = P.COR_ID
ON T.TAMANHO_ID = P.TAMANHO_ID
ON M.MODELO_ID = P.MODELO_ID
WHERE UPPER(P.DESCRICAO)LIKE UPPER (´c¬´)
ORDER BY DESCRICAO


Debug

Debug

Responder

Posts

04/10/2004

Afarias

|WHERE UPPER(P.DESCRICAO)LIKE UPPER (´c¬´)

a linha acima não permite o otimizador usar o índice de descrição.

1- vc não deve usar uma função no campo de consulta
--> UPPER(P.DESCRICAO)

2- se for usar parâmetros, troque LIKE por STARTING



T+


Responder

Gostei + 0

04/10/2004

Debug

Afarias fiz o seguinte:
Me corrija se estiver errado, por favor.

SELECT P.PRODUTO_ID, P.DESCRICAO,P.REF_FORNECEDOR, C.COR, T.TAMANHO, M.MODELO
FROM PRODUTOS P LEFT JOIN COR C LEFT JOIN TAMANHO T LEFT JOIN MODELO M
ON C.COR_ID = P.COR_ID
ON T.TAMANHO_ID = P.TAMANHO_ID
ON M.MODELO_ID = P.MODELO_ID
WHERE P.DESCRICAO STARTING WITH (´C´)
ORDER BY DESCRICAO

Melhorou, mas muito pouco, percebi se eu tirar o ORDER BY a consulta fica muito mais rapida. O codigo acima esta certo? Pode melhor?
Muito obrigado por sua atenção. Valeu mesmo!


Responder

Gostei + 0

04/10/2004

Vinicius2k

Colega,

A não ser q eu não tenha entendido o contexto desta consulta, no meu entender os joins estão colocados de forma incorreta...

1. As tabelas tem índices pelo ´ID´, normalmente PKs ?
2. As colunas do join são FKs na tabela PRODUTOS (se a ligação estiver sendo feita pelas PKs isso não fará diferença) ?
3. Existe índice pela coluna DESCRICAO na tabela PRODUTOS ?

Resumidamente na estrutura :
create table COR(
  COR_ID integer not null,
  COR varchar(10)
);
alter table COR
  add constraint PK_COR primary key (COR_ID);
/* ------------------- */

create table TAMANHO(
  TAMANHO_ID integer not null,
  TAMANHO varchar(10)
);
alter table TAMANHO
  add constraint PK_TAMANHO primary key (TAMANHO_ID);
/* ------------------- */

create table MODELO(
  MODELO_ID integer not null,
  MODELO varchar(10)
);
alter table MODELO
  add constraint PK_MODELO primary key (MODELO_ID);
/* ------------------- */

create table PRODUTOS(
  PRODUTO_ID integer not null,
  DESCRICAO varchar(30),
  REF_FORNECEDOR varchar(10),
  COR_ID integer,
  TAMANHO_ID integer,
  MODELO_ID integer
);
alter table PRODUTOS
  add constraint PK_PRODUTOS primary key (PRODUTO_ID);
alter table PRODUTOS
  add constraint FK_PRODUTOS_COR foreign key (COR_ID) references COR (COR_ID);
alter table PRODUTOS
  add constraint FK_PRODUTOS_TAMANHO foreign key (TAMANHO_ID) references TAMANHO (TAMANHO_ID);
alter table PRODUTOS
  add constraint FK_PRODUTOS_MODELO foreign key (MODELO_ID) references MODELO (MODELO_ID);

create index IX_PRODUTOS_A on PRODUTOS (DESCRICAO);


Este select, à princípio, seria o mais otimizado possível:
select 
  P.PRODUTO_ID, P.DESCRICAO, P.REF_FORNECEDOR, 
  C.COR, 
  T.TAMANHO, 
  M.MODELO
from 
  PRODUTOS P 
left join 
  COR C on (P.COR_ID = C.COR_ID)
left join 
  TAMANHO T on (P.TAMANHO_ID = T.TAMANHO_ID)
left join 
  MODELO M on (P.MODELO_ID = M.MODELO_ID)
where 
  P.DESCRICAO starting with (´C´)
order by
  P.DESCRICAO


PLAN SORT (JOIN (JOIN (JOIN (P INDEX (IX_PRODUTOS_A),C INDEX (PK_COR)),T INDEX (PK_TAMANHO)),M INDEX (PK_MODELO)))


Espero ter ajudado...
T+


Responder

Gostei + 0

05/10/2004

Debug

Vinicius, cara valeu mesmo, ficou absurdamente rapido.
As Pks e os index, das tabelas estavam igual ao que vc criou, mas os joins estavam errados.
Agora entendi como fazer um join com varias tabelas.
Muito obrigado. Valeuuuuuuuuuuuuuuuuuu.


Responder

Gostei + 0

05/10/2004

Vinicius2k

Blz. :wink:
Quando pensar uma query, aplique-a, primeiramente, num front-end que de suporte à analise ou pelo menos visualização do PLAN adotado pelo servidor (IBExpert, IBConsole, Etc), veja a informação do PLAN e nunca permita que a opção NATURAL apareca... seus índices (sejam índices normais, PKs ou FKs) sempre devem ser usados...

Se vc observar o resultado do meu PLAN (último quote), o servidor encontrou índices suficientes para executar a query, foi isso que a deixou rápida...

Para vc compreender melhor os Joins veja a respos do colega afarias:
http://delphiforum.icft.com.br/forum/viewtopic.php?t=49308

E se, dentro da cláusula ON, vc realizar mais de uma comparação, estas comparações devem conter as mesmas colunas do índice, e se estiver trabalhando com tipos de dados diferentes no índice, dê preferencia à esta sequência: [b:87ef0f9cbb]Smallint -> Integer -> Date -> String[/b:87ef0f9cbb].
E no Join :
1. T1.Smallint = T2.Smallint
2. T1.Integer = T2.Integer
3. T1.Date = T2.Date
4. T1.String = T2.String

T+


Responder

Gostei + 0

05/10/2004

Amjorge

Um a idéia interessante a ser testada é uma que filtre o máximo possível de registros usando uma operação mais rápida que like, como por exemplo =, <, ,>= e depois então, com os resgistros devidamente filtrados, fica mais fácil usar o like.

poderia usar ao invés de:

WHERE P.DESCRICAO starting with (´C´)

este:

WHERE
P.DESCRICAO >= ´C´
AND P.DESCRICAO < ´D´
AND P.DESCRICAO starting with (´C´)

Se vc. puder, por favor, dê uma testada e depois nos informe. Obrigado.


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar