微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 SQL Server 2012 SP 2 中过滤数据,最好的方法是什么

如何解决在 SQL Server 2012 SP 2 中过滤数据,最好的方法是什么

我正在使用 EF Core 2.2,我会在感觉舒适时更新到 5。

目前我正在尝试寻找任何在大表格中搜索的来源,我有很好的建模表格 1 个主表格和一些表格,用于性别、地址、上次购买、评论产品等功能

  • EF 在这方面真的很慢,所以我使用了 dapper 并调用一个存储的 程序。
  • 我想过滤大约 5.5GB(470k 行,它是 要更大,31 列,7 个表,每个表 +15 列)。
  • 我有 5 个不同的过滤器,它必须很快。因为程序 响应时间估计为 1 分钟

查询应该使用动态参数

我必须做这样的事情我尝试了一些不同的方法但仍然很慢。我有 5 个过滤器和 1 个日期声明。用户可以发送 5、4 或 3 个过滤器,也可以不发送。

  1. 我尝试过的方法,我从使用“或”的博客中读到的方法确实会降低性能
    where (SaOr.InsertDate between ISNULL(@StartDate,'1900-01-01') and ISNULL(DATEADD(DAY,1,@DueDate),@TOMORROW))
            and (@ProductName is null or  SaOrPr.Name like '%' + @ProductName + '%')
            and (@PaymentType is null or LEN(@PaymentType)> LEN(REPLACE(@PaymentType,PaymentMethodId,'')) )
            and (@Channel is null or LEN(@Channel)> LEN(REPLACE(@Channel,SaOr.ChannelId,'')))
            and (@SalesType is null or  LEN(@SalesType)> LEN(REPLACE(@SalesType,SalesOrderTypeId,'')) )
            and (@Salesstatus is null or  LEN(@Salesstatus)> LEN(REPLACE(@Salesstatus,StatusId,''))  )
  1. 我尝试过的方法,没有“或”,但它比 1 慢。
    where (SaOr.InsertDate between ISNULL(@StartDate,'1920-01-01') and ISNULL(DATEADD(DAY,@TOMORROW)) 
      
            AND (SELECT CHARINDEX(ISNULL(ISNULL(@ProductName,SaOrPr.[Name]),' '),ISNULL(SaOrPr.[Name],' '))) >0
            AND (SELECT CHARINDEX(ISNULL(CAST(PaymentMethodId AS VARCHAR(38)),ISNULL(ISNULL(@PaymentType,PaymentMethodId),' '))) >0
             AND (SELECT CHARINDEX(ISNULL(CAST(SaOr.ChannelId AS VARCHAR(38)),ISNULL(ISNULL(@Channel,SaOr.ChannelId),' '))) >0
              AND (SELECT CHARINDEX(ISNULL(CAST(SalesOrderTypeId AS VARCHAR(38)),ISNULL(ISNULL(@SalesType,SalesOrderTypeId),' '))) >0
               AND (SELECT CHARINDEX(ISNULL(CAST(StatusId AS VARCHAR(38)),ISNULL(ISNULL(@Salesstatus,StatusId),' '))) >0

3.method 使用动态查询

declare @query varchar(max)= 'insert into #TmpResult 
    select  
       some fields
FROM #tmpSales SaOr


    where ( FilteredCount between   @pagination  and   @pagination + @PageSize - 1) '

    + CASE WHEN @PaymentType IS NOT NULL THEN
    ' AND LEN(@PaymentType)> LEN(REPLACE(@PaymentType,CONVERT(varchar(38),SaOr.PaymentMethodId),''''))  ' ELSE '' END

    + CASE WHEN @Channel IS NOT NULL THEN
    ' AND LEN(@Channel)> LEN(REPLACE(@Channel,''''))  ' ELSE '' END

    + CASE WHEN @SalesType IS NOT NULL THEN
    ' AND LEN(@SalesType)> LEN(REPLACE(@SalesType,SaOr.SalesOrderTypeId),''''))  ' ELSE '' END

    + CASE WHEN @Salesstatus IS NOT NULL THEN
    ' AND LEN(@Salesstatus)> LEN(REPLACE(@Salesstatus,SaOr.StatusId),''''))  ' ELSE '' END

    +    '  OPTION (RECOMPILE);';

解决方法

您需要执行几个步骤。

  1. 将表分成 2 或 3 个部分,例如过滤产品和付款,然后插入 #Temptable 并应用 INNER 加入其他表,例如 Channel 并获取过滤后的数据 #Temptable2 THEN Join 2nd Temptable with Sales 和 SalesType
  2. 用于过滤的列,在所有列上创建索引。

如果您一次从所有表中获取数据并应用将一次过滤数百万条记录的过滤器。因此,如果您划分表格,则过滤器将应用于较少的记录。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。