0.参考文献
Table Scan, Index Scan, Index Seek
SQL SERVER – Index Seek vs. Index Scan – Diffefence and Usage – A Simple Note
Index Seek和Index Scan的区别以及适用情况
1.oracle中的表访问方式
在oracle中有表访问方式的说法,访问表中的数据主要通过三种方式进行访问:
- 全表扫描(full table scan),直接访问数据页,查找满足条件的数据
- 通过rowid扫描(table access by rowid),如果知道数据的rowid,那么直接通过rowid进行查找
- 索引扫描(index scan),如果一个表创建了索引,那么可以通过索引来找出我们想要的数据在表中的存放位置,也就是rowid,通过返回rowid然后用rowid来进行访问具体数据。
- 而索引扫描中又可分为索引全扫描(index full scan)、索引范围扫描(index range scan)和索引唯一扫描(index unique scan)等。
2.sql server中clustered index scan,table scan,index scan
在sqlserver中也有类似的内容,这里就要将的是table scan,index scan以及index seek.
- A table scan is where the table is processed row by row from beginning to end.
- An index scan is where the index is processed row by row from beginning to end.
- If the index is a clustered index then an index scan is really a table scan.
- 总结:在sql server中,对表中数据从头到尾一行一行的进行出来就是表扫描。这里的处理我们可以理解为sql中where子句的条件判断。我们需要遍历表中的每一行,判断是否满足where条件。最简单的table scan是select * from table。
- 索引扫描就是对索引中的每个节点从头到尾的访问。假设我们的索引是B树结构的,那么index scan就是访问B树中的每一个节点。
- 假如索引是聚集索引,那么B树索引的叶子节点保存的是数据页中的实际数据。假如索引是非聚集索引,那么B树叶子节点保存的是指向数据页的指针。
(ps:以下2.1-2.6于2012-9-4补充)
2.1实验数据准备
在介绍完clustered index scan,table scan和index scan以后,我们将通过实验来表述会在什么情况下使用这些表扫描方式。我们将使用AdventureWorks2008R2这个sample database进行实验,首先准备实验数据,TSQL如下所示:
--准备测试数据--------------------------------------------------
use adventureworks2008R2
go
--如果表已存在,删除
drop table dbo.SalesOrderHeader_test
go
drop table dbo.SalesOrderDetail_test
go
--创建表
select * into dbo.SalesOrderHeader_test
from Sales.SalesOrderHeader
go
select * into dbo.SalesOrderDetail_test
from Sales.SalesOrderDetail
go
--创建索引
create clustered index SalesOrderHeader_test_CL
on dbo.SalesOrderHeader_test (SalesOrderID)
go
create index SalesOrderDetail_test_NCL
on dbo.SalesOrderDetail_test (SalesOrderID)
go
--select * from dbo.SalesOrderDetail_test
--select * from dbo.SalesOrderHeader_test
declare @i int
set @i = 1
while @i<=9
begin
insert into dbo.SalesOrderHeader_test
(RevisionNumber, OrderDate, DueDate,
ShipDate,Status, OnlineOrderFlag, SalesOrderNumber,PurchaseOrderNumber,
AccountNumber, CustomerID, SalesPersonID, TerritoryID,
BillToAddressID, ShipToAddressID, ShipMethodID, CreditCardID,
CreditCardApprovalCode, CurrencyRateID, SubTotal,TaxAmt,
Freight,TotalDue, Comment,rowguid,ModifiedDate)
select RevisionNumber, OrderDate, DueDate,
ShipDate,Status, OnlineOrderFlag, SalesOrderNumber,PurchaseOrderNumber,
AccountNumber, CustomerID,SalesPersonID, TerritoryID,
BillToAddressID, ShipToAddressID, ShipMethodID, CreditCardID,
CreditCardApprovalCode, CurrencyRateID, SubTotal,TaxAmt,
Freight,TotalDue, Comment,rowguid,ModifiedDate
from dbo.SalesOrderHeader_test
where SalesOrderID = 75123
insert into dbo.SalesOrderDetail_test
(SalesOrderID, CarrierTrackingNumber, OrderQty, ProductID,
SpecialOfferID,UnitPrice,UnitPriceDiscount,LineTotal,
rowguid,ModifiedDate)
select 75123+@i, CarrierTrackingNumber, OrderQty, ProductID,
SpecialOfferID,UnitPrice,UnitPriceDiscount,LineTotal,
rowguid, getdate()
from Sales.SalesOrderDetail
set @i = @i +1
end
go
--数据准备完毕--------------------------------