日期:2014-05-18  浏览次数:20487 次

海量数据表的索引问题?
现有一个表,表的结构如下:
[name1](varchar) 
[name1](varchar) 
[日期](varchar) 
[时间](varchar) 
[数据1](real) 
[数据2](real) 
[数据3](real)
......
[标式列](smallint)

数据库是按月进行存储的,每个小时需要向这个表中插入6-20万行的记录,并且在新的数据入库后要根据[标式列(初始值为空,汇总后设为1)]中不为1的所有数据(除了标式列)进行汇总统计,汇总语句是:
select [name1],[name2],[日期],[时间],sum([数据1]),sum([数据2]),sum([数据2]),sum([数据3]).... from 海量数据表 where 标式列 <> 1 group by [name1],[name1],[日期],[时间]
现在建有的索引有:
组合聚集索引:cindex([name1],[name1],[日期],[时间])
非聚集索引:标式_index (标式列)

在其他的输出查询中是以[name1],[name1],[日期],[时间]中一个或多个为条件进行查询

问题:如何建立聚集索引和非聚集索引才能使数据插入及表数据的查询速度不会太慢,上面的所建的索引能否符合要求

注:[name1],[name1],[日期],[时间] 四列才能确定唯一记录  


------解决方案--------------------
且每月把表做月結動作,,,
放入歷史表,,,
還慢可以考慮以周為單位把表做分區表,,,



------解决方案--------------------
那就在用户端限制,,禁止一周以上的查询
或者凡是超过数天,,,在查询前,,先运行 count(*)到底会导致多少笔数据输出
凡是超标禁止
就成了吧,,
查询的时候尽量用存储过程噶,,,
还不行,,,就做分区表吧,,,
使用多个硬盘,,,把表分在多个硬盘上
只有慢慢调试
你机器性能。。内存也得要有一定水平
每天的维护做好
如果存在其他服务都喊他们搬家- -
有条件就把报表之的服务器分离,,
总之想办法实现你目标

毕竟MS是中型数据库,,,你要搞海量,,,就得付出点代价嘛- -
------解决方案--------------------
楼主最关注的是这条汇总语句太慢?还是其他SELECT查询太慢?

如果是汇总语句太慢,以下有两种办法供参考:
1、对海量基表建立索引视图,Create View V_基表(...) as Select * from 海量表 where 标示列=0
Create Index on V_基表([name1],[name1],[日期],[时间])
以后统计直接对这个索引视图统计就行了,统计完毕更新基表。
假设你基表有10亿条记录,标示列=0的有5千万条,以前你统计时会扫描到10亿条记录,而现在只需要扫
描5000万条记录就OK了,一点额外的I/O没有。即使原先统计时可以用到标示列的索引,使用索引视图也
可以比以前大大加快许多。
2、将海量表分拆成两个表,一个是标示列=1的,另一个是标示列=0的,建立一个普通视图将他们UNION起来,
查询时可以查询这个视图。统计时只统计标示列=0的表,在统计完毕后INSERT进另一个表。
不用担心INSERT速度会慢,实际上跟以前速度是差不多的,因为你以前统计完成后要UPDATE,这个UPDATE
即使仅改一个字段,也要重写一条记录,跟INSERT速度差不多。

如果你是担心其他的SELECT查询太慢,那要看你具体的SQL是怎么样的了。
------解决方案--------------------
算了一下大库的容量20万*24小时*30天*12=172800万,一年17亿的数据还是很可观了,所以我也很有兴趣为你分析一下,并提供一种解决方案,如果采纳请把效果附后说明
1,聚集索引最大的好处是查询的结果返回一个区间的值,特别是1个值,它的建立与字段自身的值有很大的关系,因为name1,name2不知道是什么意思,所以能确定这样建有什么好处。
2,聚集索引与是否唯一没有什么关系
3,建议日期在查询中是必须选择的,聚集索引为日期一个字段就够了
4,汇总不要在如大库时再做,要建临时表,临时表汇总完后,临时表入大库,删除临时表,大库不做update

------解决方案--------------------
从几个方面着手:
1.裁减废数据
2.建立分区,建立分区后,插入数据也会大大加快,你可以试试
3.建立分区索引,注意,字段尽可能的少.用选择性大的字段建立索引,1-2个字段就够了,字段太多影响查询速度

我们这里有一张表大概2000w条左右,每月150w条,按照月建立分区,每个区大概2.5g左右.查询日报表第一次基本上只需要20s,第二此大概14s.

注意你的服务器内存是不是太小,自己看一下数据缓存命中率,低于0.9就已经很不正常了.这样读取硬盘会很频繁.
------解决方案--------------------
我的看法:
1,首先,这是一个失败的查询系统和数据库设计,建索引和分区都不能解决大数据量查询的问题,因为4个查询项不能固定一个,也就不能针对查询进行优化。
2,数据库设计和查询是有很大的关联,查询有没有做限定,有没有默认区间,比如某公司只能查该公司的或者某省只能查该省的,数据库就没有办法优化。
3,name1和name2的分布是怎样的,比如英文是由26个字母组成,但d开头的英文要远远高于z开头的英文,这样的聚集索引效率就不高。
4,查询优化测试,你可以创建只有name1的聚集索引,然后查询条件包含name1,其他条件任选,看看查询速度,如果多余1000条,再看看返回前1000条的速度。

------解决方案--------------------
说明为什么要建4种聚集索引或分区
因为查询没有加限制,就是出现可以查询历年12月份的记录,如果按年分区就没有意义了,同样,在大类不选的情况下,只选小类也是要查询所有大类包含该小类的数据,如果按大类分区就没有意义了。
------解决方案--------------------
个人感觉,汇总语句select [name1],[name2],[日期],[时间],sum([数据1]),sum([数据2]),sum([数据2]),sum([数据3]).... from 海量数据表 where 标式列 <> 1 group by [name1],[name1],[日期],[时间] 
,无法利用索引,效率会很低;是否可以做一个服务,每天把汇总后的数据导入到另一个表,再供用户查询;

另外,目前建立的复合索引,只能利用在name1的情况,或者顺序一致,且有name1的查询;其他情况无法利用,因此建议再增加几个单独的索引,当然也要测试一下插入数据的情况;
再者,可以考虑限制业务,因为如果单独日期做条件,那就崩溃了!几十万条记录,所以,是否可以限制日期,时间,姓名,这三个为必须项;这样建索引就只需建一个;
最后,就是看IO了,是否可以多弄几个磁盘,数据文件分开放,日志文件、索引文件分开放。

等等,供楼主参考吧