none
vistas en SQL Server. Eficiencia

    Question

  • Hola:

    Me gustaría saber si la eficiencia de una vista SQL es parecida a si se usan las tablas directamente.

    Tengo que realizar una consulta un tanto extraña que combina 7 tablas entre sí, teniendo también en cuenta campos relacionados entre sí dentro de una misma tabla, y la única forma de la que he conseguido hacerlo requiere crear una vista uniendo los datos de las 7 tablas y de ahi, con otra consulta obtener las relaciones de esos campos dentro de la propia tabla. El problema es que si quiero filtrar los datos para no obtener todos los resultados, lo haría sobre la vista, es decir, primero se construye la vista con TODOS los datos y después en otra consulta a la vista es donde se filtra.

    Pongo las dos consultas:

    Primero construyo la vista:

    SELECT   dbo.Circuitos.Numero_Circuito, dbo.Proveedores.Nombre_Proveedor, dbo.Tournes.Numero_Tourne, dbo.Dias_Tourne.Hora_P_Llegada, 
               dbo.Dias_Tourne.Hora_P_CoD, dbo.Dias_Tourne.Hora_P_Salida, dbo.Descr_Dias.Nombre_Dia, dbo.Tipos_Tourne.Nombre_Tipo, 
               dbo.Lugares_DC.Nombre_Lugar, dbo.Tournes.Id_Tourne, dbo.Dias_Tourne.Id_Descr_Dia, dbo.Tournes.Id_Tipo_Tourne, dbo.Tournes.Id_Tourne_Rel, 
               dbo.Dias_Tourne.Id_Dia_Tourne
    FROM     dbo.Tournes INNER JOIN
               dbo.Circuitos ON dbo.Tournes.Id_Circuito = dbo.Circuitos.Id_Circuito INNER JOIN
               dbo.Dias_Tourne ON dbo.Tournes.Id_Tourne = dbo.Dias_Tourne.Id_Tourne INNER JOIN
               dbo.Lugares_DC ON dbo.Tournes.Id_Lugar_DC = dbo.Lugares_DC.Id_Lugar_DC INNER JOIN
               dbo.Proveedores ON dbo.Circuitos.Id_Proveedor = dbo.Proveedores.Id_Proveedor INNER JOIN
               dbo.Tipos_Tourne ON dbo.Tournes.Id_Tipo_Tourne = dbo.Tipos_Tourne.Id_Tipo_Tourne INNER JOIN
               dbo.Descr_Dias ON dbo.Dias_Tourne.Id_Descr_Dia = dbo.Descr_Dias.Id_Descr_Dia
    WHERE   (dbo.Circuitos.Activo = 1) AND (dbo.Tournes.Activo = 1) AND (dbo.Dias_Tourne.Activo = 1)
    

    Y una vez que tengo la vista aqui construyo la consulta (serían varias consultas, teniendo en cuenta las condiciones) que la hago directamente, ya que no uso procedimientos almacenados:

    SELECT   dbo.vT.Numero_Circuito AS CIRCUITO, dbo.vT.Id_Tourne AS Id_T_D, dbo.vT.Id_Dia_Tourne, vTRel.Id_Tourne AS Id_T_C, 
               vTRel.Id_Dia_Tourne AS Id_DIA_Rel
    FROM     dbo.vT LEFT OUTER JOIN
               dbo.vT AS vTRel ON dbo.vT.Id_Tourne = vTRel.Id_Tourne_Rel
    WHERE   (dbo.vT.Id_Tipo_Tourne = 1) AND (vTRel.Id_Tipo_Tourne = 2) AND (dbo.vT.Id_Descr_Dia = vTRel.Id_Descr_Dia)
    UNION
    SELECT   dbo.vT.Numero_Circuito AS CIRCUITO, dbo.vT.Id_Tourne AS Id_T_D, dbo.vT.Id_Dia_Tourne, vTRel.Id_Tourne AS Id_T_C, 
               vTRel.Id_Dia_Tourne AS Id_DIA_Rel
    FROM     dbo.vT LEFT OUTER JOIN
               dbo.vT AS vTRel ON dbo.vT.Id_Tourne = vTRel.Id_Tourne_Rel
    WHERE   (dbo.vT.Id_Tipo_Tourne = 1) AND (dbo.vT.Id_Tourne_Rel = 0)
    UNION
    SELECT   dbo.vT.Numero_Circuito AS CIRCUITO, vTRel.Id_Tourne AS Id_T_D, vTRel.Id_Dia_Tourne, dbo.vT.Id_Tourne AS Id_T_C, 
               dbo.vT.Id_Dia_Tourne AS Id_DIA_Rel
    FROM     dbo.vT LEFT OUTER JOIN
               dbo.vT AS vTRel ON dbo.vT.Id_Tourne = vTRel.Id_Tourne_Rel
    WHERE   (dbo.vT.Id_Tipo_Tourne = 1) AND (dbo.vT.Id_Tourne_Rel = 0)
    
    El LEFT OUTER JOIN es debido a que en una misma tabla tengo las entradas y salidas, y como resultado quiero obtener una tabla que muestre en una columna las entradas y en otra las salidas (o nulo en esa columna si alguna no existe)

     

    Monday, November 22, 2010 5:57 PM

Answers

  • Si, yo te recomiendo hacer funciones de funciones o vistas de vistas.

    Mientras más sencillo sea tu código será más fácil mantener.

    Cuando tengo un código de más de 40 líneas (tu caso), lo que trato es partirlo en subfunciones pequeñas para que sea más fácil leerlo.

    En tu caso estas haciendo select de vistas.

    Yo haría una vista de la vista o función de la función y luego usar UNIONs.


    MVP MCT MCTS Daniel Calbimonte

    http://elpaladintecnologico.blogspot.com
    • Proposed as answer by dani671MVP Thursday, November 25, 2010 7:58 PM
    • Marked as answer by Alvaro Matabuena Friday, November 26, 2010 11:19 AM
    Tuesday, November 23, 2010 7:25 PM

All replies

  • No esta mal usar vistas, pero yo te recomiendo ver  Funciones con tablas que son muy flexibles para las consultas que tu haces:

    http://msdn.microsoft.com/es-es/library/ms186755(v=SQL.100).aspx

    Fijate el ejemplo B

    B. Crear una función insertada con valores de tabla

     


    MVP MCT MCTS Daniel Calbimonte

    http://elpaladintecnologico.blogspot.com
    Monday, November 22, 2010 8:04 PM
  • Hola:

    Por lo que veo la idea es muy parecida, usar funciones hace lo mismo que las vistas pero además puedes enviarle parámetros no? El objetivo de esta oconsulta es obtener unos datos para hacer un reporte, en base a un historico, por lo que habrá muchos datos. A la hora de filtrar se puede filtrar por 4 o 5 campos, por lo que si se filtra en un principio se reduce mucho el número de registros y por tanto el tiempo.

    Como podría juntar las dos instrucciones SQL que he comentado arriba en una función?

     

    Monday, November 22, 2010 8:15 PM
  • Las funciones aceptan select union como cualquier tabla o vista.

    Puedes usar where, order by como a cualquier tabla.

    solo que usas paréntesis para parámetros:

    select  * from dbo.funcion1(1)

    union

    select  * from dbo.funcion2(1)

     


    MVP MCT MCTS Daniel Calbimonte

    http://elpaladintecnologico.blogspot.com
    Monday, November 22, 2010 8:31 PM
  • Hola.

    Las vistas no te aportan nada en el desempeño, te aportan, si acaso en la eficiencia a la hora de desarrollar tu aplicación. Si buscan ganar en rendimiento, usa procedimientos almacenados (dices que no los usas, pero no dices por qué).

    Las funciones de tipo tabla pueden ser una variante a utilizar, pero te recomendaría los procedimientos almacenados en cualquier caso.

     


    Alberto López Grande
    SQL Server MVP
    Visita mi blog en http://qwalgrande.blogspot.es/

    Monday, November 22, 2010 8:35 PM
  • qwalgrande, si ve su código, se darás cuenta que en este caso necesita funciones. Los procedimientos almacenados no son tan versátiles cuando hay que hacer uniones.

    MVP MCT MCTS Daniel Calbimonte

    http://elpaladintecnologico.blogspot.com
    • Edited by dani671MVP Tuesday, November 23, 2010 12:28 AM
    Monday, November 22, 2010 8:46 PM
  • Hola.

    Con el debido respeto, los procedimientos almacenados son igual de versátiles cuando hay que hacer uniones y cuando no hay que hacerlas (opino), no entiendo la diferencia por ese criterio. Pero es más, si en lugar de tratar de obtener toda la consulta de una tacada fuera filtrando (sin usar ni vistas ni funciones de tipo tabla), el rendimiento final sería mucho mejor aún, ya que sólo se usarían las tablas precisas en cada parte. Lo que se encapsule en la vista o en la función acabaría conduciendo a pasar por tablas que no se necesitan en todas las pasadas. Por supuesto, la programación sería menos costosa si se usan vistas o funciones.

    Y no hay que olvidar la mejor razón para usar procedimientos almacenados, y es que éstos quedan compilados y luego ya sólo resta reusar ese plan de ejecución. Tampoco hay nada que impida usar funciones dentro de un procedimiento almacenado, es otra opción más.


    Alberto López Grande
    SQL Server MVP
    Visita mi blog en http://qwalgrande.blogspot.es/

    Monday, November 22, 2010 11:12 PM
  • Gracias,

    Es verdad lo que dices, pero por ejemplo yo no se como unir los resultados de 2 procedimientos almacenados.

    Con funciones, es facil usar UNION y unir resultados.

    Como harías eso con procedimientos almacenados ?.  Si puedes hacerlo, te creo que los procedimientos almacenados son igual de versátiles que las funciones para este tipo de consultas.

     


    MVP MCT MCTS Daniel Calbimonte

    http://elpaladintecnologico.blogspot.com
    Monday, November 22, 2010 11:43 PM
  • Hola!

    La de no usar procedimientos almacenados simplemente ha sido una decisión de diseño a la hora de implementar la aplicación. Es una aplicacion de escritorio que estoy programando en c#. Ahora estoy con los reportes, y a la hora de filtrar los datos que quiero elegir formo la consulta (la parte del where) de forma dinámica, ya que sino tendría que tener tantas consultas como tipos de filtros.

    Con esta consulta que he propuesto querria hacerlo de forma dinámica también, aunque con lo complicada que es no sé si será posible. La ventaja de las vistas (y ahora que las conozco tambien las funciones) es que me permite utilizarlas para despues formar la consulta dinamica. Si toda la consulta anterior la encapsulo en una vista, me vale con hacer Select * from vistaXXX WHERE....

    Sé que no es lo optimo, y aunque en las consultas sencillas se hacerlo de otra manera en estas mas complejas ya no (sacar esa me ha llevado muchos intentos y eso que me faltan de incluir campos y otras dos o tres tablas mas).

    Tuesday, November 23, 2010 1:36 AM
  • Si, yo te recomiendo hacer funciones de funciones o vistas de vistas.

    Mientras más sencillo sea tu código será más fácil mantener.

    Cuando tengo un código de más de 40 líneas (tu caso), lo que trato es partirlo en subfunciones pequeñas para que sea más fácil leerlo.

    En tu caso estas haciendo select de vistas.

    Yo haría una vista de la vista o función de la función y luego usar UNIONs.


    MVP MCT MCTS Daniel Calbimonte

    http://elpaladintecnologico.blogspot.com
    • Proposed as answer by dani671MVP Thursday, November 25, 2010 7:58 PM
    • Marked as answer by Alvaro Matabuena Friday, November 26, 2010 11:19 AM
    Tuesday, November 23, 2010 7:25 PM
  • Hola.

    Si la limitación está en el desarrollo, lo primero es que funcione, aunque para el rendimiento quede perjudicado. Yo al menos no puedo recomendarte usar vistas, menos aún vistas que llamen a otras vistas, lo mismo con las funciones, pero entiendo que si vas a tener que invertir un tiempo enorme en construir las consultas, es normal que optes por ello.

    Hay que buscar un equilibrio, pero sí es bueno que seas consciente de que no es la mejor opción para el rendimiento.

    Daniel, con respecto a unir dos consultas en un procedimiento, tan sencillo como:

    create proc Ejemplo @pFiltro int as
    
    select campo1, campo2 from TablaA where filtro = @pFiltro
    union
    select campo1, campo2 from TablaB where filtro = @pFiltro
    
    return 0
    

    Es decir igual de fácil o de difícil que sin ellos. No conozco nada que rinda mejor en una vista o en una función que en un procedimiento almacenado (si hablamos de vistas que no estén indexadas, claro). En el mejor de los casos, va igual. 

    En cualquier caso yo iba más por la línea de que en un procedimiento almacenado puedes ir parcelando la obtención de la información, en contraposición a generar una consulta enorme que para el engine es siempre un problema. Casi siempre es mejor hacer tres consultas simples que una compleja. Y en caso de duda, se estudia y compara el plan de ejecución y el número de lecturas.


    Alberto López Grande
    SQL Server MVP
    Visita mi blog en http://qwalgrande.blogspot.es/

    Tuesday, November 23, 2010 8:09 PM
  • Hola

    ¿Has podido solucionar tu problema?

    Saludos

    Eduardo Portescheller
    Thursday, November 25, 2010 1:36 PM
  • Si, al final lo he realizado con dos funciones de tabla, donde una llama a la otra y en ambas se pasan los parámetros, asi que el filtrado le hace directamente sobre la tabla. Quedan expresiones un tanto complejas pero el rendimiento para que no es malo, pues las busquedas y filtrados son todos con claves primarias.
    Thursday, November 25, 2010 5:35 PM