【发布时间】:2013-02-05 07:05:56
【问题描述】:
我有一个非常复杂的查询,但我应用了一些索引,现在它在不到 1 秒的时间内运行得非常顺利。查询的结构是这样的(我发现没有必要发布完整的查询,我稍后会证明 - 错误不在查询本身):
DECLARE @period varchar(6);
SET @period = '201302';
DECLARE @day datetime;
SET @day = dba.fnu_firstdate(@period);//returns 2013-02-01
SELECT
user_id,
(SELECT CAST(MAX(c1) AS varchar) FROM table t WHERE t.user_id = table.user_id AND when = DATEADD(day, 0, @day)) Day01,
...
(SELECT CAST(MAX(c1) AS varchar) FROM table t WHERE t.user_id = table.user_id AND when = DATEADD(day, 30, @day)) Day31
FROM
table
是的,如果我执行此查询,大约需要 1 秒才能完成,这对我来说非常好。但是,如您所见,我需要为其提供参数。因此,我将其更改为表值函数,以便可以轻松地从中进行选择查询:
CREATE FUNCTION fnu_data(@period varchar(6))
RETURNS @results TABLE
(
id int,
Day01 varchar(10) null,
...
Day31 varchar(10) null
)
AS
BEGIN
DECLARE @day datetime;
SET @day = dba.fnu_firstdate(@period);
INSERT INTO @results
(
id,
Day01,
...
Day31
)
SELECT
SELECT
user_id,
(SELECT CAST(MAX(c1) AS varchar) FROM table t WHERE t.user_id = table.user_id AND when = DATEADD(day, 0, @day)) Day01,
...
(SELECT CAST(MAX(c1) AS varchar) FROM table t WHERE t.user_id = table.user_id AND when = DATEADD(day, 30, @day)) Day31
FROM
table
RETURN
当我这样做的时候
SELECT * FROM dba.fnu_data('201302')
需要 6 秒,这太长了。在同事的建议下,我尝试在 id 上添加主索引并将每个子选择替换为连接,但它将执行查询的时间延长到 8 秒。 (PS 查询返回约 3200 行)。
在我看来,罪魁祸首是插入,但我不知道如何才能摆脱它。
我可以做些什么来改进我的查询?
【问题讨论】:
-
你能不能给我更多的细节(也许把它放在答案中?)?我不明白如何将函数参数(我返回的表)移到函数之外?
-
也许仅将
INSERT ... SELECT的计划与底层SELECT的计划进行比较就可以揭示一些东西。无论如何,您的 SELECT 语句对我来说显然不是最理想的。 -
我并不声称我的查询是完美的,但它执行得相当快,至少对我来说足够快。我刚刚尝试创建一个临时表并插入我在函数中插入的方式,它再次运行得非常好(1秒)!现在我完全不知道问题出在哪里。
标签: sql-server sql-server-2008-r2 user-defined-functions