Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF与表值函数性能_C#_Sql Server_Entity Framework - Fatal编程技术网

C# EF与表值函数性能

C# EF与表值函数性能,c#,sql-server,entity-framework,C#,Sql Server,Entity Framework,我们使用实体框架5.0.0,数据库优先的方法 我已经将两个内联表值函数ITVF导入我的EDMX,它返回IQueryable的。一旦返回,我们通常会对它们执行一些类型的操作,比如.Skip.Take 表演很好,至少有几个小时。不做任何事,至少我所知道的性能会在一夜之间下降 首先,执行查询大约需要500毫秒。一夜之间,性能下降到查询返回超时异常30-60秒的程度。这仅在从代码执行表函数时发生,如: IQueryable<MyResult> results = _c

我们使用实体框架5.0.0,数据库优先的方法

我已经将两个内联表值函数ITVF导入我的EDMX,它返回IQueryable的。一旦返回,我们通常会对它们执行一些类型的操作,比如.Skip.Take

表演很好,至少有几个小时。不做任何事,至少我所知道的性能会在一夜之间下降

首先,执行查询大约需要500毫秒。一夜之间,性能下降到查询返回超时异常30-60秒的程度。这仅在从代码执行表函数时发生,如:

IQueryable<MyResult> results =
            _context.MyTableFunction("searchforthis")
                .Skip(currentPagingPosition*20).Take(20);
在不做任何实际更改的情况下,即使从代码调用,它也会立即恢复到500毫秒的速度


我是否遗漏了一些明显的东西,有什么想法吗?

所以我尝试将选项重新编译添加到一个内联TVF中,但这似乎是不允许的。我发现解决这个问题的唯一方法是创建一个多语句函数,但它们有各自的缺点:

设置

创建函数

测试


参数嗅探。性能问题是否表现为应用程序的高cpu/内存使用率?可能与@LukeMcGregor重复-不,它可能发生在单个参数上。之所以会发生这种情况,是因为SQL Server为传递的第一个参数值编译了一个计划,然后缓存该计划并将其重新用于所有其他调用。如果该参数不具有代表性,比如说高度选择性,那么所使用的计划对于应用程序传递的其他可能的参数值来说可能是灾难性的。在OP运行ALTER函数时,会从缓存中删除错误的计划,因此它会修复它。您可以尝试使用。虽然你可能必须通过一个函数来完成这项工作,因为EF正在生成TSQL。所以我试图理解你的回答是什么意思,但我不清楚这是否解决了你的问题,你只是说它们有它们的缺点。我遇到了一个非常类似的问题,无法找到解决它的方法。@GabrielEspinoza我没有这个问题,我只是回答问题,不是我的问题!。多语句函数的缺点是,它们像游标一样逐行执行,因此在大型数据集上速度较慢。IMHO最好的选择是编写一个存储过程来返回您的数据集,并在SP的单个语句或整个SP上使用option RECOMPILE。如果我告诉您我在没有任何更改的情况下更改了内联函数,并且它达到了加速的目的,您会相信吗?-我想当参数嗅探在优化执行计划方面失败时,它真的是个麻烦。对它进行一些控制会很好,比如在SPs上
ALTER FUNCTION [dbo].[MyTableFunction]......
CREATE Table MyTest
(
    ID INT PRIMARY KEY Identity,
    SomeValue VARCHAR(MAX),
    UpdateDate Date
)
CREATE INDEX IDX_MyTest_UpdateDate
 ON MyTest(UpdateDate)


GO
 CREATE FUNCTION MyFunction(@FromDate date, @ToDate Date)
 RETURNS TABLE 
 AS
RETURN
(   
    SELECT SomeValue, UpdateDate
    FROM MyTest
    WHERE   UpdateDate >= @FromDate AND
            UpdateDate <=@ToDate
    -- OPTION (RECOMPILE) **** NOT ALLOWED HERE**
)
GO

CREATE FUNCTION MyFunction2(@FromDate date, @ToDate Date)
 RETURNS @retMyFunction TABLE
    (
        SomeValkue VARCHAR(MAX),
        UpdateDate Date
    ) 
 AS
BEGIN
    INSERT INTO @retMyFunction
    SELECT SomeValue, UpdateDate
    FROM MyTest
    WHERE   UpdateDate >= @FromDate AND
            UpdateDate <=@ToDate
    OPTION (RECOMPILE);

    RETURN;
END
GO
 INSERT INTO MyTest (SomeValue, UpdateDate)
 SELECT CAST(X.n * Y.n * z.n AS VARCHAR(Max)), DATEADD(D, ROW_NUMBER() OVER (ORDER BY X.n), '2010-01-01')
 FROM (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)) X(n)
 CROSS APPLY (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)) Y(n)
 CROSS APPLY (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)) Z(n)
-- Index Scan
SELECT * FROM MyTest
 WHERE UpdateDate > '2010-01-02' AND UpdateDate < '2020-01-01'
-- Index Seek
 SELECT * FROM MyTest
 WHERE UpdateDate > '2010-01-02' AND UpdateDate < '2010-01-05'


-- Index Scan
SELECT *
FROM MyFunction('2010-01-02', '2020-01-01')
-- Index Scan
SELECT *
FROM MyFunction('2010-01-02', '2010-01-05')


-- Index Scan
SELECT *
FROM MyFunction2('2010-01-02', '2020-01-01')
-- Index Seek
SELECT *
FROM MyFunction2('2010-01-02', '2010-01-05')