背景:我在Azure上运行Sql Server 2014(12.0.2000.8)...
我前几天发现了一个方便的脚本,它显示了"触摸"的查询/存储过程。索引。我一直在寻找这个,因为我有一些表现很差的索引,但是我找不到它们被称为的地方。
现在我已掌握了这些信息,我一直在努力重新处理触及相关索引的触发器。
在查看我的查询的执行计划时,它说它正在进行扫描,这显然不是最佳的。
将鼠标悬停在索引上会显示联接的输出列表,但不显示谓词。
我继续创建了一个索引,其中包含该输出列表中的确切字段。
这是正在运行的查询:
declare @season int = 2017
select s.SchoolId,
s.Name [SchoolName],
s.Conference,
tr.DualRank [Rank],
convert(varchar(2), tr.DualWins) + ' - ' + convert(varchar(2), tr.DualLosses) [Record],
tr.RankingDate,
case when tr.WeekNumber = 0 then null
else
(select trx.DualRank from dbo.TeamRankings trx where trx.Season = tr.Season and trx.WeekNumber = (tr.WeekNumber - 1) and trx.SchoolId = tr.SchoolId)
- tr.DualRank
end [Trend],
(select trx.DualRank from dbo.TeamRankings trx where trx.Season = tr.Season and trx.WeekNumber = (tr.WeekNumber - 1) and trx.SchoolId = tr.SchoolId) [PreviousWeek]
from dbo.TeamRankings tr
join dbo.School s on s.SchoolId = tr.SchoolId
where tr.Season = @season
and tr.IsCurrent = 1
order by tr.DualRank
此列表中唯一一个具有扫描而不是搜索的连接是学校表格中的连接。它加入SchoolId,然后在选择部分输出名称和会议。似乎很直接。
在我的第一次尝试中,我继续创建我的索引:
create nonclustered index idx_NC_School_SchoolId_incs on dbo.School (SchoolId asc) include (Name, Conference)
但仍然导致扫描。我的第二次尝试就是这样做:
create nonclustered index idx_NC_School_SchoolId_Name_Conference on dbo.School (SchoolId asc, Name asc, Conference asc)
但是STILL正在利用我创建的索引进行扫描。
我还应该考虑尝试让此查询进行搜索而不是扫描。
有关更多背景信息,请参阅表定义的子集:
dbo.School
SchoolId int identity(1,1) primary key,
Name varchar(100) not null,
Conference varchar(100) not null -- will soon change this to a lookup table
......
我知道有人会问,但我无法弄明白该怎么做;如何将执行计划附加到问题中?
这是指向显示数据的页面的链接:http://www.wrestlestat.com/rankings/dual/live
答案 0 :(得分:0)
索引扫描并不总是坏事,特别是当你有一个非常小的表时。
但是可以肯定地提高查询效果的是将sub-queries
从select
子句移到from
并使用join
。
像......一样......
declare @season int = 2017
select s.SchoolId,
s.Name [SchoolName],
s.Conference,
tr.DualRank [Rank],
convert(varchar(2), tr.DualWins) + ' - ' + convert(varchar(2), tr.DualLosses) [Record],
tr.RankingDate,
CASE WHEN tr.WeekNumber = 0 then null
ELSE trx.DualRank - tr.DualRank end [Trend],
trx.DualRank [PreviousWeek]
from dbo.TeamRankings tr
Inner join dbo.School s on s.SchoolId = tr.SchoolId
Left join dbo.TeamRankings trx ON trx.Season = tr.Season
and trx.WeekNumber = (tr.WeekNumber - 1)
and trx.SchoolId = tr.SchoolId
where tr.Season = @season
and tr.IsCurrent = 1
order by tr.DualRank
如果sub-query
子句中有select
,则sub-query
会为outer query
返回的每一行执行from
,如果将其移至executed once
}子句和使用连接,它将是# -*- coding: utf-8 -*-
"""Add permissions for proxy model.
This is needed because of the bug https://code.djangoproject.com/ticket/11154
in Django (as of 1.6, it's not fixed).
When a permission is created for a proxy model, it actually creates if for it's
base model app_label (eg: for "article" instead of "about", for the About proxy
model).
What we need, however, is that the permission be created for the proxy model
itself, in order to have the proper entries displayed in the admin.
"""
from __future__ import unicode_literals, absolute_import, division
import sys
from django.contrib.auth.management import _get_all_permissions
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.core.management.base import BaseCommand
from django.apps import apps
from django.utils.encoding import smart_text
class Command(BaseCommand):
help = "Fix permissions for proxy models."
def handle(self, *args, **options):
for model in apps.get_models():
opts = model._meta
ctype, created = ContentType.objects.get_or_create(
app_label=opts.app_label,
model=opts.object_name.lower(),
defaults={'name': smart_text(opts.verbose_name_raw)})
for codename, name in _get_all_permissions(opts):
p, created = Permission.objects.get_or_create(
codename=codename,
content_type=ctype,
defaults={'name': name})
if created:
sys.stdout.write('Adding permission {}\n'.format(p))
,结果集将与来自其他连接的结果集连接。更高效,更清洁。
答案 1 :(得分:0)
您可以使用LAG和LEAD等窗口函数来自动连接到表格。 它可以导致更简单的执行计划。
declare @season int = 2017
select
s.SchoolId,
s.Name [SchoolName],
s.Conference,
tr.DualRank [Rank],
convert(varchar(2), tr.DualWins) + ' - ' + convert(varchar(2), tr.DualLosses) [Record],
tr.RankingDate,
CASE WHEN tr.WeekNumber = 0 THEN NULL ELSE tr.DualRank - LAG(tr.DualRank,1,0) OVER(Partition BY tr.Season,tr.SchoolId ORDER BY trx.WeekNumber) END AS [Trend],
LAG(tr.DualRank,1,0) OVER(Partition BY tr.Season,tr.SchoolId ORDER BY trx.WeekNumber) AS [PreviousWeek]
from
dbo.TeamRankings tr
join dbo.School s on s.SchoolId = tr.SchoolId
where
tr.Season = @season
and
tr.IsCurrent = 1
order by
tr.DualRank
使用时
trx.WeekNumber = (tr.WeekNumber - 1)
您正在改变tr.WeekNumber的值,因此它与存储在索引中的值不同,因此SQL将执行扫描而不是搜索。