销售数据表TH_ORDER每天差不多都会有40万行新的数据产生,而这些数据都是凌晨从指定的DB中同步过来。由于数据量过大,故将数据库进行分区。
TH_ORDER表中没有主键列,BUSINESS_DATE列为营业日期,不包含时分秒,也就是每天差不多有40万条相同的营业日期的数据。首先创建了分区函数如下
CREATE PARTITION FUNCTION pf_BUSINESS_DATE(SMALLDATETIME)
AS RANGE RIGHT FOR VALUES
(
'2012-01-01',
'2012-02-01',
'2012-03-01',
'2012-04-01',
'2012-05-01',
'2012-06-01',
'2012-07-01',
'2012-08-01',
'2012-09-01',
'2012-10-01',
'2012-11-01',
'2012-12-01'
)
分区架构
CREATE PARTITION SCHEME ps_BUSINESS_DATE
AS PARTITION pf_BUSINESS_DATE
TO ([PRIMARY],FG1, FG2, FG3,FG4, FG5, FG6,FG7, FG8, FG9,FG10, FG11, FG12)
由于Order表中已经存在数据。故给BUSINESS_DATE添加索引如下及分区架构:
CREATE NONCLUSTERED INDEX [IX_TH_ORDER_BUSSINESS_DATE] ON [dbo].[TH_ORDER]
(
[BUSINESS_DATE] DESC
) ON ps_BUSINESS_DATE([BUSINESS_DATE])
当表中有新数据也就是40万行新数据时,对表执行查询前一天的营业数据(新数据),会变的异常的慢,半个小时都不出数据,而查询前几天的数据就挺正常的。
所以就将索引删除后再添加:
DROP INDEX TH_ORDER.IX_TH_T_ORDER_BUSSINESS_DATE
CREATE NONCLUSTERED INDEX [IX_TH_ORDER_BUSSINESS_DATE] ON [dbo].[TH_ORDER]
(
[BUSINESS_DATE] DESC
) ON ps_BUSINESS_DATE([BUSINESS_DATE])
这样查询前一天的营业数据挺正常的,为啥重新创建索引后查询就正常了。
这该怎么优化呢?
------解决方案--------------------
如果你是想要按营业日期 BUSINESS_DATE 列对表进行分区,首先表里原来的聚集索引需要Drop,然后按照分区架构对 BUSINESS_DATE 建立聚集索引。
可是我看你的索引创建语句,建的非聚集索引,这样你表中数据应该没有分区。你可以看看文件组对应文件的大小,是否数据已经存在文件中了。
------解决方案--------------------
对于销售数据表,你经常的查询条件应该有时间条件吧,如果是的话,我建议你还是按营业日期 BUSINESS_DATE 列建聚集索引,对表中数据进行分区,然后再对经常查询,重复性不高的某列利用同样的分区架构建立非聚集索引,这样在查询时加上分区条件与新建索引的过滤条件,应该能提升性能。
------解决方案--------------------
最直接的办法,LZ看一下查询的语句 Ctrl+L 看一下执行计划。 里面如果没有用到分区索引,那你的查询当然会慢 。
如果Business_date 是第一个条件的话,而每天都会有40W 我建议LZ在 Business_date字段上建立聚集索引,而且是分区的。(这样可以用到分区索引,直接指向相应分区)
然后对应其它查询条件使用非聚集索引。 可以更精确定位单一数据。
参考.
------解决方案--------------------
你在测试查询性能是有没有清除缓存数据啊?
另外你的查询语句能否贴出来以下?
------解决方案--------------------
建议:
CREATE CLUSTERED INDEX [IX_TH_ORDER_BUSSINESS_DATE] ON [dbo].[TH_ORDER]
(
[BUSINESS_DATE] DESC
) ON ps_BUSINESS_DATE([BUSINESS_DATE])
即将索引改为聚集分区,这样会将表也作了分区。
注意,聚集索引并不一定需要唯一。
------解决方案--------------------
- SQL code
SELECT MR.myRegionId , MR.myRegionDes AS MYRegion , b.branchId ,b.sap_outlet ,B.sap_name ,b.bdes AS ShopName ,I.ItemId AS ITEM_CODE ,I.ItemName ,SUM(O.QTY) QTY ,SUM(O.AMT-O.ITEM_DISC-O.CAT_DISC-O.ORDER_DISC) AMT ,O.REGION ,O.BUSINESS_DATE FROM ( select ITEM_CODE, REGION , BUSINESS_DATE, OUTLET, TABLE_NUM, QTY, AMT, ITEM_DISC, CAT_DISC, ORDER_DISC from TH_ORDER WHERE BUSINESS_DATE BETWEEN '2012-04-16' AND '2012-04-16' AND TYPE = 'N') O LEFT JOIN ING_ITEM I ON O.ITEM_CODE=I.ItemId AND O.REGION=I.REGION AND O.BUSINESS_DATE=I.BUSINESS_DATE LEFT JOIN branch B ON B.branchId=O.OUTLET LEFT JOIN myRegion MR ON MR.myRegionId=B.myregionId LEFT JOIN JI_table tb ON O.OUTLET= tb.OUTLET and O.TABLE_NUM=tb.ROOM_NUM LEFT JOIN CT_OUTLET_FLOOR ct ON tb.OUTLET=ct.OUTLET and tb.FLOOR=ct.FLOOR GROUP BY MR.myRegionId, MR.myRegionDes,b.branchId,b.sap_outlet,B.sap_name,b.bdes,I.ItemId,I.ITEMNAME,O.REGION,O.BUSINESS_DATE;--你看着这样会不会快点,另外 TYPE='N' 数据在40万里面占百分数?能否建立索引,如果是SQL 2008可以建立条件索引,如下:crteate index IX_TH_ORDER_TYPEon TH_ORDER(TYPE)where TYPE = 'N';如果是sql2005及以下,以上索引不支持,如果值不多,不适合建索引。