0

我从上一个关于 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 行,AddrDistance 有 190000 行,Address 有 4 行,DistanceQueryTask 有 4 行。

问题是,这可以更快地完成吗?我猜,相同的查询运行多次select bold_id from DistanceQueryTask。请注意,我对存储过程不感兴趣,只对普通 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

4 回答 4

2

正如 Daniel 和 Andre 所建议的,索引有很大帮助。
我建议使用这个索引(DistanceMeters、PseudoDistanceAsCostKm、Bold_id),因为索引的前 2 部分是恒定的,然后是需要读取的索引的一小部分。

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

于 2010-03-17T09:06:27.290 回答
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
于 2010-03-16T23:27:11.640 回答
2

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

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

于 2010-03-16T21:55:36.407 回答
2

为这部分创建一个索引: (DistanceAsMeters = 0 and PseudoDistanceAsCostKm = 0) 因为它对其进行了(坏的)表扫描:ADDRDISTANCE NATURAL

并尝试使用连接而不是弗朗索瓦所说的子选择。

于 2010-03-17T06:42:28.343 回答