2

我正在努力帮助我的高级用户更多地访问我们的数据,这样我就不必每天 25 次中断我的工作(玩 Pac-Man)来编写 Ad Hoc Queries 等。

我正在尝试使用数据源视图、数据模型和报表生成器 2 和 3 来允许他们访问已清理的数据,他们可以在其中安全地进行自己的基本分析。我想创建涵盖业务流程的通用报告模型,而不是为他们需要的每个临时报告创建一个特定的报告模型。

我必须使用命名查询创建数据源视图 (DSV),因为源数据库缺少主键,但在 identity_columns 上有唯一的聚集索引。

这是我的问题。当我使用这样一个相对简单的查询时:

SELECT SOM.FSONO AS SalesNo
     , SOM.FCUSTNO AS CustNo
     ,SLC.fcompany as CustName
     , SOM.FCUSTPONO AS CustPONo
     , SOM.fsoldby AS SalesPerson
     , SOR.FENUMBEr AS ItemNo
     , SOR.finumber AS IntItemNo
     , SOR.frelease AS Rels
     , SOI.fprodcl AS ProdClass
     , SOI.fgroup AS GroupCode
     , rtrim(SOR.FPARTNO) AS PartNo
     , SOR.fpartrev AS PartRev
     , cast(SOI.fdesc AS VARCHAR(20)) AS PartDescription
     ,SOM.forderdate as OrderDate
     ,SOR.fduedate as DueDate
     , SOR.FORDERQTY AS QtyOrd
     , SOR.FUNETPRICE AS NetUnitPrice
     , (SOR.FORDERQTY * SOR.funetprice) AS NetAmountOrdered
FROM  slcdpm SLC inner join 
somast SOM on SLC.fcustno = SOM.fcustno
     LEFT OUTER JOIN soitem SOI
       ON (SOM.fsono = SOI.fsono)
     LEFT OUTER JOIN sorels SOR
       ON (SOI.fsono = SOR.fsono)     
AND       (SOI.finumber = SOR.finumber)

假设用户使用 Report Builder 3 中的报表模型,并且只为其数据集请求 SalesNo、PartNo、PartRev、OrderDate 和 TotalNetAmount。

为提取该数据而生成的 SQL 是:

SET DATEFIRST 7
SELECT
    CAST(1 AS BIT) [c0_is_agg],
    CAST(1 AS BIT) [c1_is_agg],
    CAST(1 AS BIT) [c2_is_agg],
    CAST(1 AS BIT) [c3_is_agg],
    4 [agg_row_count],
    [CustomerSales].[TotalNetAmountOrdered] [TotalNetAmountOrdered],
    [CustomerSales].[SalesNo] [SalesNo],
    [CustomerSales].[PartNo] [PartNo],
    [CustomerSales].[PartRev] [PartRev],
    [CustomerSales].[OrderDate] [OrderDate]
FROM
    (
        SELECT
            SUM([CustomerSales].[NetAmountOrdered]) [TotalNetAmountOrdered],
            [CustomerSales].[SalesNo] [SalesNo],
            [CustomerSales].[PartNo] [PartNo],
            [CustomerSales].[PartRev] [PartRev],
            [CustomerSales].[OrderDate] [OrderDate]
        FROM
            (
                SELECT        SOM.fsono AS SalesNo, SOM.fcustno AS CustNo, SLC.fcompany AS CustName, SOM.fcustpono AS CustPONo, SOM.fsoldby AS SalesPerson, 
                         SOR.fenumber AS ItemNo, SOR.finumber AS IntItemNo, SOR.frelease AS Rels, SOI.fprodcl AS ProdClass, SOI.fgroup AS GroupCode, RTRIM(SOR.fpartno) AS PartNo, 
                         SOR.fpartrev AS PartRev, CAST(SOI.fdesc AS VARCHAR(20)) AS PartDescription, SOM.forderdate AS OrderDate, SOR.fduedate AS DueDate, SOR.forderqty AS QtyOrd, 
                         SOR.funetprice AS NetUnitPrice, SOR.forderqty * SOR.funetprice AS NetAmountOrdered
FROM            slcdpm AS SLC INNER JOIN
                         somast AS SOM ON SLC.fcustno = SOM.fcustno LEFT OUTER JOIN
                         soitem AS SOI ON SOM.fsono = SOI.fsono LEFT OUTER JOIN
                         sorels AS SOR ON SOI.fsono = SOR.fsono AND SOI.finumber = SOR.finumber
            ) [CustomerSales]
        WHERE
            CAST(1 AS BIT) = 1
        GROUP BY
            [CustomerSales].[SalesNo], [CustomerSales].[PartNo], [CustomerSales].[PartRev], [CustomerSales].[OrderDate]
    ) [CustomerSales]
ORDER BY
    [SalesNo], [PartNo], [PartRev], [OrderDate]

我本来希望只提取用户在报告中请求的字段,而不是 DSV 中的每个字段。此外,如果创建了约束数据的参数,例如 OrderDate 的开始日期和结束日期,则无论如何都会返回完整的数据集。

我在这里做错了吗?

有没有更好的方法来解决这个问题?

其他管理员在使用报表模型时是否发现自己存在性能问题?

4

1 回答 1

4

处理报表模型时有时会出现性能问题。这是报告模型不适用于向所有用户推出以替换所有报告的原因之一。报表模型背后的语义查询引擎生成的查询是不可调整的,而且通常完全不是您自己编写它们的方式。

该引擎本质上将命名查询视为一个视图,并将其扩展为基础查询,就像它是一个视图一样。在构建直接覆盖数据库的模型时,这通常是一个问题。

从我的角度来看,理想的情况是拥有一个单独的数据库(可能是数据仓库),最好放在单独的服务器上。这个 dw 将被展平,以便您可以优化它的读取性能。然后,您可以直接在数据源视图中使用这些表,并且模型背后的语义查询引擎应该能够进行更好的查询。

由于经济或其他限制,这种理想通常是不可能的。您是否可以尝试将基本表中的 ETL 工作或多或少地转换为一组新的表,您可以针对报告进行优化以支持您的模型?

于 2010-09-03T17:33:01.717 回答