我正在使用医疗记录系统,该系统将数据存储在类似于电子表格的构造中 - 列标题中的日期/时间,每行第一列中的测量值(例如医生姓名,Rh,血型),和交叉单元格中的值。基于此构造的报告通常需要显示10个或更多这些度量。
出于报告目的,数据集需要为每位患者提供一行,测量的日期/时间以及每次测量的列。实质上,需要将构造旋转90度。
有一次,我实际上使用了SQL Server的PIVOT功能来做到这一点。由于各种原因,很明显这种方法不起作用。我决定使用内联视图(IV)将数据按到所需的格式。简化的查询类似于:
SELECT patient_id,
datetime,
m1.value AS physician_name,
m2.value AS blood_type,
m3.value AS rh
FROM patient_table
INNER JOIN ( complex query here
WHERE measure_id=1) m1...
INNER JOIN (complex query here
WHERE measure_id=2) m2...
LEFT OUTER JOIN (complex query here
WHERE measure_id=3) m3...
如您所见,在某些情况下,这些IV用于限制结果数据集(INNER JOIN),在其他情况下,它们不限制数据集(LEFT OUTER JOIN)。但是,除了measure_id的不同之外,“复杂查询”部分对于这些度量中的每一个都基本相同。虽然这种方法有效,但它会导致相当大的SQL语句,限制重用,并将查询暴露给错误。
我的想法是用内联表值UDF替换'复杂查询'和WHERE子句。这将简化查询,减少错误并增加代码重用。我唯一想到的问题就是表现。 UDF方法会导致性能显着下降吗?它可以改善问题吗?
感谢您的时间和考虑。
答案 0 :(得分:8)
正确定义的TVF不会引入任何问题。与视图或临时表和变量相比,您会发现许多关于性能问题的实施爆破TVF的声明。通常不被理解的是,TVF的行为与视图不同。将View定义放入原始查询中,然后优化器将按其认为合适的方式重新排列查询树(除非在索引视图上使用NOEXPAND子句)。 TVF具有不同的语义,有时,特别是在更新数据时,这导致TVF输出被假脱机haloween protection。它有助于标记函数WITH SCHEMABINDING
,请参阅Improving query plans with the SCHEMABINDING option on T-SQL UDFs。
理解确定性和精确功能的概念也很重要。虽然它们主要适用于标量值函数,但TVF也会受到影响。请参阅User-Defined Function Design Guidelines。
答案 1 :(得分:2)
由于您需要SQL字符串并且可能无法向系统添加视图或UDF,因此您可能希望使用WITH ... AS将复杂查询限制到一个位置(至少对于此语句。 )。
WITH complex(patientid, datetime, measure_id, value) AS
(Select... Complex Query)
SELECT patient_id
, datetime
, m1.value AS physician_name
, m2.value AS blood_type
, m3.value AS rh
FROM patient_table
INNER JOIN (Select ,,,, From complex WHERE measure_id=1) m1...
INNER JOIN (Select ,,,, From complex WHERE measure_id=2) m2...
LEFT OUTER JOIN (Select ,,,, From complex WHERE measure_id=3) m3...
答案 2 :(得分:1)
您还有第三种选择;传统的VIEW(假设您有一个加入的密钥)。理论上,三个选项之间不应存在性能差异,因为SQL Server应相应地评估和优化计划。现实情况是,有时这种情况不会像我们想的那样发生。
传统视图的好处是您可以将其作为索引视图,并为SQL Server提供另一个性能辅助;但是,你只需要测试一下。
答案 3 :(得分:1)
Sql Server 2005回答: 您可以使用temp / var表来减少内联视图。这些问题的性能问题是每次点击查询所需的临时插入,但如果结果集足够小,它们可以提供帮助。您可以在var表上使用主键,在临时表上使用主键/索引。除了普通的belive之外,我发现了一些文章,表明temp / var表都存储在temp db中。
UDF函数,我们发现在复杂查询中有多层udf但性能较差,但会保持可用性。 务必为指定的各种条件正确创建功能。将用于内连接的那些,以及将用于左连接的那些。
所以,总的来说。我们确实使用UDF,但是当我们发现性能下降时,我们移动查询以将UDF选择插入到temp / var表中并加入这些选择。
创建易于使用/维护的功能,并在需要的地方和时间应用性能增强。
编辑:
如果你需要为crystal运行它,并且你计划使用存储过程,是的,你可以在SP内部执行temp / var表中的sql语句。
如果您打算使用SP,请告诉我。然后,Sql也将使用给定的params缓存sp计划。
同样从之前的水晶实验中,要避免的事情是,可以在SP中进行分组,如果不需要,可以在SP中进行分页。和函数调用,如果这可以在服务器上处理。