当前位置: 代码迷 >> Sql Server >> 海量数据库相关处理有关问题
  详细解决方案

海量数据库相关处理有关问题

热度:69   发布时间:2016-04-27 19:11:43.0
海量数据库相关处理问题
1、因为之前没做过大数据处理项目,陆续在这里请教过不少类似的问题,很多大侠热心的帮助了我。
为了方便这里的大侠们了解,我尽量仔细的说明:
之前的三个帖子,比较新一点,回复过的大侠可以很快的了解我的问题所在:
http://topic.csdn.net/u/20090907/10/627bfeec-8bda-4d99-aded-e13435e7c4fe.html
http://topic.csdn.net/u/20090907/16/80f35fbd-3c6c-4ca0-80f7-d55806bf0ddf.html
http://topic.csdn.net/u/20090901/09/b3cd8e71-19be-4694-b43b-0e57cdf4bef2.html

2、针对举例的第二个贴子,为了方便描述,我在这里根据大侠的提议,提出我这边数据搜索的整个问题,分数100;如果系统允许的话,我可以加分数,这个系列问题困扰了我很久;本来我还在尝试用前面几楼提议的去优化,但是感觉真的怎么优化都不咋样····现在50多W的数据,搜索的时候已经很慢了,特别是关键字没有匹配的时候,会全表遍历2边,很慢。(一遍是获取相关总记录数:用于分页(用的是开源的AspNetPager),一遍是获取相关的记录)

3、简单介绍一下这个数据库和硬件,主要用来查询一些信息,目前50W左右数据,以后的话,至少是几百w的数据,甚至是上kw(这个目前先不考虑);存放的是独立托管的一台至强系列服务器,4核,4G内存。数据库和程序放开存放不同的盘符(也可以做到分开存放到2台服务器--如果效率会快的话);系统如果说要跟什么像,有点类似搜索引擎。

4、数据库表:相关的几张表简单描述: InfoTmp、InfoReal、KeyTmp、KeyReal、MyCounry、MyCategory、MyTopic
【InfoTmp】:用于存放临时数据,这些数据都是人工添加的,只有通过审核才会加入InfoReal表;
【InfoReal】:正式数据,用于前台显示;
【KeyTmp】:第3点说到有点类似搜索引擎,就是在这里,用户每搜索一次的关键字,会加入到这个KeyTmp,然后通过计划任务,每天24点,整理后(相同的关键字合并,统计数量;如果正式key表存在则加数量,不存在则新加记录)加入KeyReal;
【MyCounry、MyCategory、MyTopic】:分别存放的是国家,类别,主题信息。
表结构简单举例:
【InfoReal】
[CI_ID],[CI_CorpName],[Country_Continent],[Country_ID],[C_FatherID],[C_ChildID],[CI_MobilePhone],[CI_StateFlag],[CI_CreateTime],[CI_ModifyTime],[CI_ClickTimes],[CI_BuyTimes],[CI_Keywords],[CI_SearchKey]
,[topic_ID],[CI_Charge].......

主要问题所在的存放内容举例: 
----------------------------- 
CI_ID C_FatherID C_ChildID 
10024 1024,1025,1056, 1045,1088,1045,1054,1063, 
10025 1024,1025,1056, 1045,1088,1045,1054,1063, 

----------------------------- 
-----------------------------
【MyCategory】存放内容举例: C_FatherID:0表示为大类
C_ID C_FatherID 
1024 0  
1045 1024 
1054 1025 
-----------------------------
-----------------------------
【MyCounry】存放内容举例: Country_Continent:表示洲,1亚洲,2欧洲....
Country_ID Country_Continent
1024 1  
1045 2
1054 3
-----------------------------
-----------------------------
问题描述:最初的主表设计,信息对于类别(国家,类别,主题是唯一对应的),后来项目已经做好了,领导要求修改:一条信息可以属于多个小类别(也可以属于不同的大类)。于是我把InfoReal的[C_FatherID],[C_ChildID]都改为了字符型,存放的内容见上面内容举例。
再则,最初是没有C_FatherID和Country_Continent;最初数据搜索,都是选择一个大类,然后选择相关小类;国家也一样,先选择洲,然后选择具体国家;后来需求改变,改成了,可以选择1个洲或者多个国家(可以属于不同洲);1个大类或者多个小类(可以属于不同大类);同时还有主题,价格,排序等一些附加搜索条件...于是我陆续在这里请教了一些问题。最初因为项目结构都搞好了,我实在不想改动,后来结合大家的意见和搜索速度实在慢,感觉非常有必要改动。于是我开了这个帖子。

下面我贴出取数据列表的存储过程并做简单说明:
SQL code
ALTER PROCEDURE [dbo].[corpListRealUser]    -- Add the parameters for the stored procedure here    @myContinent varchar(10),    --传入洲的值    @myCountrys varchar(50), --传入国家的值;已处理成sql条件语句,后面说明    @myCategoryB varchar(10), --传入大类的值    @myCategorys varchar(50), --传入小类的值;已处理成sql条件语句,后面说明    @myTopic decimal,  --传入主题的ID    @myPriceL int,  --传入价格范围的起始         @myPriceH int,  --传入价格范围的终点    @myOrderType int,  --传入排序类型(按时间,价格,点击量,购买量)         @myOrderFlag int,  --传入排序标志(升序还是降序)    @mySerKeyword varchar(500),  --传入关键字    @CI_StartRecordIndex int,  --传入分页起始点    @CI_EndRecordIndex int   --传入分页终结点ASBEGIN    -- SET NOCOUNT ON added to prevent extra result sets from    -- interfering with SELECT statements.    SET NOCOUNT ON;    -- Insert statements for procedure here    declare @str varchar(max),@strOrder varchar(200)    set @str=''        if @myTopic>0        begin        set @[email protected]+'and topic_ID='+rtrim(@myTopic)        end    if @myPriceH<500        begin        set @[email protected]+' and CI_Charge BETWEEN '+rtrim(@myPriceL)+' AND '+rtrim(@myPriceH)        end    if @myContinent<>'0'        begin        set @[email protected]+'and Country_Continent='+rtrim(@myContinent)        end    if @myCountry<>'0'        begin        set @[email protected][email protected]        end    if @myCategoryB<>'0'        begin        set @[email protected]+'and C_FatherID='+rtrim(@myCategoryB)        end    if @myCategoryS<>'0'        begin        set @[email protected][email protected]        end[b]--这里的myCountrys和myCategorys都已在前台程序处理成:and (charindex(',195,',','+InfoReal.C_ChildID)> 0 or charindex(',81,',','+InfoReal.C_ChildID)> 0 or charindex(',64,',','+InfoReal.C_ChildID)> 0-----这种语句,结合我最上面举例到的三个帖子,大侠的给我建议是把charindex改为like;然后把or,改为union all模式-----因为语句的问题,还有其他条件,改成union all我也是比较的懵,不太会改;然后第二个帖子提到了,结构问题,很关键,让我意识到我不改结构,其实速度是无法改变慢的局面的。[/b]    if @mySerKeyword<>''        begin            set @[email protected]+'and (CI_SearchKey like ''%'+ @mySerKeyword +'%'')'        end--以下部分是排序条件    set @strOrder=''    declare @orderPX varchar(10)    if @myOrderFlag=1        set @orderPX=' asc'    else        set @orderPX=' desc'    if @myOrderType=1        begin                        set @[email protected]+'order by [email protected]            end    else if @myOrderType=2        begin                        set @[email protected]+'order by [email protected]            end    else if @myOrderType=3        begin                        set @[email protected]+'order by [email protected]            end    else if @myOrderType=4        begin                        set @[email protected]+'order by [email protected]            end    else        begin                        set @[email protected]+'order by [email protected]            end    --下面部分简单说明:1、infoReal表为了加快速度,最初关键字搜索匹配是跟CI_CorpName和CI_Keywords和CI_Profile用or连接;后来加了CI_SearchKey这个字段,取值是把前面三个字段值结合,然后截取250个字符做的搜索关键字。2、为了加快速度,我最大也只取600条数据;如果数据库匹配的数据多,速度是相对快点,如果没有匹配或者没有达到600条,就会表全部扫描一遍(加上分页读取记录总数,相当于2边),速度就相对比较慢。3、搜索相关的条件字段我都有做索引,CI_ID是主键唯一,聚集索引我是做在了CI_SearchKey这个字段上(就是搜索关键字)4、CI_StateFlag=1 or CI_StateFlag=3这里我用了OR结构是不是索引也不起效果了??这个字段是用来判断数据是否在前台显示的判断标识符。    declare @sql varchar(max)    set @sql = 'select * from     (select top 600 row_number() over ('+rtrim(@strOrder)+',CI_ID desc)as Row,    CI_ID,CI_CorpName,CI_Profile,CI_StateFlag,CI_Charge,CI_ModifyTime,CI_ClickTimes,CI_BuyTimes,Country_ID from TE_CorpInfoReal where (CI_StateFlag=1 or CI_StateFlag=3) [email protected]+') t           WHERE 1=1 AND Row BETWEEN '+rtrim(@CI_StartRecordIndex)+' AND '+rtrim(@CI_EndRecordIndex)+' order by row'    exec(@sql)END
  相关解决方案