查询优化器在从表中查询数据时,需要选择一个合适的访问模式,在决定使用哪一种索引,使用扫描还是查找,使用书签查询时,查询优化器要考虑许多因素,这些因素包括:
- 索引执行时,查找或扫描所需的I/O数
- 评估查询中的索引键是否是最佳
- 谓词的选择性(也就是说,相对于表中总记录数满足谓词的百分比)
- 索引是否覆盖所有列?
下面通过一个例子来介绍:
create table T (a int, b int, c int, d int, x char(200))
create unique clustered index Ta on T(a)
create index Tb on T(b)
create index Tcd on T(c, d)
create index Tdc on T(d, c)
插入一些数据:
set nocount on
declare @i int
set @i = 0
while @i < 100000
begin
insert T values (@i, @i, @i, @i, @i)
set @i = @i + 1
end
无Where条件
Select a,b FROM T,
该
查询不包含Where条件语句,而使用扫描,可是这里有两种索引可用:聚集索引(Ta)和非聚集索引(Tb),这两个索引均覆盖a和b两列,另外,聚集索
引也覆盖c和x列.由于x列是字符型,长度为200个字符,聚集索引的每一行总宽度超过了200个字节,对于每一个8KB的页面,存储的行数也不超过40
行.而索引需要2500个页来存储所有10万行数据,与之相反的是,非聚集索引中每一行的总宽仅有8个字节,加一些头部信息,每一页可以存储上百行数据,
索引则需要不到250页来存储所有的10万行数据.通过扫描非聚集索引,当执行查询时则需要较少的I/O操作.因而使用的最佳计划是:
|--Index Scan(OBJECT:([T].[Tb]))
我们也可以使用sys.dm_db_index_physical_stats视图来比较聚集索引与非聚集索引两者所使用的页数
select index_id, page_count
from sys.dm_db_index_physical_stats
(DB_ID('northwind'), OBJECT_ID('T'), NULL, NULL, NULL)
执行上述查询后,结果如下:
索引ID号 |
页数 |
1 |
2858 |
2 |
174 |
3 |
223 |
4 |
223 |
从输出结果可以看出,非聚集索引存储行所使用的页数明显小于聚集索引使用的页数.
当然我们也可以使用stats I/O和索引hints来比较聚集索引与非聚集索引的I/O数.
set statistics io on
select a, b from T with (index(Ta))
表'T'。扫描计数1,逻辑读取2872
次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。
select a, b from T with (index(Tb))
表'T'。扫描计数1,逻辑读取176
次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。
从stats I/O数可以看出,非聚集索引在获取数据时,读取较少的数据页.
索引的选择性
select a from T
where c > 150 and c < 160 and d > 100 and d < 200
此查询有两个不同的谓词用于索引查找,可以使用位于c列上的非聚集索引Tcd,也可以使用位于d列上的非聚集索引Tdc.
查询优化器通过查看两个谓词的选择性来确定使用哪一个索引,在c列上的谓词选择的行仅有9行,而在d列上则有99行,显然使用索引Tcd来评估位于d列上的residual谓词比使用Tdc索引的I/O开销要小得多.
以下是该查询的计划:
|--Index Seek(OBJECT:([T].[Tcd]), SEEK:([T].[c] > (150) AND [T].[c] < (160)),
Where:([T].[d]>(100) AND [T].[d]<(200)) orDERED FORWARD)
索引查找与索引扫描示例
select a from T where a between 1001 and 9000
select a from T where a between 101 and 90000
其执I/O信息如下:
表'T'。扫描计数1,逻辑读取234
次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。
表'T'。扫描计数1,逻辑读取176
次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。
如您所预料的,对于第一个查询来说,查询优化器在a列上选择使用聚集索引来获取数据,以下是其的查询计划:
|--Clustered Index Seek(OBJECT:([T].[Ta]),
SEEK:([T].[a] >= CONVERT_IMPLICIT(int,[@1],0) AND [T].[a] <= CONVERT_IMPLICIT(int,[@2],0)) orDERED FORWARD)
注意:该计划中的两个参数是由自动参数化功能所生成的,当执行该计划时,@1参数为1001,@2参数为9000.
对于第二个查询来说,查询优化器却选择了非聚集索引来扫描数据,以下其查询计划:
|--Index Scan(OBJECT:([T].[Tb]), Where:([T].[a]>=(101) AND [T].[a]<=(90000)))
为
什么是这样呢?注意第一个查询选择的记录数有8千行(相对于10万行数据而言),对于聚集索引来说,选择度为表的8%,约230个数据页,而第二查询选择
的记录数有89000行,选择度为表的约90%,若使用聚集索引来读取89000行数据时,则需要读2500个数据页.通过比较,非聚集索引仅需要读取
174个页面,查询优化器选择此计划,大大减少了I/O操作.
带书签查询的查询与扫描示例
select x from T where b between 101 and 200
select x from T where b between 1001 and 2000
对
于上述的两个查询而言,可以通过聚集索引直接扫描然后在列b上应用谓词,或者使用非聚集索引Tb在列b上执行索引查找,然后在聚集索引上执行书签查询来读
取满足x列值的行.(注意:书签查询采用的I/O开销比较大的方式是随机读.)对于查找的选择度高的书签查询,则是值得的.
以下是第一个包含书签查询的查询计划(仅需要读取100行):
|--Nested Loops(Inner Join, OUTER REFERENCES:([T].[a], [Expr1005]) ...)
|--Index Seek(OBJECT:([T].[Tb]), SEEK:([T].[b] >= (101) AND [T].[b] <= (200)) ...)
|--Clustered Index Seek(OBJECT:([T].[Ta]), SEEK:([T].[a]=[T].[a]) LOOKUP ...)
而第二个查询则读取1000行,对于表而言,仅有1%.查询优化器由此推出,执行1000次的随机读要比执行2800次的顺序读的开销要大得多,第二个查询的计划如下:
|--Clustered Index Scan(OBJECT:([T].[Ta]), Where:([T].[b]>=(1001) AND [T].[b]<=(2000)))
源文出处:http://www.haixiait.com/article.asp?id=162
相关推荐
SQLserver索引失效举例.txt
### Oracle索引使用样例详解 #### 一、索引并行创建 在Oracle数据库中,并行创建索引可以显著提高创建索引的速度,尤其是在处理大量数据时。下面的SQL语句展示了如何并行创建一个索引: ```sql CREATE INDEX IDX_GD...
DB2索引及其优化 DB2索引设计及其优化是...在本文中,我们讨论了DB2索引的概念、创建索引、建立索引注意事项、索引分类和索引优化等方面的知识点,并提供了一些有用的提示和建议,以帮助读者更好地理解和应用DB2索引。
LaTeX论文写作教程-建立索引及文献引用 LaTeX是一种基于TeX的排版系统,用于创建高质量的科技文档,如学术论文、书籍、报告等。与传统的字处理软件(如Word)相比,LaTeX具有以下优势: 专业排版:LaTeX提供了丰富...
代码复制粘贴 改下里面的参数 就可以用 而且参数 也有说明 简单易懂
C语言实现的词索引表程序:IndexBook。C语言实现按照索引插入并查找元素。严蔚敏建立词索引表:严蔚敏数据结构C语言实现,串操作应用举例中的词索引表例子,由于作者没给出完整源码,自己写了一个比较完整的。
#### 举例说明 假设有一个名为`T`的表,包含7条记录,表结构存储在`t.frm`文件中,数据存储在`t.ibd`文件中。表的结构和数据如下: - **聚集索引结构**:查询速度最快,只需两次I/O操作。 - **非聚集索引结构(a...
举例来说,如果我们有一个名为`people`的表,包含`lname`、`fname`和`age`三列,若要查询姓`Liu`、名`Zhiqun`且年龄为26的用户ID,创建一个`(lname, fname, age)`的多列索引会非常有效。如果只对`lname`创建单列索引...
### bbf算法的详细介绍与应用举例 #### 一、引言 在计算机视觉领域,特别是形状索引(Shape Indexing)技术中,一种名为“Best Bin First”(BBF)的搜索算法因其在高维特征空间中的高效表现而受到广泛关注。本文...
"MySql 相关面试题举例" 本资源摘要信息涵盖了 MySQL 相关的面试题,包括关系型和非关系型数据库的区别、MySQL 语句执行步骤、索引的使用原因、索引的三种常见底层数据结构、索引的常见类型、MyISAM 和 InnoDB 实现...
"数据结构C语言树二叉树详细举例介绍" 本文档为数据结构C语言树二叉树的详细介绍,包括树的类型定义、二叉树的类型定义、二叉树的存储结构、二叉树的遍历、线索二叉树、树和森林的表示方法、树和森林的遍历、哈夫曼...
- **字段类型举例**: - `long`:用于整数类型的字段,如`houseId`。 - `text`:用于长文本字段,如`title`、`description`。`index": "true"`表明这个字段需要被分析并建立索引,以便进行全文搜索。 - `integer...
在MySQL数据库中,索引是优化查询性能的关键工具。前缀索引是一种特殊的索引类型,它允许我们只对字符串的起始部分创建索引,而不是整个字符串。这在处理大字符串时尤其有用,因为完全索引可能会占用大量存储空间,...
举例来说,使用一个包含唯一索引的列来查询一个特定的值,如`SELECT * FROM table WHERE id = x`,就会被识别为const类型。因为id作为唯一索引,查询的性能极高。 2. ref:ref是另一种执行计划类型,指的是使用普通...
2. 设计合理的索引:索引可以显著提升查询速度。主键应具有唯一性且不易变动,适合创建聚集索引;对于经常用于搜索或排序的列,可建立非聚集索引。 3. 避免数据冗余:通过规范化设计减少重复数据,降低数据不一致的...
day05_11_常见问题_数组索引越界异常
1. 描述索引如何提高查询速度,并举例说明。 2. 比较聚集索引和非聚集索引的区别,给出实际应用场景。 3. 设计一个包含多个索引的数据库表,并解释为什么选择这些索引。 4. 在SSMS中,如何查看和分析一个表的索引...
举例来说,假设我们有一个教师档案表,我们可以根据教师的编号、部门或职称建立索引。如果按照部门建立索引,会形成对应于不同系的子表,每个子表在索引表中都有一个条目,包括子表的开始位置和长度。类似地,按照...