请教Sqlserver2000建索引问题,谢谢

时间:2022-04-24 21:18:02
请教一个sql建索引的问题:
1、有这样一张表:

CREATE TABLE [dbo].[CUBE_Sales_ByBrand]
(
 [Id] [bigint] IDENTITY(1,1) NOT NULL,
 [RsYear] [int] NOT NULL,
 [RsMonth] [int] NOT NULL,
 [RsWeek] [int] NOT NULL,
 [RsDay] [int] NOT NULL,
 [Sdate] [datetime] NOT NULL,
 [CompanyCode] [varchar](50) NULL,
 [CompanyName] [varchar](50) NULL,
 [OrgCode] [varchar](50) NULL,
 [OrgName] [varchar](50) NULL,
 [ChannelId] [int] NOT NULL,
 [OutletCode] [varchar](50) NOT NULL,
 [OutletName] [varchar](50) NOT NULL,
 [EmpCode] [varchar](50) NULL,
 [EmpName] [varchar](50) NULL,
 [BrandCode] [varchar](50) NOT NULL,
 [BrandName] [varchar](50) NOT NULL,
 [MoneyXiaoshou] [decimal](18, 2) NULL,
 [MoneyLingshou] [decimal](18, 2) NULL,
 [MoneyDadan] [decimal](18, 2) NULL,
 [MoneyJiazhuang] [decimal](18, 2) NULL,
 [MoneyTuangou] [decimal](18, 2) NULL,
 [MoneyTuihuo] [decimal](18, 2) NULL


2、查询时where后经常用到 RsYear,RsMonth,RsWeek,RsDay,Sdate,OutletCode,OrgCode,BrandCode 做为条件。
3、当数据量比较大时,请问该如何建索引,谢谢。


ChannelId也会用到,不过比较少

8 个解决方案

#1


最常用的几个,键个联合索引

#2


按順序建立複合索引

#3


怎样才能充分利用SQL索引 
     背景:目前WEB的普及太快,很多网站都会因为大流量的数据而发生服务器习惯性死机,一个查询语句只能适用于一定的网络环境.没有优化的查询当遇上大数据量时就不适用了.

     本文主旨:讨论什么情况下能利用上索引.

     索引:创建索引可以根据查询业务的不同分为两种:单一列的索引,联合索引. 顾名思义,单一列索引就是指在表的某一列上创建索引,联合索引是在多个列上联合创建索引.

     优缺点比较: 


         1):索引所占用空间:单一列索引相对要小.

         2):索引创建时间:单一列索引相对短. 


         3):索引对insert,update,delete的影响程序:单一列索引要相对低. 


         4):在多条件查询时,联合索引效率要高. 


    索引的使用范围:单一列索引可以出现在where 条件中的任何位置,而联合索引需要按一定的顺序来写. 


    本文所用测试软件环境如下:SQL05   

      DEMO:创建一个人员表,包含人员ID,姓名.在人员ID上创建一个聚集索引,在first_name和last_name上创建一个联合

索引.  


create table person (id int, last_name varchar(30), first_name varchar(30))
create unique clustered index person_id on person (id)
create index person_name on person (last_name, first_name)

     

     在上例中,id上创建了聚集索引,下面的查询都会用了聚集索引. 


    where id=1
    where id>1
    where id<1
    where id between 1 and n
    where id like '1%'

    where id in(1,2,3...)

     说明:  id 列出现在条件中的位置并不一定要求第一列,不受位置影响.

     不过下面的查询方式则不会用上聚集索引.
    where person_id +1=n
    where person_id like '%5'
    where person_id like '%5%'
    where person_id abs(15)

    联合索引列比起单一列索引最大的好处在于,对于多条件的查询它比起单一列索引更加精确.拿上面的人员表来说吧,如果

要查询一个人的全名,只知道first_name是很难马上找到这个人的全名的,如果知道first_name和last_name则会非常容易找到.下面根据不同的条件与输出列顺序说明索引的应用.

     第一种情况:--条件和输出列和索引列顺序相同
select last_name,first_name from person where last_name='1' and first_name='1'
stmtText
Index Seek(OBJECT:([bdg_web_vaction].[dbo].[person].[person_name]), 
SEEK:([bdg_web_vaction].[dbo].[person].[last_name]=[@1] 

AND [bdg_web_vaction].[dbo].[person].[first_name]=[@2]) ORDERED FORWARD)

      结果:利用person_name联合索引查找

      第二种情况:--条件列与索引列顺序不同,但输出列相同
select last_name,first_name from person where first_name='1' and last_name='1'
stmtText
Index Seek(OBJECT:([bdg_web_vaction].[dbo].[person].[person_name]), 
SEEK:([bdg_web_vaction].[dbo].[person].[last_name]=[@2] AND [bdg_web_vaction].
[dbo].[person].[first_name]=[@1]) ORDERED FORWARD)

 

       结果:利用person_name联合索引查找


       第三种情况:--条件列与输出列与索引列的顺序都不相同
select first_name,last_name from person where first_name='1' and last_name='1'
Index Seek(OBJECT:([bdg_web_vaction].[dbo].[person].[person_name]), 
SEEK:([bdg_web_vaction].[dbo].[person].
[last_name]=[@2] AND [bdg_web_vaction].[dbo].[person].[first_name]=[@1]) ORDERED FORWARD) 

 

        结果:利用person_name联合索引查找


        第四种情况:--条件列在first_name和last_name中间加入另外一个条件
SELECT id, first_name,last_name from person where first_name='1' AND  id=1 and last_name='1'
     Clustered Index Seek(OBJECT:([bdg_web_vaction].[dbo].[person].[person_id]),
 SEEK:([bdg_web_vaction].[dbo].[person].[id]=CONVERT_IMPLICIT(int,[@2],0)),  
WHERE:([bdg_web_vaction].[dbo].[person].[first_name]=[@1] AND [bdg_web_vaction].[dbo].[person].[las

        结果:不能利用person_name联合索引查找

       第五种情况:--在输出列中分开first_name和last_name
SELECT  first_name,id,last_name from person where first_name='1' and last_name='1'
Index Seek(OBJECT:([bdg_web_vaction].[dbo].[person].[person_name]),
 SEEK:([bdg_web_vaction].[dbo].[person].
[last_name]=[@2] AND [bdg_web_vaction].[dbo].[person].[first_name]=[@1])
 ORDERED FORWARD) 

 

       结果:利用person_name联合索引查找


       第六种情况:条件列没有出现联合索引的第一列
SELECT  first_name,id,last_name from person where first_name='1'
SELECT  first_name,last_name from person where first_name='1'
SELECT  last_name ,first_name from person where first_name='1'

Index Scan(OBJECT:([bdg_web_vaction].[dbo].[person].[person_name]),

  WHERE:([bdg_web_vaction].[dbo].[person].[first_name]=[@1])) 

 

       结果:不能利用person_name联合索引.

      第七种情况:--条件列出现联合索引的第一列
SELECT  first_name,id,last_name from person where last_name='1'
SELECT  first_name,last_name from person where last_name='1'
SELECT  last_name ,first_name from person where last_name='1'
Index Seek(OBJECT:([bdg_web_vaction].[dbo].[person].[person_name]),
 SEEK:([bdg_web_vaction].[dbo].[person].[last_name]=[@1]) ORDERED FORWARD) 

 

      结果:利用person_name联合索引查找

      联合索引使用总结:

         1):查询条件中出现联合索引第一列,或者全部,则能利用联合索引.


         2):条件列中只要条件相连在一起,以本文例子来说就是:

              last_name='1' and first_name='1'

              与

              first_name='1' and last_name='1' 


                 ,无论前后,都会利用上联合索引.


         3):查询条件中没有出现联合索引的第一列,而出现联合索引的第二列,或者第三列,都不会利用联合索引查询. 


     单一列索引的应用总结:

          1):只要条件列中出现索引列,无论在什么位置,都能利用索引查询.


      两者的共同点:

          1):要想利用索引,都要符合SARG标准.

          2) :都是为了提高查询速度.

          3):都需要额外的系统开销,磁盘空间.


     补充说明: stmtText信息来产生,在查询语句前面加上:SET STATISTICS PROFILE on.可以通过运行它,来观察你的查询是否合理,这样才能真正做到优化.

      总结:即使表上创建了索引,但如果查询语句写的不科学的话(不符合SARG标准),也于事无补,要根据表索引情况来优化查询语句,如没有合适的索引可用,则要创建相应索引.

#4


经常同时用的话, 所有列建立一个复合索引, 在顺序上, 列的宽度小, 能够通过该列条件把数据量限制在最少的, 应该优先出现

经常是几个条件组合的话, 根据同时出现在组合中的情况来确定建立几个索引

如果列值仅有几个, 除非查询的值能够把数据量限制在很小范围, 否则不考虑建立索引

#5


把最常用来查询的字段建立索引,索引的建立并不是越多越好,他也是很占空间的。而且聚集索引还是会以第一个字符作为优先搜索的条件。

#6


另外, 建议把你的自增列设置为主键

除非你的表中只有为很少量的索引, 并且通过这些索引列上的条件能把数据量过滤到很小的值, 否则你的表中都应该包含一个宽度很小的列做为主键(聚集的, 一般为选择自增列)

#7


引用 4 楼 zjcxc 的回复:
经常同时用的话, 所有列建立一个复合索引, 在顺序上, 列的宽度小, 能够通过该列条件把数据量限制在最少的, 应该优先出现 

经常是几个条件组合的话, 根据同时出现在组合中的情况来确定建立几个索引 

如果列值仅有几个, 除非查询的值能够把数据量限制在很小范围, 否则不考虑建立索引 


是的,自己还是要县分析一下表里面满足条件的行数各列是一个什么情况

#8


mark!

#1


最常用的几个,键个联合索引

#2


按順序建立複合索引

#3


怎样才能充分利用SQL索引 
     背景:目前WEB的普及太快,很多网站都会因为大流量的数据而发生服务器习惯性死机,一个查询语句只能适用于一定的网络环境.没有优化的查询当遇上大数据量时就不适用了.

     本文主旨:讨论什么情况下能利用上索引.

     索引:创建索引可以根据查询业务的不同分为两种:单一列的索引,联合索引. 顾名思义,单一列索引就是指在表的某一列上创建索引,联合索引是在多个列上联合创建索引.

     优缺点比较: 


         1):索引所占用空间:单一列索引相对要小.

         2):索引创建时间:单一列索引相对短. 


         3):索引对insert,update,delete的影响程序:单一列索引要相对低. 


         4):在多条件查询时,联合索引效率要高. 


    索引的使用范围:单一列索引可以出现在where 条件中的任何位置,而联合索引需要按一定的顺序来写. 


    本文所用测试软件环境如下:SQL05   

      DEMO:创建一个人员表,包含人员ID,姓名.在人员ID上创建一个聚集索引,在first_name和last_name上创建一个联合

索引.  


create table person (id int, last_name varchar(30), first_name varchar(30))
create unique clustered index person_id on person (id)
create index person_name on person (last_name, first_name)

     

     在上例中,id上创建了聚集索引,下面的查询都会用了聚集索引. 


    where id=1
    where id>1
    where id<1
    where id between 1 and n
    where id like '1%'

    where id in(1,2,3...)

     说明:  id 列出现在条件中的位置并不一定要求第一列,不受位置影响.

     不过下面的查询方式则不会用上聚集索引.
    where person_id +1=n
    where person_id like '%5'
    where person_id like '%5%'
    where person_id abs(15)

    联合索引列比起单一列索引最大的好处在于,对于多条件的查询它比起单一列索引更加精确.拿上面的人员表来说吧,如果

要查询一个人的全名,只知道first_name是很难马上找到这个人的全名的,如果知道first_name和last_name则会非常容易找到.下面根据不同的条件与输出列顺序说明索引的应用.

     第一种情况:--条件和输出列和索引列顺序相同
select last_name,first_name from person where last_name='1' and first_name='1'
stmtText
Index Seek(OBJECT:([bdg_web_vaction].[dbo].[person].[person_name]), 
SEEK:([bdg_web_vaction].[dbo].[person].[last_name]=[@1] 

AND [bdg_web_vaction].[dbo].[person].[first_name]=[@2]) ORDERED FORWARD)

      结果:利用person_name联合索引查找

      第二种情况:--条件列与索引列顺序不同,但输出列相同
select last_name,first_name from person where first_name='1' and last_name='1'
stmtText
Index Seek(OBJECT:([bdg_web_vaction].[dbo].[person].[person_name]), 
SEEK:([bdg_web_vaction].[dbo].[person].[last_name]=[@2] AND [bdg_web_vaction].
[dbo].[person].[first_name]=[@1]) ORDERED FORWARD)

 

       结果:利用person_name联合索引查找


       第三种情况:--条件列与输出列与索引列的顺序都不相同
select first_name,last_name from person where first_name='1' and last_name='1'
Index Seek(OBJECT:([bdg_web_vaction].[dbo].[person].[person_name]), 
SEEK:([bdg_web_vaction].[dbo].[person].
[last_name]=[@2] AND [bdg_web_vaction].[dbo].[person].[first_name]=[@1]) ORDERED FORWARD) 

 

        结果:利用person_name联合索引查找


        第四种情况:--条件列在first_name和last_name中间加入另外一个条件
SELECT id, first_name,last_name from person where first_name='1' AND  id=1 and last_name='1'
     Clustered Index Seek(OBJECT:([bdg_web_vaction].[dbo].[person].[person_id]),
 SEEK:([bdg_web_vaction].[dbo].[person].[id]=CONVERT_IMPLICIT(int,[@2],0)),  
WHERE:([bdg_web_vaction].[dbo].[person].[first_name]=[@1] AND [bdg_web_vaction].[dbo].[person].[las

        结果:不能利用person_name联合索引查找

       第五种情况:--在输出列中分开first_name和last_name
SELECT  first_name,id,last_name from person where first_name='1' and last_name='1'
Index Seek(OBJECT:([bdg_web_vaction].[dbo].[person].[person_name]),
 SEEK:([bdg_web_vaction].[dbo].[person].
[last_name]=[@2] AND [bdg_web_vaction].[dbo].[person].[first_name]=[@1])
 ORDERED FORWARD) 

 

       结果:利用person_name联合索引查找


       第六种情况:条件列没有出现联合索引的第一列
SELECT  first_name,id,last_name from person where first_name='1'
SELECT  first_name,last_name from person where first_name='1'
SELECT  last_name ,first_name from person where first_name='1'

Index Scan(OBJECT:([bdg_web_vaction].[dbo].[person].[person_name]),

  WHERE:([bdg_web_vaction].[dbo].[person].[first_name]=[@1])) 

 

       结果:不能利用person_name联合索引.

      第七种情况:--条件列出现联合索引的第一列
SELECT  first_name,id,last_name from person where last_name='1'
SELECT  first_name,last_name from person where last_name='1'
SELECT  last_name ,first_name from person where last_name='1'
Index Seek(OBJECT:([bdg_web_vaction].[dbo].[person].[person_name]),
 SEEK:([bdg_web_vaction].[dbo].[person].[last_name]=[@1]) ORDERED FORWARD) 

 

      结果:利用person_name联合索引查找

      联合索引使用总结:

         1):查询条件中出现联合索引第一列,或者全部,则能利用联合索引.


         2):条件列中只要条件相连在一起,以本文例子来说就是:

              last_name='1' and first_name='1'

              与

              first_name='1' and last_name='1' 


                 ,无论前后,都会利用上联合索引.


         3):查询条件中没有出现联合索引的第一列,而出现联合索引的第二列,或者第三列,都不会利用联合索引查询. 


     单一列索引的应用总结:

          1):只要条件列中出现索引列,无论在什么位置,都能利用索引查询.


      两者的共同点:

          1):要想利用索引,都要符合SARG标准.

          2) :都是为了提高查询速度.

          3):都需要额外的系统开销,磁盘空间.


     补充说明: stmtText信息来产生,在查询语句前面加上:SET STATISTICS PROFILE on.可以通过运行它,来观察你的查询是否合理,这样才能真正做到优化.

      总结:即使表上创建了索引,但如果查询语句写的不科学的话(不符合SARG标准),也于事无补,要根据表索引情况来优化查询语句,如没有合适的索引可用,则要创建相应索引.

#4


经常同时用的话, 所有列建立一个复合索引, 在顺序上, 列的宽度小, 能够通过该列条件把数据量限制在最少的, 应该优先出现

经常是几个条件组合的话, 根据同时出现在组合中的情况来确定建立几个索引

如果列值仅有几个, 除非查询的值能够把数据量限制在很小范围, 否则不考虑建立索引

#5


把最常用来查询的字段建立索引,索引的建立并不是越多越好,他也是很占空间的。而且聚集索引还是会以第一个字符作为优先搜索的条件。

#6


另外, 建议把你的自增列设置为主键

除非你的表中只有为很少量的索引, 并且通过这些索引列上的条件能把数据量过滤到很小的值, 否则你的表中都应该包含一个宽度很小的列做为主键(聚集的, 一般为选择自增列)

#7


引用 4 楼 zjcxc 的回复:
经常同时用的话, 所有列建立一个复合索引, 在顺序上, 列的宽度小, 能够通过该列条件把数据量限制在最少的, 应该优先出现 

经常是几个条件组合的话, 根据同时出现在组合中的情况来确定建立几个索引 

如果列值仅有几个, 除非查询的值能够把数据量限制在很小范围, 否则不考虑建立索引 


是的,自己还是要县分析一下表里面满足条件的行数各列是一个什么情况

#8


mark!