- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章利用 SQL Server 过滤索引提高查询语句的性能分析由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
大家好,我是只谈技术不剪发的 tony 老师.
microsoft sql server 过滤索引(筛选索引)是指基于满足特定条件的数据行进行索引。与全表索引(默认创建)相比,设计良好的筛选索引可以提高查询性能、减少索引维护开销并可降低索引存储开销。本文就给大家介绍一下 microsoft sql server 中的过滤索引功能.
在创建过滤索引之前,我们需要了解它的适用场景.
我们在创建索引时可以通过一个 where 子句指定需要索引的数据行,从而创建一个过滤索引。例如,对于以下订单表 orders:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
create
table
orders (
id
integer
primary
key
,
customer_id
integer
,
status
varchar
(10)
);
begin
declare
@counter
int
= 1
while @counter <= 1000000
begin
insert
into
orders
select
@counter, (rand() * 100000),
case
when
(rand() * 100)<1
then
'pending'
when
(rand() * 100)>99
then
'shipped'
else
'completed'
end
set
@counter = @counter + 1
end
end
;
|
订单表中总共有 100 万个订单,通常绝大部分的订单都处于完成状态。一般情况下,我们只需要针对某个用户未完成的订单进行查询跟踪,因此可以创建一个基于用户编号和状态的部分索引:
1
|
create
index
full_idx
on
orders (customer_id, status);
|
然后我们查看以下查询语句的执行计划:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
set
statistics
profile
on
select
*
from
orders
where
customer_id = 5043
and
status !=
'completed'
;
id |customer_id|status |
------+-----------+-------+
743436| 5043|pending|
947848| 5043|shipped|
rows
executes stmttext stmtid nodeid parent physicalop logicalop argument definedvalues estimaterows estimateio estimatecpu avgrowsize totalsubtreecost outputlist warnings type parallel estimateexecutions
2 1
select
*
from
[orders]
where
[customer_id]=@1
and
[status]<>@2 1 1 0
null
null
null
null
1.405213
null
null
null
0.003283546
null
null
select
0
null
2 1 |
--index seek(object:([hrdb].[dbo].[orders].[full_idx]), seek:([hrdb].[dbo].[orders].[customer_id]=(5043) and [hrdb].[dbo].[orders].[status] < 'completed' or [hrdb].[dbo].[orders].[customer_id]=(5043) and [hrdb].[dbo].[orders].[status] > 'completed') ordered forward) 1 2 1 index seek index seek object:([hrdb].[dbo].[orders].[full_idx]), seek:([hrdb].[dbo].[orders].[customer_id]=(5043) and [hrdb].[dbo].[orders].[status] < 'completed' or [hrdb].[dbo].[orders].[customer_id]=(5043) and [hrdb].[dbo].[orders].[status] > 'completed') ordered forward [hrdb].[dbo].[orders].[id], [hrdb].[dbo].[orders].[customer_id], [hrdb].[dbo].[orders].[status] 1.405213 0.003125 0.0001585457 27 0.003283546 [hrdb].[dbo].[orders].[id], [hrdb].[dbo].[orders].[customer_id], [hrdb].[dbo].[orders].[status] null plan_row 0 1
|
输出结果显示查询利用索引 full_idx 扫描查找所需的数据.
我们可以查看一下索引 full_idx 占用的空间大小:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
select
ix.
name
as
"index name"
,
sum
(sz.used_page_count) * 8/1024.0
as
"index size (mb)"
from
sys.dm_db_partition_stats
as
sz
inner
join
sys.indexes
as
ix
on
sz.object_id = ix.object_id
and
sz.index_id = ix.index_id
inner
join
sys.tables tn
on
tn.object_id = ix.object_id
where
tn.
name
=
'orders'
group
by
ix.
name
;
index
name
|
index
size
(mb)|
----------------------------+---------------+
full_idx | 26.171875|
pk__orders__3213e83f1e3b8a3b| 29.062500|
|
接下来我们再创建一个部分索引,只包含未完成的订单数据,从而减少索引的数据量:
1
2
|
create
index
partial_idx
on
orders (customer_id)
where
status !=
'completed'
;
|
索引 partial_idx 中只有 customer_id 字段,不需要 status 字段。同样可以查看一下索引 partial_idx 占用的空间大小:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
select
ix.
name
as
"index name"
,
sum
(sz.used_page_count) * 8/1024.0
as
"index size (mb)"
from
sys.dm_db_partition_stats
as
sz
inner
join
sys.indexes
as
ix
on
sz.object_id = ix.object_id
and
sz.index_id = ix.index_id
inner
join
sys.tables tn
on
tn.object_id = ix.object_id
where
tn.
name
=
'orders'
group
by
ix.
name
;
index
name
|
index
size
(mb)|
----------------------------+---------------+
full_idx | 26.171875|
partial_idx | 0.289062|
pk__orders__3213e83f1e3b8a3b| 29.062500|
|
索引只有 0.29 mb,而不是 26 mb,因为绝大多数订单都处于完成状态.
以下查询显式了适用过滤索引时的执行计划:
1
2
3
4
5
6
7
8
9
10
|
select
*
from
orders
with
(
index
( partial_idx ) )
where
customer_id = 5043
and
status !=
'completed'
;
rows
executes stmttext stmtid nodeid parent physicalop logicalop argument definedvalues estimaterows estimateio estimatecpu avgrowsize totalsubtreecost outputlist warnings type parallel estimateexecutions
2 1
select
*
from
orders
with
(
index
( partial_idx ) )
where
customer_id = 5043
and
status !=
'completed'
1 1 0
null
null
null
null
1.124088
null
null
null
0.03279812
null
null
select
0
null
2 1 |
--nested loops(inner join, outer references:([hrdb].[dbo].[orders].[id])) 1 2 1 nested loops inner join outer references:([hrdb].[dbo].[orders].[id]) null 1.124088 0 4.15295e-05 24 0.03279812 [hrdb].[dbo].[orders].[id], [hrdb].[dbo].[orders].[customer_id], [hrdb].[dbo].[orders].[status] null plan_row 0 1
2 1 |
--index seek(object:([hrdb].[dbo].[orders].[partial_idx]), seek:([hrdb].[dbo].[orders].[customer_id]=(5043)) ordered forward) 1 3 2 index seek index seek object:([hrdb].[dbo].[orders].[partial_idx]), seek:([hrdb].[dbo].[orders].[customer_id]=(5043)) ordered forward, forcedindex [hrdb].[dbo].[orders].[id], [hrdb].[dbo].[orders].[customer_id] 9.935287 0.003125 0.0001679288 15 0.003292929 [hrdb].[dbo].[orders].[id], [hrdb].[dbo].[orders].[customer_id] null plan_row 0 1
2 2 |
--clustered index seek(object:([hrdb].[dbo].[orders].[pk__orders__3213e83f1e3b8a3b]), seek:([hrdb].[dbo].[orders].[id]=[hrdb].[dbo].[orders].[id]) lookup ordered forward) 1 5 2 clustered index seek clustered index seek object:([hrdb].[dbo].[orders].[pk__orders__3213e83f1e3b8a3b]), seek:([hrdb].[dbo].[orders].[id]=[hrdb].[dbo].[orders].[id]) lookup ordered forward, forcedindex [hrdb].[dbo].[orders].[status] 1 0.003125 0.0001581 16 0.02946366 [hrdb].[dbo].[orders].[status] null plan_row 0 9.935287
|
我们比较通过 full_idx 和 partial_idx 执行以下查询的时间:
1
2
3
4
5
6
7
8
9
|
-- 300 ms
select
count
(*)
from
orders
with
(
index
( full_idx ) )
where
status !=
'completed'
;
-- 10 ms
select
count
(*)
from
orders
with
(
index
( partial_idx ) )
where
status !=
'completed'
;
|
另外,过滤索引还可以用于实现其他的功能。例如,我们可以将索引 partial_idx 定义为唯一索引,从而实现每个用户只能存在一个未完成订单的约束.
1
2
3
4
5
6
7
8
9
10
|
drop
index
partial_idx
on
orders;
truncate
table
orders;
create
unique
index
partial_idx
on
orders (customer_id)
where
status !=
'completed'
;
insert
into
orders(id, customer_id, status)
values
(1, 1,
'pending'
);
insert
into
orders(id, customer_id, status)
values
(2, 1,
'pending'
);
sql 错误 [2601] [23000]: 不能在具有唯一索引“partial_idx”的对象“dbo.orders”中插入重复键的行。重复键值为 (1)。
|
用户必须完成一个订单之后才能继续生成新的订单.
通过以上介绍可以看出,过滤索引是一种经过优化的非聚集索引,尤其适用于从特定数据子集中选择数据的查询.
到此这篇关于利用 sql server 过滤索引提高查询语句的性能分析的文章就介绍到这了,更多相关sql server索引提高语句性能内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.csdn.net/horses/article/details/109437027 。
最后此篇关于利用 SQL Server 过滤索引提高查询语句的性能分析的文章就讲到这里了,如果你想了解更多关于利用 SQL Server 过滤索引提高查询语句的性能分析的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在比较工作簿中的工作表。该工作簿有两张名为 PRE 和 POST 的工作表,每张工作表都有相同的 19 列。行数每天都不同,但特定一天的两张表的行数相同。该宏将 PRE 工作表中的每一行与 POS
我有一个对象数组,我一次循环遍历该数组一个对象,然后进行几次检查以查看该数组中的每个对象是否满足特定条件,如果该对象满足此条件,则复制一个属性将此对象放入数组中(该属性还包含另一个对象)。 for(v
我正在编写一个必须非常快的应用程序。我使用 Qt 5.5 和 Qt Creator,Qt 的 64 位 MSVC2013 编译版本。 我使用非常困倦的 CS 来分析我的应用程序,我看到占用最多独占时间
我有以下 CountDownTimer 在我的 Android 应用程序中不断运行。 CountDownTimer timer_status; timer_status = new CountDown
有一个优化问题,我必须调用随机森林回归器的预测函数数千次。 from sklearn.ensemble import RandomForestRegressor rfr = RandomForestR
我正在努力提高现有 Asp.Net Web 应用程序的数据访问层的性能。场景是。 它是一个基于 Web 的 Asp.Net 应用程序。 数据访问层使用 NHibernate 1.2 构建并作为 WCF
我在我的 Intel Edison 上运行 Debian,并尝试使用 ffmpeg 通过 USB 网络摄像头捕获视频。我正在使用的命令是: ffmpeg -f video4linux2 -i /dev
我有一个 For循环遍历整数 1 到 9 并简单地找到与该整数对应的最底部的条目(即 1,1,1,2,3,4,5 将找到第三个“1”条目)并插入一个空白行。我将数字与仅对应于此代码的应用程序的字符串“
我有一个带有非规范化架构(1 个表)的 postgresql 数据库,其中包含大约 400 万个条目。现在我有这个查询: SELECT count(*) AS Total, (SELECT c
在 Ltac 中实现复杂的策略时,有一些 Ltac 命令或策略调用我预计会失败以及预期失败(例如终止 repeat 或导致回溯)。这些故障通常在故障级别 0 时引发。 更高级别引发的故障“逃避”周
我正在尝试提高 ansible playbook 的性能。我有一个测试剧本如下: --- - name: Test hosts: localhost connection: local g
我正在使用 axios从 Azure 存储 Blob 下载文件 (~100MB)。 axios({ method: 'get', url: uri, onDownloadProgress:
我有一个 ClojureScript 程序,主要对集合执行数学计算。它是在惯用的、独立于主机的 Clojure 中开发的,因此很容易对其进行基准测试。令我惊讶的是(与答案对 Which is fast
我有一个程序必须在硬件允许的情况下尽快发出数千个 http 请求。在现实世界中,这些连接中的每一个都将连接到一个离散的服务器,但我已经编写了一个测试程序来帮助我模拟负载(希望如此)。 我的程序使用 A
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在计算 Clojure 中 3d 点云的边界框。点云表示为 Java 原始浮点数组,点云中的每个点都使用 4 个浮点存储,其中最后一个浮点未使用。像这样: [x0 y0 z0 u0 x1 y1
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我正在尝试使用rayshader 包制作图像。我很高兴能够使用如下代码创建一个 png 文件: library(ggplot2) library(rayshader) example_plot <-
更新 显然,jQuery 模板可以被编译,并且它有助于显示带有 if 语句 的模板的性能 here . 但是如图here ,预编译的 jQuery 模板对我的情况没有多大作用,因为我的模板不包含逻辑
我是编程新手。我有一个启用分页的 ScrollView ,其中包含许多页面(最多十个),并且在每个页面上都有一个自定义按钮。每个自定义按钮都有一个自定义图像。我在 Interface Builder
我是一名优秀的程序员,十分优秀!