【问题标题】:SQL Server WITH very slowSQL Server 速度很慢
【发布时间】:2012-06-25 01:57:30
【问题描述】:

我正在使用 SQL Server 2008 并尝试运行:

WITH results (Row, code, p_name, phone, intake_date, shipped_status, shipped_date,
 event_status, intake_status, slsperson, referral_source, dr )
AS
( 
    SELECT ROW_NUMBER() OVER (ORDER BY intake_date ASC)AS Row, code, p_name, phone, 
    intake_date, shipped_status, shipped_date, event_status, intake_status, slsperson, 
    referral_source, dr
    FROM db.schema.sales_referral_list('2012-05-1', '2012-06-1', 'CXJ7')
)
SELECT Row, code as p_id, p_name, phone, intake_status, intake_date, shipped_status,
 shipped_date, event_status, slsperson, referral_source, dr 
FROM results 
WHERE Row BETWEEN 0 AND 50 ORDER BY Row

当我在没有 With AS 语句(即仅内部 select 语句)的情况下运行它时,它会在大约 1 秒内执行。当我使用用于在网站上进行分页的 With 语句时,执行时间超过 15 秒。我可以做一些优化来提高这个语句的性能吗? (sales_referral_list是一个表值函数,需要3个参数。它一直在1秒内运行,所以我比较确定不是问题)。感谢您提供的任何帮助。

==========更新=========

表值函数如下: 表值函数如下:

    (   
-- Add the parameters for the function here
@START DATE,
@END DATE,
@SLSCODE VARCHAR(4)


 )
RETURNS TABLE 
AS
RETURN 
(
-- Add the SELECT statement with parameter references here
    SELECT 
    A.code,
    B.last+', '+B.first AS p_name,
    B.phoneday AS Phone,
    B.slcode,
    B.regdate as intake_date,
    CASE
        WHEN CAST(C.newdate AS  DATE) is not null THEN 'SHIPPED'
        WHEN B.udef1='03' THEN 'NON-SERV'
        ELSE 'NOT SHIPPED'
    END as shipped_status,
    CASE
        WHEN CAST(C.newdate AS  DATE)='1900-01-01' THEN ''
        ELSE CAST(C.newdate AS  DATE)
    END as shipped_date,
    CASE
        WHEN E.status='1' THEN 'ACTIVE'
        WHEN E.status='2' THEN 'COMPLETE'
        WHEN E.status='0' THEN 'DELETED'
        ELSE 'NO EVENT'
    END event_status,
    F.file_status as intake_status,
    D.employee as slsperson,
    B.rfname as referral_source,
    B.dcname as doctor
FROM event.dbo.distinct_account() a
LEFT OUTER JOIN event.dbo.patient_dg() B ON A.code=B.code
LEFT OUTER JOIN event.dbo.newdate() c on a.code=c.ACCOUNT
LEFT OUTER JOIN event.dbo.employee D ON B.slname=D.employee
LEFT OUTER JOIN(
    SELECT
        id,
        patient_id,
        status
    FROM event.dbo.event A
    WHERE A.task_id IN ('WF','WT')
    group by id,patient_id,status
    ) E ON A.code=E.patient_id
LEFT OUTER  JOIN event.dbo.taskWF F ON E.id=F.event_id
    WHERE b.regdate>=@START
AND b.regdate<=@END
AND slcode=@SLSCODE
)

正常返回的结果介于 100 到 500 条记录之间。表值函数 patient_dg 大约有 60,000 条记录

【问题讨论】:

  • 返回了多少行?您的最终订单要求生成所有行。您可能会更快地看到内部查询的部分结果。
  • WITH 不是原因。它的运行时成本为零。原因在别处。
  • 这些语句被称为 Common Table Expressions (CTE),我同意 usr - 默认情况下,CTE 并不慢或坏 - 一定有严重错误与您的表设置和/或索引(或缺少)
  • @marc_s 一个叫其他几个的怎么样...
  • dbo.distinct_account() 这样的连接函数在我看来也很可疑。您似乎试图通过将一堆不同的查询塞进一堆函数来封装代码。这可能使您更容易使用外部查询,但它与优化器密切相关。我将开始尝试通过解开您创建的这个巢来提高性能。这将使优化器有更好的机会处理您拥有的实际数据和统计信息,而不是仅仅查看所有这些黑盒函数并耸耸肩。

标签: sql-server optimization common-table-expression with-statement


【解决方案1】:

您可以尝试将结果存储到临时表中(这已经以类似的方式隐式发生在您的查询中)。如果您可以保留会话从而保留#Results 临时表,那么您可以执行具有不同行范围的语句。填充 #Results 后会很快。

我忘了说,我猜到了字段的数据类型。您可能需要更改其中的一些。准确匹配类型也有助于提高性能。

CREATE TABLE #WholeResultSet
(
    Id INT NOT NULL PRIMARY KEY,
    [Row] INT NOT NULL,
    p_id INT NOT NULL,
    p_name VARCHAR(MAX) NOT NULL,
    phone VARCHAR(MAX) NOT NULL,
    intake_date DATETIME NOT NULL,
    shipped_status VARCHAR(MAX) NOT NULL,
    shipped_date DATETIME NOT NULL,
    event_status VARCHAR(MAX) NOT NULL,
    intake_status VARCHAR(MAX) NOT NULL,
    slsperson VARCHAR(MAX) NOT NULL,
    referral_source VARCHAR(MAX) NOT NULL,
    dr VARCHAR(MAX)  NOT NULL
) ;

INSERT INTO #WholeResultSet
(
    [Row], p_id, p_name, phone, intake_status, intake_date, shipped_status,
    shipped_date, event_status, slsperson, referral_source, dr 
)
SELECT
    ROW_NUMBER() OVER (ORDER BY intake_date ASC),
    code, p_name, phone,  intake_date, shipped_status,
    shipped_date, event_status, intake_status, slsperson, 
    referral_source, dr
FROM db.schema.sales_referral_list('2012-05-1', '2012-06-1', 'CXJ7') ;

SELECT * FROM #WholeResultSet WHERE Row BETWEEN 0 AND 50 ORDER BY Rownumber ;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-21
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    相关资源
    最近更新 更多