sql2000索引的问题

qq_17208157 2014-07-03 05:01:30

SELECT a.OrderId,b.Sku
FROM Order a, OrderDetail b WHERE a.OrderId = b.OrderId

这种情况下 OrderDetail的组合索引会使用到


SELECT a.OrderId,b.SKu,b.Qty
FROM Order a,OrderDetail b WHERE a.OrderId = b.OrderId

这种情况下 OrderDetail的组合索引就失效了。

OrderDetail的组合索引是这样建立的。

Create Index i_OrderId_SKu ON OrderDetail(OrderId,Sku)


不知道是不是我对索引理解有错误。。。 还请高手讲解下. 我的理解第二种查询多了一个字段 b.Qty 应该是可以利用到索引的。
...全文
147 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
發糞塗牆 2014-07-03
  • 打赏
  • 举报
回复
主键默认是聚集索引,理论上不应该存在table scan
qq_17208157 2014-07-03
  • 打赏
  • 举报
回复
引用 16 楼 ap0405140 的回复:

SELECT a.OrderId,b.SKu,b.Qty
FROM Order a,OrderDetail b WHERE a.OrderId = b.OrderId
这是查询所有Order的资料, 返回的数据量比较大, 实际应用中应该很少这么用吧? 这时即使是有索引也不定会用的(因为用索引的成本反而高过直接去全表扫描). 建议: 1.只建OrderId的非聚集索引, OrderDetail(OrderId) 2.查询时尽量加上过滤条件,减少无需返回的数据量. 如加OrderID,日期区间,客户ID,Order状态等. 3.检查索引碎片情况,定时的重建/重整索引. 4.检查SQL2000 SP4补丁是否已安装.
回版主,SP4已经打了。 "这时即使是有索引也不定会用的(因为用索引的成本反而高过直接去全表扫描)."  我现在自己也比较认同,这个原因。 多谢各位的帮助。
qq_17208157 2014-07-03
  • 打赏
  • 举报
回复
不好意思,刚有点忙。 OrderDetail 只是加了一个 identity 的主键
唐诗三百首 2014-07-03
  • 打赏
  • 举报
回复

SELECT a.OrderId,b.SKu,b.Qty
FROM Order a,OrderDetail b WHERE a.OrderId = b.OrderId
这是查询所有Order的资料, 返回的数据量比较大, 实际应用中应该很少这么用吧? 这时即使是有索引也不定会用的(因为用索引的成本反而高过直接去全表扫描). 建议: 1.只建OrderId的非聚集索引, OrderDetail(OrderId) 2.查询时尽量加上过滤条件,减少无需返回的数据量. 如加OrderID,日期区间,客户ID,Order状态等. 3.检查索引碎片情况,定时的重建/重整索引. 4.检查SQL2000 SP4补丁是否已安装.
發糞塗牆 2014-07-03
  • 打赏
  • 举报
回复
OrderDetail 的主键是哪列?
qq_17208157 2014-07-03
  • 打赏
  • 举报
回复
引用 13 楼 DBA_Huangzj 的回复:
有10几个字段,基本上要走聚集索引扫描/查找
不好意思,没有完全理解。
發糞塗牆 2014-07-03
  • 打赏
  • 举报
回复
有10几个字段,基本上要走聚集索引扫描/查找
qq_17208157 2014-07-03
  • 打赏
  • 举报
回复
回大版:   2000不支持计算列的。   OrderDetail 的主键其实是一个 Identity. 查询字段 OrderId, Sku,Qty,Cost,Price,Name, 有10多个字段。所以我基本对将查询字段加组合索引这个方案放弃了。 好头疼,出现这样的问题。。。
發糞塗牆 2014-07-03
  • 打赏
  • 举报
回复
SELECT a.OrderId,b.SKu,b.Qty,b.cost,b.cost*b.Qty AS Price FROM Order a,OrderDetail b WHERE a.OrderId = b.OrderId 针对这个查询的建议: 1、加一列计算列,直接计算cost*Qty的结果,这样可以减少运算的开销,计算列是一个列,比如: create table test(a int ,b int , a*b as c ) --其中c就是计算列,每次a、b插入时自动计算出结果存起来,你只需要在C中加上索引即可。但是很久没用2000了,我不记得2000支不支持。反正2005是支持的。 2、order 表,orderid一定要有索引,不管是聚集还是非聚集。OrderDetail表,orderid,sku,qty,cost这个组合一个索引试试,如果detail表的orderid上有聚集索引,只需要用后面三列
發糞塗牆 2014-07-03
  • 打赏
  • 举报
回复
table scan?你的表没主键?
qq_17208157 2014-07-03
  • 打赏
  • 举报
回复
引用 6 楼 DBA_Huangzj 的回复:
如果你要查的列非常多,那估计还是走聚集索引查找/扫描居多,但是where条件用到的还是建议加上一个非聚集索引
回版主,确定查询列比较多。

SELECT a.OrderId,b.SKu,b.Qty,b.cost,b.cost*b.Qty AS Price
FROM Order a,OrderDetail b WHERE a.OrderId = b.OrderId

类似于这样的。。 这下真的头疼了。 刚测试了下,如果只查询 Detail表里的组合索引的几个字段。 查询只要20秒。 如果加了一个qty . 3分钟也没出来数据。
qq_17208157 2014-07-03
  • 打赏
  • 举报
回复
引用 4 楼 AcHerat 的回复:
给单个OrderId创建非聚集索引。
多谢回复,刚尝试了下 建立之后,还是 Table Scan.
發糞塗牆 2014-07-03
  • 打赏
  • 举报
回复
大部分情况下,“不建议”的操作是:每列一个索引
發糞塗牆 2014-07-03
  • 打赏
  • 举报
回复
如果你要查的列非常多,那估计还是走聚集索引查找/扫描居多,但是where条件用到的还是建议加上一个非聚集索引
發糞塗牆 2014-07-03
  • 打赏
  • 举报
回复
2000的话比较难,2005及以上版本可以考虑用include索引,但是2000也不是很死板,可以通过多个非聚集索引进行“索引交叉”查询,这个很大程度取决于哪个操作的开销低(sqlserver是基于开销的优化)。如果你要查询的列不是非常多,那么建一个或者少量几个非聚集索引,2000有个需要注意的地方,where条件中的列顺序要和索引定义中的一模一样才有用,否则一样无用。2005没测过,2008已经消除了这个限制。
AcHerat 2014-07-03
  • 打赏
  • 举报
回复
给单个OrderId创建非聚集索引。
qq_17208157 2014-07-03
  • 打赏
  • 举报
回复
多谢大版。  我想问下,这种问题有没有其它变通的办法,因为 OrderDetail 里还有其它字段需要 Select 出来.
發糞塗牆 2014-07-03
  • 打赏
  • 举报
回复
qty多出来之后,由于优化器不能从i_OrderId_SKu这个索引中直接得到数据,所以应该会引入一个叫书签查找的操作,通过聚集索引或者堆的RID把qty的数据也查出来,如果直接扫描堆表或者聚集索引比非聚集索引+书签查找更低开销,那么会出现你说的索引没用到的情况
發糞塗牆 2014-07-03
  • 打赏
  • 举报
回复
这个要加上这个索引:Create Index i_OrderId_SKu ON OrderDetail(OrderId,Sku,Qty) 2000的索引比较没那么聪明

22,206

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧