--先试下这个SELECT A.X INTO # FROM A,B,C WHERE A.ID=B.A_ID AND B.B_id =C.B_ID AND C.ID IN (1)SELECT COUNT(*) FROM # WHERE dbo.IsMatchByTime(X,'pattern')=1DROP TABLE #
--TRY SELECT COUNT(*) FROM (SELECT A.X FROM A,B,C WHERE A.ID=B.A_ID AND B.B_id =C.B_ID AND C.ID =1) T WHERE dbo.IsMatchByTime(X,'pattern')=1 --在A.ID ,B.A_ID,B.B_id,C.B_ID上建立索引
回Yang,肯定是有多个我才会用in的
回复 qianjin036a: 我也看过执行计划,是不是就是你说的showplan_all?现在确实应该是对每一行记录都执行了我这个函数。 他的执行方法是先将in谓词的表做inner join,然后再cluster index scan然后再执行filter(也就是调用我的函数),我现在的问题是它为什么要执行这个函数,那不摆明做无用功吗,我如何能够使他在前面条件不满足的时候就不去做后面的多余判断了
那这样试试: ;with cit as( select X from A where id in (select A_id from B where B_id in(select B_id from C where C_id=1)) ) select count(*) from cit where dbo.IsMatchByTime(X,'pattern')=1
1)select * from productuseinfo where distributionid in (select distributionid from distribution where productid in(select productid from product where catelogid in (1))) and dbo.IsMatchByTime(usetrackwithtime,'','2001-08-01 00:00:00','2008-08-04 00:00:00' )=12) |--Hash Match(Inner Join, HASH:([cia].[dbo].[Distribution].[DistributionID])=([cia].[dbo].[ProductUseInfo].[DistributionID]))3) |--Hash Match(Inner Join, HASH:([cia].[dbo].[Product].[ProductID])=([cia].[dbo].[Distribution].[ProductID]))4) | |--Clustered Index Scan(OBJECT:([cia].[dbo].[Product].[PK_Product]), WHERE:([cia].[dbo].[Product].[CatelogID]=(1)))5) | |--Clustered Index Scan(OBJECT:([cia].[dbo].[Distribution].[PK_Distribution]))6) |--Filter(WHERE:([cia].[dbo].[IsMatchByTime]([Expr1009],N'','2001-08-01 00:00:00.000','2008-08-04 00:00:00.000')=(1)))7) |--Compute Scalar(DEFINE:([Expr1009]=CONVERT_IMPLICIT(nvarchar(4000),[cia].[dbo].[ProductUseInfo].[UseTrackWithTime],0)))8) |--Clustered Index Scan(OBJECT:([cia].[dbo].[ProductUseInfo].[PK_ProductUseInfo])) 以上是执行计划,我的函数是dbo.IsMatchByTime(usetrackwithtime,'','2001-08-01 00:00:00','2008-08-04 00:00:00' ) 谢谢各位了同时再问下上面我说的问题:(但是请教各位为什么会这样,我前面的限制条件已经能确定了啊,为什么它还要进行后面的比较?由于我这个函数使用了正则表达式,理论上说速度肯定是会有影响。所以我不能让他每次都执行这个函数,而且事实上前面的条件已经限制住了,它为什么还要进行后面的判断?) 他为什么要进行后面的调用函数来判断?我前面不是已经限制住了吗?
--TRY:SET NOCOUNT ON GO CREATE INDEX IX_CtID_PID ON Product(catelogid,productid) GO CREATE INDEX IX_PID_DID ON distribution(productid,distributionid) GO CREATE INDEX IX_DID ON productuseinfo(distributionid) GO SET STATISTICS IO ON SET STATISTICS PROFILE ON GOSELECT COUNT(*) FROM productuseinfo a WITH(INDEX=IX_DID) INNER JOIN distributionid b ON a.distributionid=b.distributionid INNER JOIN Product c ON b.productid=c.productid WHERE catelogid =1 AND dbo.IsMatchByTime(usetrackwithtime,'','2001-08-01 00:00:00','2008-08-04 00:00:00' )=1 --看结果怎么样,再把执行计划帖上来。
1)SELECT COUNT(*) FROM productuseinfo a WITH(INDEX=IX_DID) INNER JOIN distribution b ON a.distributionid=b.distributionid INNER JOIN Product c ON b.productid=c.productid WHERE catelogid =1 AND dbo.IsMatchByTime(usetrackwithtime,'','2001-08-01 00:00:00','2008-08-04 00:00:00' )=12) |--Compute Scalar(DEFINE:([Expr1006]=CONVERT_IMPLICIT(int,[globalagg1009],0)))3) |--Stream Aggregate(DEFINE:([globalagg1009]=SUM([partialagg1008]))) 4) |--Parallelism(Gather Streams)5) |--Stream Aggregate(DEFINE:([partialagg1008]=Count(*)))6) |--Filter(WHERE:([cia].[dbo].[IsMatchByTime](CONVERT_IMPLICIT(nvarchar(4000),[cia].[dbo].[ProductUseInfo].[UseTrackWithTime] as [a].[UseTrackWithTime],0),N'','2001-08-01 00:00:00.000','2008-08-04 00:00:00.000')=(1)))7) |--Nested Loops(Inner Join, OUTER REFERENCES:([a].[UserID], [a].[DistributionID], [Expr1011]) WITH UNORDERED PREFETCH)8) |--Nested Loops(Inner Join, OUTER REFERENCES:([b].[DistributionID], [Expr1010]) WITH UNORDERED PREFETCH)9) | |--Nested Loops(Inner Join, OUTER REFERENCES:([c].[ProductID]))10) | | |--Parallelism(Distribute Streams, RoundRobin Partitioning)11) | | | |--Index Seek(OBJECT:([cia].[dbo].[Product].[IX_CtID_PID] AS [c]), SEEK:([c].[CatelogID]=(1)) ORDERED FORWARD)12) | | |--Index Seek(OBJECT:([cia].[dbo].[Distribution].[IX_Distribution] AS [b]), SEEK:([b].[ProductID]=[cia].[dbo].[Product].[ProductID] as [c].[ProductID]) ORDERED FORWARD)13) | |--Index Seek(OBJECT:([cia].[dbo].[ProductUseInfo].[IX_DID] AS [a]), SEEK:([a].[DistributionID]=[cia].[dbo].[Distribution].[DistributionID] as [b].[DistributionID]) ORDERED FORWARD)14) |--Clustered Index Seek(OBJECT:([cia].[dbo].[ProductUseInfo].[PK_ProductUseInfo] AS [a]), SEEK:([a].[UserID]=[cia].[dbo].[ProductUseInfo].[UserID] as [a].[UserID] AND [a].[DistributionID]=[cia].[dbo].[ProductUseInfo].[DistributionID] as [a].[DistributionID]) LOOKUP ORDERED FORWARD)
再试一下这个(把强制索引去掉) SELECT COUNT(*) FROM productuseinfo a INNER JOIN distributionid b ON a.distributionid=b.distributionid INNER JOIN Product c ON b.productid=c.productid WHERE catelogid =1 AND dbo.IsMatchByTime(usetrackwithtime,'','2001-08-01 00:00:00','2008-08-04 00:00:00' )=1
--先试下这个SELECT A.X
INTO #
FROM A,B,C
WHERE A.ID=B.A_ID
AND B.B_id =C.B_ID
AND C.ID IN (1)SELECT COUNT(*) FROM # WHERE dbo.IsMatchByTime(X,'pattern')=1DROP TABLE #
SELECT COUNT(*) FROM (SELECT A.X
FROM A,B,C
WHERE A.ID=B.A_ID
AND B.B_id =C.B_ID
AND C.ID =1) T WHERE dbo.IsMatchByTime(X,'pattern')=1
--在A.ID ,B.A_ID,B.B_id,C.B_ID上建立索引
我也看过执行计划,是不是就是你说的showplan_all?现在确实应该是对每一行记录都执行了我这个函数。
他的执行方法是先将in谓词的表做inner join,然后再cluster index scan然后再执行filter(也就是调用我的函数),我现在的问题是它为什么要执行这个函数,那不摆明做无用功吗,我如何能够使他在前面条件不满足的时候就不去做后面的多余判断了
;with cit as(
select X from A where id in (select A_id from B where B_id in(select B_id from C where C_id=1))
)
select count(*) from cit where dbo.IsMatchByTime(X,'pattern')=1
我用的是.net的sqlCommand来执行
由于持久层不是我写的,因此必须要找到一个只需要一条查询语句就可以返回结果的方法。
与5楼类似.你的函数是否能重写?如果能重写,试试对函数进行优化.
以上是执行计划,我的函数是dbo.IsMatchByTime(usetrackwithtime,'','2001-08-01 00:00:00','2008-08-04 00:00:00' )
谢谢各位了同时再问下上面我说的问题:(但是请教各位为什么会这样,我前面的限制条件已经能确定了啊,为什么它还要进行后面的比较?由于我这个函数使用了正则表达式,理论上说速度肯定是会有影响。所以我不能让他每次都执行这个函数,而且事实上前面的条件已经限制住了,它为什么还要进行后面的判断?)
他为什么要进行后面的调用函数来判断?我前面不是已经限制住了吗?
还有我也是KG蜜啊,看在KG份上,帮我义不容辞啊~~~
我应该怎么建立索引?这些字段都是int型
GO
CREATE INDEX IX_CtID_PID ON Product(catelogid,productid)
GO
CREATE INDEX IX_PID_DID ON distribution(productid,distributionid)
GO
CREATE INDEX IX_DID ON productuseinfo(distributionid)
GO
SET STATISTICS IO ON
SET STATISTICS PROFILE ON
GOSELECT COUNT(*)
FROM productuseinfo a WITH(INDEX=IX_DID)
INNER JOIN distributionid b
ON a.distributionid=b.distributionid
INNER JOIN Product c
ON b.productid=c.productid
WHERE catelogid =1
AND dbo.IsMatchByTime(usetrackwithtime,'','2001-08-01 00:00:00','2008-08-04 00:00:00' )=1 --看结果怎么样,再把执行计划帖上来。
4) |--Parallelism(Gather Streams)5) |--Stream Aggregate(DEFINE:([partialagg1008]=Count(*)))6) |--Filter(WHERE:([cia].[dbo].[IsMatchByTime](CONVERT_IMPLICIT(nvarchar(4000),[cia].[dbo].[ProductUseInfo].[UseTrackWithTime] as [a].[UseTrackWithTime],0),N'','2001-08-01 00:00:00.000','2008-08-04 00:00:00.000')=(1)))7) |--Nested Loops(Inner Join, OUTER REFERENCES:([a].[UserID], [a].[DistributionID], [Expr1011]) WITH UNORDERED PREFETCH)8) |--Nested Loops(Inner Join, OUTER REFERENCES:([b].[DistributionID], [Expr1010]) WITH UNORDERED PREFETCH)9) | |--Nested Loops(Inner Join, OUTER REFERENCES:([c].[ProductID]))10) | | |--Parallelism(Distribute Streams, RoundRobin Partitioning)11) | | | |--Index Seek(OBJECT:([cia].[dbo].[Product].[IX_CtID_PID] AS [c]), SEEK:([c].[CatelogID]=(1)) ORDERED FORWARD)12) | | |--Index Seek(OBJECT:([cia].[dbo].[Distribution].[IX_Distribution] AS [b]), SEEK:([b].[ProductID]=[cia].[dbo].[Product].[ProductID] as [c].[ProductID]) ORDERED FORWARD)13) | |--Index Seek(OBJECT:([cia].[dbo].[ProductUseInfo].[IX_DID] AS [a]), SEEK:([a].[DistributionID]=[cia].[dbo].[Distribution].[DistributionID] as [b].[DistributionID]) ORDERED FORWARD)14) |--Clustered Index Seek(OBJECT:([cia].[dbo].[ProductUseInfo].[PK_ProductUseInfo] AS [a]), SEEK:([a].[UserID]=[cia].[dbo].[ProductUseInfo].[UserID] as [a].[UserID] AND [a].[DistributionID]=[cia].[dbo].[ProductUseInfo].[DistributionID] as [a].[DistributionID]) LOOKUP ORDERED FORWARD)
应该是正常了。
请问老大你这是怎么弄的?这是什么原理
有什么关于数据库优化方面的书吗?
感谢啊
SELECT COUNT(*)
FROM productuseinfo a
INNER JOIN distributionid b
ON a.distributionid=b.distributionid
INNER JOIN Product c
ON b.productid=c.productid
WHERE catelogid =1
AND dbo.IsMatchByTime(usetrackwithtime,'','2001-08-01 00:00:00','2008-08-04 00:00:00' )=1