使用Interbase优化SQL

时间:2010-03-16 21:14:52

标签: sql delphi interbase

我从之前question关于SQL的好答案中获得灵感。 现在,这个SQL在带有Interbase 2009的数据库上运行。它的大小约为21 GB。

SELECT DistanceAsMeters, AddrDistance.Bold_Id, AddrDistance.Created, AddressFrom.CityName_CO as FromCity, AddressTo.CityName_CO as ToCity
FROM AddrDistance
LEFT JOIN Address AddressFrom ON AddrDistance.FromAddress = AddressFrom.Bold_Id
LEFT JOIN Address AddressTo ON AddrDistance.ToAddress = AddressTo.Bold_Id
Where  DistanceAsMeters = 0 and PseudoDistanceAsCostKm = 0
       and not AddrDistance.bold_id in (select bold_id from DistanceQueryTask)
Order By Created Desc

AddrDistance有840000行 带有地址的190000行和带有DistanceQueryTask的4。

问题是,这可以更快地完成吗?我想,同样的查询运行多次从DistanceQueryTask中选择bold_id 。请注意,我对存储过程不感兴趣,只是简单的SQL:)

EDIT1 以下是当前的执行计划:

Statement: SELECT DistanceAsMeters, AddrDistance.Bold_Id, AddrDistance.Created, AddressFrom.CityName_CO as FromCity, AddressTo.CityName_CO as ToCity
FROM AddrDistance
LEFT JOIN Address AddressFrom ON AddrDistance.FromAddress = AddressFrom.Bold_Id
LEFT JOIN Address AddressTo ON AddrDistance.ToAddress = AddressTo.Bold_Id
Where  DistanceAsMeters = 0 and PseudoDistanceAsCostKm = 0
       and not AddrDistance.bold_id in (select bold_id from DistanceQueryTask)
Order By Created Desc

PLAN (DISTANCEQUERYTASK INDEX (RDB$PRIMARY218))
PLAN SORT (JOIN (JOIN (ADDRDISTANCE NATURAL,ADDRESSFROM INDEX (RDB$PRIMARY234)),ADDRESSTO INDEX (RDB$PRIMARY234)))

是的,如果数据库中有行,则DistanceQueryTask意味着数字较小。

4 个答案:

答案 0 :(得分:2)

使用左连接和子查询会减慢任何查询速度。

您可以使用正确的索引(在Bold_id,DistanceMeters,PseudoDistanceAsCostKm上)进行一些改进,记住更多索引会增加数据库的大小

答案 1 :(得分:2)

我认为bold_id是你的关键,因此被正确编入索引 然后通过连接替换subselect和not ... in可能有助于优化器。

SELECT DistanceAsMeters, Bold_Id, Created, AddressFrom.CityName_CO as FromCity, AddressTo.CityName_CO as ToCity
FROM AddrDistance
LEFT JOIN Address AddressFrom ON AddrDistance.FromAddress = AddressFrom.Bold_Id
LEFT JOIN Address AddressTo ON AddrDistance.ToAddress = AddressTo.Bold_Id
LEFT JOIN DistanceQueryTask ON AddrDistance.bold_id = DistanceQueryTask.bold_id
Where  DistanceAsMeters = 0 and PseudoDistanceAsCostKm = 0
  and DistanceQueryTask.bold_id is null
Order By Created Desc

答案 2 :(得分:2)

为此部分创建索引:(DistanceAsMeters = 0且PseudoDistanceAsCostKm = 0) 因为它对它进行(坏)表扫描:ADDRDISTANCE NATURAL

尝试使用连接而不是Francois所述的subselect。

答案 3 :(得分:2)

丹尼尔和安德烈建议索引有很多帮助 我建议使用这个索引(DistanceMeters,PseudoDistanceAsCostKm,Bold_id),因为索引的前两部分是常量,然后是读取所需索引的一小部分。

如果存在FromAddress和/或ToAddress这一事实,您可以将LEFT JOIN更改为INNER JOIN,因为它通常更快(查询优化器可以做出一些假设)。