none
Inner join campos no clave RRS feed

  • Pregunta

  • Hola a todos: 

    Tengo problemas con una consulta . . tarda demasiado mas de 7 segundos la he revisado varias veces y me quedo con la duda de la relacion que tienen entre dos campos que no son pk 

     

    el campo que contiene la llave foranea hace referencia a un campo que no es primary key 

    a esto se debe el problema?  . .por lo general he visto los inner join entre pk y fk sin embargo me gustaria tener sus opiniones al respecto

     

    de antemano muchas gracias

     

     

    martes, 5 de julio de 2011 20:40

Respuestas

  • Con permiso del resto de compañeros.

    El 66 % del coste de tu consulta es simplemente recoerrer tu tabla contrato completa, Crea un índice que contenta las columnas Cod y objt en principio solamente ese. 

    Los joins se hacen de la forma más adecuada, con merge join,  En cualquier caso probablemente un índice en la tabla supervisor por los campos cod_emp ,contract o al reves contract,cod_emp (crea ambos,mira cual usa el plan de ejecución y borras el otro). mejoren tu consulta.

     

    Saludos

    Miguel Egea


    Comparte lo que sepas, aprende lo que no sepas (FGG) http://www.portalsql.com
    miércoles, 6 de julio de 2011 15:06
    Moderador

Todas las respuestas

  • Una restriccion de clave foranea puede referenciar la clave primaria, grupo de columnas que participan en una restriccion de unicidad (unique constraint), o que forman parte de un indice unico.

    No puedo darte sugesrencia o explicacion alguna sobre le que te esta sucediendo, ya que no tenemos conocimientos de la estructura de las tablas, inclyendo rstricciones e indices. Asi como informacion sobre el plan de ejecucion.

     


    AMB

    Some guidelines for posting questions...

    martes, 5 de julio de 2011 21:10
  • Independientemente de que uses pk, fk o no las uses ... Ten presente que usamos operadores JOIN para mejorar el rendimiento de las consultas frente a realizar una subconsulta de una consulta...

     La ventaja de crear un operador JOIN consiste en que puede evaluar tablas en un orden distinto del definido por la consulta.

     La ventaja de usar una subconsulta es que normalmente no es necesario explorar todas las filas de la subconsulta para evaluar la expresión de ésta.

    Por ejemplo, una subconsulta EXISTS puede devolver TRUE al ver la primera fila que coincida...


    Espero me entiendas.
    No sé, si preguntas por algo mas concreto, en tal caso comentanoslo.


     Norman M. Pardell 

    ||Microsoft Certified IT Professional|| Database Administrator. Database Developer. SQL Server 2008


    martes, 5 de julio de 2011 21:15
  • Hola.

    No hay ninguna relación entre el rendimiento de un inner join y el hecho de que cruces claves primarias, foráneas o naturales. Lo importante es la indexación que tengas y de la consulta. ¿Puedes pasarnos la sentencia? A lo mejor podemos sugerirte la creación de un índice o  la reescritura de la sentencia.


    Alberto López Grande
    SQL Server MVP
    Visita mi blog en http://qwalgrande.blogspot.es/ Sígueme en twitter en http://twitter.com/qwalgrande

    martes, 5 de julio de 2011 21:16
    Moderador
  • Hola Norman, no se puede generalizar esta apreciación. No es ni cierta ni falsa, pero no tiene fundamento. Generalmente el optimizador de consultas usa planes de ejecución identicos en consultas resueltas con join o con exist, y el optimizador resuelve el orden de evaluación de tablas según el plan que elije. 

    En todo caso, las respuestas de norman y de alberto me parecen lo más adecuadas. nada que ver que la consulta se haga por la pk o por cualquier otra cosa, lo que importa es la consulta y la indexación para resolverla, o la forma de reescribirla para que rinda mejor.


    Comparte lo que sepas, aprende lo que no sepas (FGG) http://www.portalsql.com
    martes, 5 de julio de 2011 21:40
    Moderador
  • Generalilzar no es una certeza.


     Norman M. Pardell 

    ||Microsoft Certified IT Professional|| Database Administrator. Database Developer. SQL Server 2008

    martes, 5 de julio de 2011 22:05
  •  

    SELECT
    
    	CONTRAT.COD, CONTRAT.OBJTO, 
    
    	( 
    
    SELECT TOP 1
    
    	TERCERO.COD
    
    FROM 
    
    	SUPERVISOR INNER JOIN TERCERO 
    
    ON 
    
    	SUPERVISOR.COD_EMP = TERCERO.COD_EMP 
    
    WHERE
    
    	SUPERVISOR.CONTRAT= CONTRAT.COD
    
    ) AS SUPERVISOR
    
    FROM 
    
    CONTRAT
    
    
    

     

    TERCERO.COD_EMP aparece como Unique Index pero tiene valores null

    TERCERO.COD es el campo Primary Key

    SUPERVISOR.COD_EMP es la foreign key que hace referencia a  COD_EMP de tercero . . especialmente

    En el plan de ejecucion me arroja un full scan y no toma el pk de tercero

    El campo ID_FNCNRIO en la tabla SUPERVISOR tiene repetido por ej el id_fncnrio 1  por lo que esta columna no es unique index


    • Editado Juanweb martes, 5 de julio de 2011 22:59 Anadir
    martes, 5 de julio de 2011 22:46
  • Juanweb,

    Sin intenciones de ofender, pero parece que tratas de evitar nuestra ayuda por todo lo alto.

    Para evitar el dime que te dire, es preferible y de mucha ayuda, que postees la estructura de las tablas en cuestion, incluyendo restricciones e indices. Asi como el plan de ejecucion, y de ser posible una breve descripcion de lo que tratas de hacer con este query.

    Como buena practica, es recomendable tener un indice que soporte la restriccion de clave foranea. Por ejemplo, si tienes una restriccion de clave foranea en la tabla [supervisor], usando la columna [cod_emp] para referenciar la tabla [tercero] y columna [cod_emp], entonces es recomendable tener un indice en la tabla [supervisor] por la columna [cod_emp].

    Es dificil saber lo que tratas de hacer solo con leer el query. Al parecer tratas de traer, para cada fila en la tabla [contract], cualquier [cod_emp] de la tabla [tercero] siempre y cuando esta tenga una fila que mache en la tabla [supervisor] y que esta a su vez tenga un fila que mache con la tabla [contrat].

    Que tal si pruebas:

    select
        C.cod,
        C.objto,
        max_tercero_cod
    from
        contract as C
        inner join
        (
        select
            S.contract,
            max(T.cod) as max_tercero_cod
        from
            supervisor as S
            inner join
            tercero as T
            on S.cod_emp = T.cod_emp
        group by
            S.contract
        ) as R
        on C.cod = R.contract;
    GO

     


    AMB

    Some guidelines for posting questions...

    miércoles, 6 de julio de 2011 0:28
  • ejecutando su instruccion obtengo el siguiente plan de ejecucion

     

    la ejecucion de una subconsulta ralentiza la consulta? como lo hago en la instruccion que puse

    ia cree el indice en la columna ID_FNCNRIO del supervisor 

    hay un table scan sobre la tabla supervisor

    el join entonces se puede hacer entre el campo de la tabla supervisor y la columna de id_fncnrio  de tercero . . esta columna no es pk la pk es terccod

    miércoles, 6 de julio de 2011 14:12
  • Con permiso del resto de compañeros.

    El 66 % del coste de tu consulta es simplemente recoerrer tu tabla contrato completa, Crea un índice que contenta las columnas Cod y objt en principio solamente ese. 

    Los joins se hacen de la forma más adecuada, con merge join,  En cualquier caso probablemente un índice en la tabla supervisor por los campos cod_emp ,contract o al reves contract,cod_emp (crea ambos,mira cual usa el plan de ejecución y borras el otro). mejoren tu consulta.

     

    Saludos

    Miguel Egea


    Comparte lo que sepas, aprende lo que no sepas (FGG) http://www.portalsql.com
    miércoles, 6 de julio de 2011 15:06
    Moderador