2016-01-21 67 views
0

我有一個查詢在4秒內運行,但在WHERE中沒有is null,但在is null需要幾分鐘時間。我已經閱讀了空檢查對性能的影響,但在這種情況下,我無法修改正在運行的查詢。我可以修改索引或視圖以提高'空'子句的性能

select 
    view_scores.* 
from 
    view_scores 
    inner join licenses AS l on view_scores.studentId = l.account_id 
where view_scores.archived_date is null 
    and l.school_id = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' 
    and l.is_current = 1 
    and l.expiration_date >= SYSDATETIME() 

view_scores是一個視圖,它彙集其他表中的數據的其他視圖,其中一個視圖最終保存archived_date字段。該字段中的空值意味着它尚未歸檔。同樣,數據結構不在我的控制範圍之內。我現在可以改變的是所涉及的觀點的內部和表格上的索引。我是否有希望在不更改查詢或模式的情況下顯着提高對archived_date的空檢查?

view_scores與此SQL

SELECT 
    ueh.user_id AS studentId, 
    vu.first_name + ' ' + vu.last_name AS studentName, 
    ueh.archived_date as archived_date, 
    MIN([ueh].[date_taken]) AS [started_date], 
    MAX(ueh.date_taken) AS last_date, 
    SUM(CAST([ueh].[actual_time] AS FLOAT)/600000000) AS [total_time_minutes], 
    SUM([exercise_scores].[earned_score]) AS [earned_score], 
    SUM([exercise_scores].[possible_score]) AS [possible_score], 
    AVG([exercise_scores].[percent_score]) AS [percent_score], 
    COUNT(ueh.exercise_id) AS total_exercises 
FROM [user_exercise_history] AS [ueh] 
LEFT JOIN 
    (
     SELECT 
      coding_exercise_score.exercise_id AS exercise_id, 
      coding_exercise_score.assessment_id AS assessment_id, 
      coding_exercise_score.user_id AS user_id, 
      coding_exercise_score.archived_date AS archived_date, 
      score.earned AS earned_score, 
      score.possible AS possible_score, 
      CASE score.possible 
       WHEN 0 THEN 0 
       WHEN score.earned THEN 100 
       ELSE 9.5 * POWER(CAST(score.earned AS DECIMAL)/score.possible * 100, 0.511) 
      END AS percent_score 
     FROM coding_exercise_score 
     INNER JOIN 
      coding_exercise_score_detail AS score_detail 
      ON coding_exercise_score.id = score_detail.exercise_score_id 
     INNER JOIN 
      score 
      ON score.id = score_detail.score_id 
     WHERE score_detail.is_best_score = 'True' 

     UNION 

     SELECT 
      mc_score.exercise_id AS exercise_id, 
      mc_score.assessment_id AS assessment_id, 
      mc_score.user_id AS user_id, 
      mc_score.archived_date AS archived_date, 
      score.earned AS earned_score, 
      score.possible AS possible_score, 
      CASE score.possible 
       WHEN 0 THEN 0 
       WHEN score.earned THEN 100 
       ELSE 9.5 * POWER(CAST(score.earned AS DECIMAL)/score.possible * 100, 0.511) 
      END AS percent_score 
     FROM 
      multiple_choice_exercise_score AS mc_score 
     INNER JOIN score 
      ON score.id = mc_score.score_id 
    ) AS [exercise_scores] 
     ON 
      (
       (ueh.exercise_id = [exercise_scores].exercise_id 
        AND ueh.user_id = [exercise_scores].user_id 
        AND (
         (ueh.assessment_id IS NULL AND [exercise_scores].assessment_id IS NULL) 
         OR ueh.assessment_id = [exercise_scores].assessment_id 
         ) 
        AND (ueh.archived_date IS NULL) 
       ) 
      ) 
INNER JOIN entity_account AS vu ON ((ueh.user_id = vu.account_id)) 
INNER JOIN (
    select 
     g.group_id, 
     g.entity_name, 
     g.entity_description, 
     g.created_on_date, 
     g.modified_date, 
     g.created_by, 
     g.modified_by, 
     agj.account_id 
    from entity_group as g 
    inner join 
     account_group_join as agj 
    on agj.group_id = g.group_id 
    where g.entity_name <> 'Administrators' 
     and g.entity_name <> 'Group 1' 
     and g.entity_name <> 'Group 2' 
     and g.entity_name <> 'Group 3' 
     and g.entity_name <> 'Group 4' 
     and g.entity_name <> 'Group 5' 
) AS g ON ueh.user_id = g.account_id 
WHERE ueh.status = 'Completed' 
GROUP BY ueh.user_id, vu.first_name, vu.last_name, ueh.archived_date 

user_exercise_history.archived_date AS archived_date是外地的空支票最終被執行鍼對創建。我可以以任何我想要的方式修改視圖並以任何我想要的方式編制索引,但這就是它。

帶有空檢查的執行計劃包含一組非常瘋狂的排序和散列匹配,它們與score和coding_exercise_score_detail有關。

Execution Plan Details

+0

'EXEC sp_updatestats;'到你的數據庫更新統計。任何改變? – Mihai

+0

所以如果你可以改變視圖的內部,我們可以看到創建視圖的sql嗎? – HLGEM

+1

你是否在視圖中調用任何其他視圖?如果是這樣,這通常是一個壞主意。我們幾乎失去了一個數百萬美元的客戶,因爲一個不知情的人對圍繞着視圖的觀點進行了整體設計。 – HLGEM

回答

0

你可以把一個視圖索引。
Create Indexed Views
上view_scores.archived_date

+0

我的理解是,您只能使用確定性值對視圖進行索引。如果我理解,某些列是SUM或AVG或COUNT,這是非確定性的。這使得這不可能,對嗎? – sonicblis

+0

只有當您想使其成爲索引/實體化視圖時,纔可以在視圖上創建索引。可能OP不希望那樣。 – Rahul

+0

可悲的是,很少有意見實際符合索引標準。 – HLGEM

0

嘗試的指數一般都參與JOIN ON條件和WHEREORDER BY應該被索引獲得更好的性能列。既然你說view_scores是一個視圖,然後檢查實際表中的列archived_date是否索引。如果沒有,那麼你應該考慮在該列上創建一個索引。

您也可以考慮將該條件添加到視圖創建邏輯本身。

view_scores.archived_date is null 
+0

在該字段中添加非聚集索引不會產生任何影響。在該字段上添加聚集索引使性能變差。 – sonicblis

+0

它是一個日期時間列嗎?你也可以在視圖創建本身中加入coolumn。 – Rahul

+0

它是(明顯)允許空值的日期時間。你怎麼把它包含在視圖本身中?現在視圖將其作爲列返回。選擇... ueh.archived_date作爲archived_date ...,ueh是返回實際字段archived_date的另一個視圖。 – sonicblis

0
ON  ueh.exercise_id = [exercise_scores].exercise_id 
    AND ueh.user_id  = [exercise_scores].user_id 
    AND ueh.archived_date IS NULL 
    AND (( ueh.assessment_id IS NULL 
      AND [exercise_scores].assessment_id IS NULL 
     ) 
      OR ueh.assessment_id = [exercise_scores].assessment_id 
     ) 

我想看看這個
或加入通常是緩慢的
皮克和ID將無法使用

ON  ueh.exercise_id = [exercise_scores].exercise_id 
    AND ueh.user_id  = [exercise_scores].user_id 
    AND ueh.archived_date IS NULL 
    AND isnull(ueh.assessment_id, -1) = isnull([exercise_scores].assessment_id, -1) 
相關問題