![](/img/trans.png)
[英]How do I write a query to compare the indexes on two SQL Server tables?
[英]In SQL Server, how do I make sql using "or" clauses over two connected tables use the correct indexes
我有两个表TableA
和TableB
,它们由AID
相关。 AID
是TableA
中的主键和TableB
中的外键。
以下 SQL 用于 select 从TableB
连接到TableA
的任何内容,其中ADesc
或BDesc
类似于某个值。
SQL1:
SELECT *
FROM TableB
INNER JOIN TableA ON TableA.AID = TableB.AID
WHERE ADesc LIKE 'A0A4D1%' OR BDesc = 'A0A4D1%'
AID
( TableA_PK
) 上有一个聚集索引ADesc
( TableA_I1
) 上有一个非聚集索引BID
( TableB_PK
) 上有一个聚集索引BDesc
( TableB_I1
) 上有一个非聚集索引如果我将上面的 SQL 分成两条语句(或一条语句与 SQL2 中的 UNION 连接),SQL 服务器将真正有效地利用TableA_I1
和TableB_I1
并限制ADesc
或BDesc
。
SQL2:
SELECT *
FROM TableB
INNER JOIN TableA ON TableA.AID = TableB.AID
WHERE ADesc LIKE 'A0A4D1%'
UNION
SELECT *
FROM TableB
INNER JOIN TableA ON TableA.AID = TableB.AID
WHERE BDesc = 'A0A4D1%'
但是,SQL1 既不使用TableA_I1
也不使用TableB_I1
,返回速度要慢得多。
我的问题是有没有办法让 SQL 服务器执行 SQL1 但使用与 SQL2 中相同的索引和类似的执行计划?
我正在使用 SQL 服务器 2019。
这似乎是一个奇怪的问题,它引出了下面的问题——你为什么不把它改成 UNION 呢? 第一,我的实际 SQL 要复杂得多,生成的 UNION 会很大,所以我想看看是否可以简化。 第二,我很好奇为什么 SQL 服务器无法解决问题并自行优化。
创建所有表和索引的SQL如下:
CREATE TABLE TableA
(
AID INT IDENTITY(1,1) NOT NULL,
ADesc VARCHAR(50) NOT NULL
)
GO
CREATE NONCLUSTERED INDEX TableA_I1 ON TableA (ADesc ASC)
GO
CREATE UNIQUE CLUSTERED INDEX TableA_PK ON TableA (AID ASC)
GO
CREATE TABLE TableB
(
BID INT IDENTITY(1,1) NOT NULL,
AID INT NOT NULL,
BDesc VARCHAR(50) NOT NULL
)
GO
CREATE NONCLUSTERED INDEX TableB_I1 ON TableB (BDesc ASC)
GO
CREATE UNIQUE CLUSTERED INDEX TableB_PK ON TableB (BID ASC)
GO
然后我将几百万行放入表中以确保有足够的数据 go at!
也许尝试使用以下模式进行试验。 使用带有主键的临时表意味着 SQL 服务器将有准确的统计信息可供使用。
drop table if exists #aid;
create table #aid(aid int primary key);
insert into #aid(aid)
select aid
from TableA
where ADesc like 'A0A4D1%'
union all
select aid
from TableB
where BDesc = 'A0A4D1';
select a.<columns>, b.<columns>
from #aid x
join TableA a on a.aid = x.aid
join TableB b on b.aid = x.aid;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.