Tom*_*bes 9 sql-server execution-plan count
在 SQL Server 2012 中,我有一个表值函数,它连接到另一个表,我需要计算这个“表值函数”的行数。当我检查执行计划时,我可以看到左连接表。为什么?左连接表如何影响返回的行数?我希望数据库引擎不需要在 SELECT count(..) 查询中评估左联合表。
Select count(realtyId) FROM [dbo].[GetFilteredRealtyFulltext]('"praha"')
Run Code Online (Sandbox Code Playgroud)
执行计划:
表值函数:
CREATE FUNCTION [dbo].[GetFilteredRealtyFulltext]
(@criteria nvarchar(4000))
RETURNS TABLE
AS
RETURN (SELECT
realty.Id AS realtyId,
realty.OwnerId,
realty.Caption AS realtyCaption,
realty.BusinessCategory,
realty.Created,
realty.LastChanged,
realty.LastChangedType,
realty.Price,
realty.Pricing,
realty.PriceCurrency,
realty.PriceNote,
realty.PricePlus,
realty.OfferState,
realty.OrderCode,
realty.PublishAddress,
realty.PublishMap,
realty.AreaLand,
realty.AreaCover,
realty.AreaFloor,
realty.Views,
realty.TopPoints,
realty.Radius,
COALESCE(realty.Wgs84X, ruian_cobce.Wgs84X, ruian_obec.Wgs84X) as Wgs84X,
COALESCE(realty.Wgs84Y, ruian_cobce.Wgs84Y, ruian_obec.Wgs84Y) as Wgs84Y,
realty.krajId,
realty.okresId,
realty.obecId,
realty.cobceId,
IsNull(CONVERT(int,realty.Ranking),0) as Ranking,
realty.energy_efficiency_rating,
realty.energy_performance_attachment,
realty.energy_performance_certificate,
realty.energy_performance_summary,
Category.Id AS CategoryId,
Category.ParentCategoryId,
Category.WholeName,
okres.nazev AS okres,
ruian_obec.nazev AS obec,
ruian_cobce.nazev AS cobce,
ExternFile.ServerPath,
Person.ParentPersonId,
( COALESCE(ftR.Rank,0) + COALESCE(ftObec.Rank,0) + COALESCE(ftOkres.Rank,0) + COALESCE(ftpobvod.Rank,0)) AS FtRank
FROM realty
JOIN Category ON realty.CategoryId = Category.Id
LEFT JOIN ruian_cobce ON realty.cobceId = ruian_cobce.cobce_kod
LEFT JOIN ruian_obec ON realty.obecId = ruian_obec.obec_kod
LEFT JOIN okres ON realty.okresId = okres.okres_kod
LEFT JOIN ExternFile ON realty.Id = ExternFile.ForeignId AND ExternFile.IsMain = 1 AND ExternFile.ForeignTable = 5
INNER JOIN Person ON realty.OwnerId = Person.Id
Left JOIN CONTAINSTABLE(Realty, *, @criteria) ftR ON realty.Id = ftR.[Key]
Left JOIN CONTAINSTABLE(ruian_obec, *, @criteria) ftObec ON realty.obecId = ftObec.[Key]
Left JOIN CONTAINSTABLE(Okres, *, @criteria) ftOkres ON realty.okresId = ftOkres.[Key]
Left JOIN CONTAINSTABLE(pobvod, *, @criteria) ftpobvod ON realty.pobvodId = ftpobvod.[Key]
WHERE Person.ConfirmStatus = 1
AND ( COALESCE(ftR.Rank,0) + COALESCE(ftObec.Rank,0) + COALESCE(ftOkres.Rank,0) + COALESCE(ftpobvod.Rank,0)) > 0
)
Run Code Online (Sandbox Code Playgroud)
更新:
我添加了唯一索引以遵循 Rob Farley 的想法:
Create unique nonclustered index ExternFileIsMainUnique ON ExternFile(ForeignId) WHERE IsMain = 1 AND ForeignTable = 5
Run Code Online (Sandbox Code Playgroud)
并由数据库引擎建议索引:
CREATE NONCLUSTERED INDEX [RealtyOwnerLocation] ON [dbo].[Realty]
Run Code Online (Sandbox Code Playgroud)
( [OwnerId] ASC ) 包括 ( [Id], [okresId], [obecId], [pobvodId]) GO
为简单起见,我删除了条件
WHERE Person.ConfirmStatus = 1
Run Code Online (Sandbox Code Playgroud)
来自上面的表值函数。
现在执行计划要简单得多,但它仍然触及表 ExternFile:
也许 sql server 不够聪明?
Rob*_*ley 12
如果ForeignId, ForeignTable, IsMain不知道*在 中是唯一的ExternFile,那么 QO 将需要包括该表来计算计数。任何时候多行匹配,计数都会受到影响。
加入简化在 SQL Server
设计中进行简化(SQLBits 记录)
更新(由 OP):解决方案是从 LEFT JOIN(可以生成多行)更改查询中的行:
LEFT JOIN ExternFile ON realty.Id = ExternFile.ForeignId AND ExternFile.IsMain = 1 AND ExternFile.ForeignTable = 5
Run Code Online (Sandbox Code Playgroud)
OUTER APPLY with TOP(产生一行,不影响计数)
OUTER APPLY (SELECT TOP (1) ServerPath FROM ExternFile WHERE ForeignId = realty.Id AND IsMain = 1 AND ForeignTable = 5) AS ExternFile
Run Code Online (Sandbox Code Playgroud)
查询现在更有效。添加唯一索引无法完成,因为值不是唯一的,它们仅对于条件中的组合是唯一的,并且这不被视为如上所述的唯一。
| 归档时间: |
|
| 查看次数: |
604 次 |
| 最近记录: |