Как улучшить SQL скорость запроса с 4 секунд до максимум 500 мс в Net Core 3.1 в ситуации фильтрации, SQL Server Enterprise 2019, Windows Azure - PullRequest
1 голос
/ 10 июля 2020

Нам нужно улучшить некоторые запросы к проекту недвижимости ~ аналогично booking.com, где нам нужно сделать некоторую фильтрацию для продуктов. Фильтры будут слева, продукты - справа.

Примеры фильтров :

  • Звездный рейтинг : 1 звезда (10 результатов), 2 звезды (12 результатов), 3 звезды (2 результата), et c

  • Тип недвижимости : Квартиры (20 результатов), Отели (30 результатов) и т.д. : Net Core 3.1, Entity Core, 1 сервер Windows 2019 SQL Server Enterprise 2019 (4 процессора, 16 ГБ ОЗУ), 1 Windows сервер Azure, SSD

    Структура базы данных

    • Продукты (ProductID, Title, et c): Hotel 1, Hotel 2: 1400 элементов в таблице

    • Атрибуты (AtrivuteValueID, Title): рейтинг звезд, тип свойства: 255 элементов в таблице

    • AtributeValues ​​ ( AtrivuteValueID, AtributeID, Заголовок): A partments, Hotels, 1, 2 и т. д. c: 1025 элементов в таблице

    • ProductAtributes (ProductAtributeID, ProductID, AtributeID, AtributeValueID): 140000 элементов в таблице

    • Индексированное представление : ViewAdminProductAtributes: 11900 элементов в представлении

          CREATE VIEW[dbo].[ViewAdminProductAtributeHintView] with SCHEMABINDING AS
      select[pa].[ProductAtributeID], [a].[AtributeID], [av].[AtributeValueID],[pa].[ProductID],
      [pa].[GroupID],[pa].[PartitionID],[pa].[PricePolicyID],[pa].[PricePolicyEntityID],
      [pa].[ProductCategoryID],[pa].[ProductCategoryIDP],[pa].[ProductCategoryIDPP],[pa].[IsPublished]         
      from[dbo].[ProductAtributes] [pa]
      inner join[dbo].[Atributes] [a] on[pa].[AtributeID] = [a].[AtributeID] and([a].[IsDisplayToFilters]= 1 or[a].[IsDisplayToFiltersOnKeySearch]= 1)
      inner join[dbo].[AtributeValues] [av] on[pa].[AtributeValueID] = [av].[AtributeValueID]
      CREATE Unique  CLUSTERED INDEX[IX_AdminProductAtributesFiltersHintView] ON[dbo].[ViewAdminProductAtributeHintView]( [ProductAtributeID] ASC)
      CREATE NONCLUSTERED INDEX[IX_NC_AdminProductAtributesFiltersHintView_AtributeValueID] ON[dbo].[ViewAdminProductAtributeHintView]
      ([AtributeValueID] ASC)Include([ProductID] , [AtributeID], [GroupID], [PartitionID], [PricePolicyID], [PricePolicyEntityID], [ProductCategoryID], [ProductCategoryIDP], [ProductCategoryIDPP], [IsPublished])
      

    Когда пользователь выбирает только 1-3 Фильтры Время запроса составляет ~ 300 мс, но после 4 фильтров время запроса составляет ~ 4 секунды.

    Нам нужно, чтобы это время запроса было меньше 800 мс для ~ 10 выбранных фильтров

    Мы пробовали все: индексирование представления, запрос представления с помощью (NOEXPAND), замена отдельного на Group By, тестирование плана выполнения в реальном времени (у нас есть поиск везде), но ничего не работает.

    Время запроса такое же в SQL Management Studio (4 секунды), поэтому проблем с EF Core нет.

    У сервера достаточно ресурсов, когда результат пользовательского фильтра не вызывает больших изменений в ЦП (3%) или ОЗУ.

    Есть что мы можем сделать с SQL сервером? Некоторые оптимизации?

    Запросы для фильтрации продуктов отлично работают : (206 мс)

     Executed DbCommand (206ms) [Parameters=[@__atributeID_3='?' (DbType = Int32), @__atributeID_5='?' (DbType = Int32), @__atributeID_7='?' (DbType = Int32), @__atributeID_9='?' (DbType = Int32), @__atributeID_11='?' (DbType = Int32), @__atributeID_13='?' (DbType = Int32), @__ProductCategoryID_1='?' (DbType = Int32), @__IsPublished_2='?' (DbType = Boolean), @__p_15='?' (DbType = Int32), @__p_16='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
      SELECT [p0].[ProductID], [p0].[Title], [p0].[LastUpdated], [p0].[ProductCategoryID], [p0].[Importance], COALESCE((
          SELECT MIN([p].[Price])
          FROM [ProductPricePolicies] AS [p]
          WHERE ([p0].[ProductID] = [p].[ProductID]) AND ([p].[IsMainUnitPrice] = CAST(1 AS bit))), 0.0) AS [PriceMin], [p0].[UrlNice], [p0].[CultureID], [p0].[ProductIDP]
      FROM [Products] AS [p0]
      INNER JOIN (
          SELECT DISTINCT [v].[ProductID]
          FROM [ViewAdminProductAtributeHintView] AS [v] WITH (NOEXPAND)
          INNER JOIN [ViewAdminProductAtributeHintView] AS [v0] WITH (NOEXPAND) ON [v].[ProductID] = [v0].[ProductID]
          INNER JOIN [ViewAdminProductAtributeHintView] AS [v1] WITH (NOEXPAND) ON [v].[ProductID] = [v1].[ProductID]
          INNER JOIN [ViewAdminProductAtributeHintView] AS [v2] WITH (NOEXPAND) ON [v].[ProductID] = [v2].[ProductID]
          INNER JOIN [ViewAdminProductAtributeHintView] AS [v3] WITH (NOEXPAND) ON [v].[ProductID] = [v3].[ProductID]
          INNER JOIN [ViewAdminProductAtributeHintView] AS [v4] WITH (NOEXPAND) ON [v].[ProductID] = [v4].[ProductID]
          INNER JOIN [ViewAdminProductAtributeHintView] AS [v5] WITH (NOEXPAND) ON [v].[ProductID] = [v5].[ProductID]
          WHERE (((((((((([v0].[AtributeID] = @__atributeID_3) AND [v0].[AtributeValueID] IN (224)) AND (((([v].[GroupID] = [v0].[GroupID]) OR ([v].[GroupID] IS NULL AND [v0].[GroupID] IS NULL)) OR ([v].[GroupID] IS NOT NULL AND [v0].[GroupID] IS NULL)) OR ([v].[GroupID] IS NULL AND [v0].[GroupID] IS NOT NULL))) AND (((([v].[PartitionID] = [v0].[PartitionID]) OR ([v].[PartitionID] IS NULL AND [v0].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NOT NULL AND [v0].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NULL AND [v0].[PartitionID] IS NOT NULL))) AND (((([v].[PricePolicyID] = [v0].[PricePolicyID]) OR ([v].[PricePolicyID] IS NULL AND [v0].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NOT NULL AND [v0].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NULL AND [v0].[PricePolicyID] IS NOT NULL))) AND (((([v].[PricePolicyEntityID] = [v0].[PricePolicyEntityID]) OR ([v].[PricePolicyEntityID] IS NULL AND [v0].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NOT NULL AND [v0].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NULL AND [v0].[PricePolicyEntityID] IS NOT NULL))) AND (((((([v1].[AtributeID] = @__atributeID_5) AND [v1].[AtributeValueID] IN (307)) AND (((([v].[GroupID] = [v1].[GroupID]) OR ([v].[GroupID] IS NULL AND [v1].[GroupID] IS NULL)) OR ([v].[GroupID] IS NOT NULL AND [v1].[GroupID] IS NULL)) OR ([v].[GroupID] IS NULL AND [v1].[GroupID] IS NOT NULL))) AND (((([v].[PartitionID] = [v1].[PartitionID]) OR ([v].[PartitionID] IS NULL AND [v1].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NOT NULL AND [v1].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NULL AND [v1].[PartitionID] IS NOT NULL))) AND (((([v].[PricePolicyID] = [v1].[PricePolicyID]) OR ([v].[PricePolicyID] IS NULL AND [v1].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NOT NULL AND [v1].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NULL AND [v1].[PricePolicyID] IS NOT NULL))) AND (((([v].[PricePolicyEntityID] = [v1].[PricePolicyEntityID]) OR ([v].[PricePolicyEntityID] IS NULL AND [v1].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NOT NULL AND [v1].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NULL AND [v1].[PricePolicyEntityID] IS NOT NULL)))) AND (((((([v2].[AtributeID] = @__atributeID_7) AND [v2].[AtributeValueID] IN (371)) AND (((([v].[GroupID] = [v2].[GroupID]) OR ([v].[GroupID] IS NULL AND [v2].[GroupID] IS NULL)) OR ([v].[GroupID] IS NOT NULL AND [v2].[GroupID] IS NULL)) OR ([v].[GroupID] IS NULL AND [v2].[GroupID] IS NOT NULL))) AND (((([v].[PartitionID] = [v2].[PartitionID]) OR ([v].[PartitionID] IS NULL AND [v2].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NOT NULL AND [v2].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NULL AND [v2].[PartitionID] IS NOT NULL))) AND (((([v].[PricePolicyID] = [v2].[PricePolicyID]) OR ([v].[PricePolicyID] IS NULL AND [v2].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NOT NULL AND [v2].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NULL AND [v2].[PricePolicyID] IS NOT NULL))) AND (((([v].[PricePolicyEntityID] = [v2].[PricePolicyEntityID]) OR ([v].[PricePolicyEntityID] IS NULL AND [v2].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NOT NULL AND [v2].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NULL AND [v2].[PricePolicyEntityID] IS NOT NULL)))) AND (((((([v3].[AtributeID] = @__atributeID_9) AND [v3].[AtributeValueID] IN (596)) AND (((([v].[GroupID] = [v3].[GroupID]) OR ([v].[GroupID] IS NULL AND [v3].[GroupID] IS NULL)) OR ([v].[GroupID] IS NOT NULL AND [v3].[GroupID] IS NULL)) OR ([v].[GroupID] IS NULL AND [v3].[GroupID] IS NOT NULL))) AND (((([v].[PartitionID] = [v3].[PartitionID]) OR ([v].[PartitionID] IS NULL AND [v3].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NOT NULL AND [v3].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NULL AND [v3].[PartitionID] IS NOT NULL))) AND (((([v].[PricePolicyID] = [v3].[PricePolicyID]) OR ([v].[PricePolicyID] IS NULL AND [v3].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NOT NULL AND [v3].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NULL AND [v3].[PricePolicyID] IS NOT NULL))) AND (((([v].[PricePolicyEntityID] = [v3].[PricePolicyEntityID]) OR ([v].[PricePolicyEntityID] IS NULL AND [v3].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NOT NULL AND [v3].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NULL AND [v3].[PricePolicyEntityID] IS NOT NULL)))) AND (((((([v4].[AtributeID] = @__atributeID_11) AND [v4].[AtributeValueID] IN (599)) AND (((([v].[GroupID] = [v4].[GroupID]) OR ([v].[GroupID] IS NULL AND [v4].[GroupID] IS NULL)) OR ([v].[GroupID] IS NOT NULL AND [v4].[GroupID] IS NULL)) OR ([v].[GroupID] IS NULL AND [v4].[GroupID] IS NOT NULL))) AND (((([v].[PartitionID] = [v4].[PartitionID]) OR ([v].[PartitionID] IS NULL AND [v4].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NOT NULL AND [v4].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NULL AND [v4].[PartitionID] IS NOT NULL))) AND (((([v].[PricePolicyID] = [v4].[PricePolicyID]) OR ([v].[PricePolicyID] IS NULL AND [v4].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NOT NULL AND [v4].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NULL AND [v4].[PricePolicyID] IS NOT NULL))) AND (((([v].[PricePolicyEntityID] = [v4].[PricePolicyEntityID]) OR ([v].[PricePolicyEntityID] IS NULL AND [v4].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NOT NULL AND [v4].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NULL AND [v4].[PricePolicyEntityID] IS NOT NULL)))) AND (((((([v5].[AtributeID] = @__atributeID_13) AND [v5].[AtributeValueID] IN (1529)) AND (((([v].[GroupID] = [v5].[GroupID]) OR ([v].[GroupID] IS NULL AND [v5].[GroupID] IS NULL)) OR ([v].[GroupID] IS NOT NULL AND [v5].[GroupID] IS NULL)) OR ([v].[GroupID] IS NULL AND [v5].[GroupID] IS NOT NULL))) AND (((([v].[PartitionID] = [v5].[PartitionID]) OR ([v].[PartitionID] IS NULL AND [v5].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NOT NULL AND [v5].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NULL AND [v5].[PartitionID] IS NOT NULL))) AND (((([v].[PricePolicyID] = [v5].[PricePolicyID]) OR ([v].[PricePolicyID] IS NULL AND [v5].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NOT NULL AND [v5].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NULL AND [v5].[PricePolicyID] IS NOT NULL))) AND (((([v].[PricePolicyEntityID] = [v5].[PricePolicyEntityID]) OR ([v].[PricePolicyEntityID] IS NULL AND [v5].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NOT NULL AND [v5].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NULL AND [v5].[PricePolicyEntityID] IS NOT NULL)))
      ) AS [t] ON [p0].[ProductID] = [t].[ProductID]
      WHERE ([p0].[CultureID] IS NULL AND ((([p0].[ProductCategoryID] = @__ProductCategoryID_1) OR ([p0].[ProductCategoryIDP] IS NOT NULL AND ([p0].[ProductCategoryIDP] = @__ProductCategoryID_1))) OR ([p0].[ProductCategoryIDPP] IS NOT NULL AND ([p0].[ProductCategoryIDPP] = @__ProductCategoryID_1)))) AND ([p0].[IsPublished] = @__IsPublished_2)
      ORDER BY [p0].[Importance], [p0].[ProductID] DESC
      OFFSET @__p_15 ROWS FETCH NEXT @__p_16 ROWS ONLY
    

    Но основная проблема заключается в получении и подсчете фильтры (AtributeValues) NEt Основной запрос: (3736 мс)

    public static async Task<List<AtributeValue>> GetAtributesValues(this DbSet<Atribute> source, ApplicationDbContext context, List<AtributeValue> Filters, int? ProductCategoryID)
        {
            var productAtibutesQuery = context.ViewAdminProductAtributes.WithHint("NOEXPAND").AsQueryable();
            if (ProductCategoryID.HasValue)
            {
                productAtibutesQuery = productAtibutesQuery.Where(p => (p.ProductCategoryID == ProductCategoryID));
            }
            if (Filters?.Any() == true)
            {
                foreach (var filtersGroup in Filters.GroupBy(p => p.AtributeID))
                {
                    int atributeID = filtersGroup.Key;
                    var atributeValues = filtersGroup.Select(p => p.AtributeValueID).ToList();
    
                    productAtibutesQuery = (from pf in productAtibutesQuery
                                            join y in context.ViewAdminProductAtributes.WithHint("NOEXPAND")
                                            on pf.ProductID equals y.ProductID
                                            where y.AtributeID == atributeID && (pf.AtributeValueID == y.AtributeValueID || atributeValues.Contains(y.AtributeValueID))
                                                    &&
                                                    ((pf.GroupID == y.GroupID) || (pf.GroupID != null && y.GroupID == null) || (pf.GroupID == null && y.GroupID != null))
                                                    &&
                                                    ((pf.PartitionID == y.PartitionID) || (pf.PartitionID != null && y.PartitionID == null) || (pf.PartitionID == null && y.PartitionID != null))
                                                    &&
                                                    ((pf.PricePolicyID == y.PricePolicyID) || (pf.PricePolicyID != null && y.PricePolicyID == null) || (pf.PricePolicyID == null && y.PricePolicyID != null))
                                                    &&
                                                    ((pf.PricePolicyEntityID == y.PricePolicyEntityID) || (pf.PricePolicyEntityID != null && y.PricePolicyEntityID == null) || (pf.PricePolicyEntityID == null && y.PricePolicyEntityID != null))
                                            select pf);
                }
            }
    
            var results = (from av in context.AtributeValues
                            join p in (from p in productAtibutesQuery
                                        group p by new { p.ProductID, p.AtributeValueID} into g
                                        select new
                                        {
                                            g.Key.AtributeValueID,
                                            g.Key.ProductID,
                                        }
                                        ).GroupBy(p => p.AtributeValueID)
                                            .Select
                                            (
                                                a => new
                                                {
                                                    AtributeValueID = a.Key,
                                                    Count = a.Count()
                                                }
                                            )
                                    on av.AtributeValueID equals p.AtributeValueID
                                    select new AtributeValue
                                    {
                                        AtributeValueID = av.AtributeValueID,
                                        Title = av.Title,
                                        Importance = av.Importance,
                                        AtributeID = av.AtributeID,
                                        Count = p.Count
                                    }
                                ).ToList();
    
                return results;         
    
        }
    

    Переведено SQL:

     Executed DbCommand (3,736ms) [Parameters=[@__ProductCategoryID_0='?' (DbType = Int32), @__atributeID_1='?' (DbType = Int32), @__atributeID_3='?' (DbType = Int32), @__atributeID_5='?' (DbType = Int32), @__atributeID_7='?' (DbType = Int32), @__atributeID_9='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
      SELECT [a].[AtributeValueID], [a].[Title], [a].[Importance], [a].[AtributeID], [t0].[c] AS [Count]
      FROM [AtributeValues] AS [a]
      INNER JOIN (
          SELECT [t].[AtributeValueID], COUNT(*) AS [c]
          FROM (
              SELECT [v].[AtributeValueID], [v].[ProductID]
              FROM [ViewAdminProductAtributeHintView] AS [v] WITH (NOEXPAND)
              INNER JOIN [ViewAdminProductAtributeHintView] AS [v0] WITH (NOEXPAND) ON [v].[ProductID] = [v0].[ProductID]
              INNER JOIN [ViewAdminProductAtributeHintView] AS [v1] WITH (NOEXPAND) ON [v].[ProductID] = [v1].[ProductID]
              INNER JOIN [ViewAdminProductAtributeHintView] AS [v2] WITH (NOEXPAND) ON [v].[ProductID] = [v2].[ProductID]
              INNER JOIN [ViewAdminProductAtributeHintView] AS [v3] WITH (NOEXPAND) ON [v].[ProductID] = [v3].[ProductID]
              INNER JOIN [ViewAdminProductAtributeHintView] AS [v4] WITH (NOEXPAND) ON [v].[ProductID] = [v4].[ProductID]
              WHERE (((((((([v].[ProductCategoryID] = @__ProductCategoryID_0) OR ([v].[ProductCategoryIDP] = @__ProductCategoryID_0)) OR ([v].[ProductCategoryIDPP] = @__ProductCategoryID_0)) AND ([v].[IsPublished] = CAST(1 AS bit))) AND (((((([v0].[AtributeID] = @__atributeID_1) AND (([v].[AtributeValueID] = [v0].[AtributeValueID]) OR [v0].[AtributeValueID] IN (307))) AND (((([v].[GroupID] = [v0].[GroupID]) OR ([v].[GroupID] IS NULL AND [v0].[GroupID] IS NULL)) OR ([v].[GroupID] IS NOT NULL AND [v0].[GroupID] IS NULL)) OR ([v].[GroupID] IS NULL AND [v0].[GroupID] IS NOT NULL))) AND (((([v].[PartitionID] = [v0].[PartitionID]) OR ([v].[PartitionID] IS NULL AND [v0].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NOT NULL AND [v0].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NULL AND [v0].[PartitionID] IS NOT NULL))) AND (((([v].[PricePolicyID] = [v0].[PricePolicyID]) OR ([v].[PricePolicyID] IS NULL AND [v0].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NOT NULL AND [v0].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NULL AND [v0].[PricePolicyID] IS NOT NULL))) AND (((([v].[PricePolicyEntityID] = [v0].[PricePolicyEntityID]) OR ([v].[PricePolicyEntityID] IS NULL AND [v0].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NOT NULL AND [v0].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NULL AND [v0].[PricePolicyEntityID] IS NOT NULL)))) AND (((((([v1].[AtributeID] = @__atributeID_3) AND (([v].[AtributeValueID] = [v1].[AtributeValueID]) OR [v1].[AtributeValueID] IN (371))) AND (((([v].[GroupID] = [v1].[GroupID]) OR ([v].[GroupID] IS NULL AND [v1].[GroupID] IS NULL)) OR ([v].[GroupID] IS NOT NULL AND [v1].[GroupID] IS NULL)) OR ([v].[GroupID] IS NULL AND [v1].[GroupID] IS NOT NULL))) AND (((([v].[PartitionID] = [v1].[PartitionID]) OR ([v].[PartitionID] IS NULL AND [v1].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NOT NULL AND [v1].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NULL AND [v1].[PartitionID] IS NOT NULL))) AND (((([v].[PricePolicyID] = [v1].[PricePolicyID]) OR ([v].[PricePolicyID] IS NULL AND [v1].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NOT NULL AND [v1].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NULL AND [v1].[PricePolicyID] IS NOT NULL))) AND (((([v].[PricePolicyEntityID] = [v1].[PricePolicyEntityID]) OR ([v].[PricePolicyEntityID] IS NULL AND [v1].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NOT NULL AND [v1].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NULL AND [v1].[PricePolicyEntityID] IS NOT NULL)))) AND (((((([v2].[AtributeID] = @__atributeID_5) AND (([v].[AtributeValueID] = [v2].[AtributeValueID]) OR [v2].[AtributeValueID] IN (596))) AND (((([v].[GroupID] = [v2].[GroupID]) OR ([v].[GroupID] IS NULL AND [v2].[GroupID] IS NULL)) OR ([v].[GroupID] IS NOT NULL AND [v2].[GroupID] IS NULL)) OR ([v].[GroupID] IS NULL AND [v2].[GroupID] IS NOT NULL))) AND (((([v].[PartitionID] = [v2].[PartitionID]) OR ([v].[PartitionID] IS NULL AND [v2].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NOT NULL AND [v2].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NULL AND [v2].[PartitionID] IS NOT NULL))) AND (((([v].[PricePolicyID] = [v2].[PricePolicyID]) OR ([v].[PricePolicyID] IS NULL AND [v2].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NOT NULL AND [v2].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NULL AND [v2].[PricePolicyID] IS NOT NULL))) AND (((([v].[PricePolicyEntityID] = [v2].[PricePolicyEntityID]) OR ([v].[PricePolicyEntityID] IS NULL AND [v2].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NOT NULL AND [v2].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NULL AND [v2].[PricePolicyEntityID] IS NOT NULL)))) AND (((((([v3].[AtributeID] = @__atributeID_7) AND (([v].[AtributeValueID] = [v3].[AtributeValueID]) OR [v3].[AtributeValueID] IN (599))) AND (((([v].[GroupID] = [v3].[GroupID]) OR ([v].[GroupID] IS NULL AND [v3].[GroupID] IS NULL)) OR ([v].[GroupID] IS NOT NULL AND [v3].[GroupID] IS NULL)) OR ([v].[GroupID] IS NULL AND [v3].[GroupID] IS NOT NULL))) AND (((([v].[PartitionID] = [v3].[PartitionID]) OR ([v].[PartitionID] IS NULL AND [v3].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NOT NULL AND [v3].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NULL AND [v3].[PartitionID] IS NOT NULL))) AND (((([v].[PricePolicyID] = [v3].[PricePolicyID]) OR ([v].[PricePolicyID] IS NULL AND [v3].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NOT NULL AND [v3].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NULL AND [v3].[PricePolicyID] IS NOT NULL))) AND (((([v].[PricePolicyEntityID] = [v3].[PricePolicyEntityID]) OR ([v].[PricePolicyEntityID] IS NULL AND [v3].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NOT NULL AND [v3].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NULL AND [v3].[PricePolicyEntityID] IS NOT NULL)))) AND (((((([v4].[AtributeID] = @__atributeID_9) AND (([v].[AtributeValueID] = [v4].[AtributeValueID]) OR [v4].[AtributeValueID] IN (1529))) AND (((([v].[GroupID] = [v4].[GroupID]) OR ([v].[GroupID] IS NULL AND [v4].[GroupID] IS NULL)) OR ([v].[GroupID] IS NOT NULL AND [v4].[GroupID] IS NULL)) OR ([v].[GroupID] IS NULL AND [v4].[GroupID] IS NOT NULL))) AND (((([v].[PartitionID] = [v4].[PartitionID]) OR ([v].[PartitionID] IS NULL AND [v4].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NOT NULL AND [v4].[PartitionID] IS NULL)) OR ([v].[PartitionID] IS NULL AND [v4].[PartitionID] IS NOT NULL))) AND (((([v].[PricePolicyID] = [v4].[PricePolicyID]) OR ([v].[PricePolicyID] IS NULL AND [v4].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NOT NULL AND [v4].[PricePolicyID] IS NULL)) OR ([v].[PricePolicyID] IS NULL AND [v4].[PricePolicyID] IS NOT NULL))) AND (((([v].[PricePolicyEntityID] = [v4].[PricePolicyEntityID]) OR ([v].[PricePolicyEntityID] IS NULL AND [v4].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NOT NULL AND [v4].[PricePolicyEntityID] IS NULL)) OR ([v].[PricePolicyEntityID] IS NULL AND [v4].[PricePolicyEntityID] IS NOT NULL)))
              GROUP BY [v].[ProductID], [v].[AtributeValueID]
          ) AS [t]
          GROUP BY [t].[AtributeValueID]
      ) AS [t0] ON [a].[AtributeValueID] = [t0].[AtributeValueID]
    

    План выполнения (2 фильтра) - Вроде нормально выглядит. enter image description here

    Execution Plan ( 4-5 Filters ) : It Looks BAD

    введите описание изображения здесь

...