And*_*sch 3 sql-server index-tuning string-searching
我想跨连接表的列进行搜索。以下查询的最佳索引配置是什么?
Table A
------------
Id
ValueA
-- Table A has many more columns
Table B
------------
Id
AId
ValueB
-- Table B has many more columns
Run Code Online (Sandbox Code Playgroud)
此刻,我对主键和非聚集索引(不包括任何列)列的聚簇索引AId,ValueA和ValueB。
SELECT *
FROM TableA a
INNER JOIN TableB b ON a.Id = b.AId
WHERE
a.ValueA LIKE 'SearchTerm%' OR
b.ValueB LIKE 'SearchTerm%'
Run Code Online (Sandbox Code Playgroud)
更新 表 A 可能会遇到数百万个,而表 B 将只有数万个条目。
在现实世界中,表 A 将是一个交易列表,其中的值是某种交易引用。表 B 将是一个用户列表,其中的值可以是任何名称或任何其他描述性信息。
目前我们使用的是一个 ORM,它本质上会做一个SELECT *. 当然,这可以改变,但会对应用程序产生相当大的影响。
您的查询对于优化器来说是一个棘手的问题,原因有二。
SELECT *定查询的组件有关。总之,这些限制意味着几乎没有索引可以帮助写入(ORM 生成)的查询,撇开(非聚集)列存储索引的可能性。
如果性能不足,您可能不得不硬着头皮编写自定义查询。在这种情况下,修改现有索引ValueB以包含 AId将很有用,再加上如下重写:
SELECT TA.*, TB.*
FROM
(
-- Disjunction as union
SELECT A.Id, b.Id
FROM TableA a
INNER JOIN TableB b
ON b.AId = a.Id
WHERE
a.ValueA LIKE 'SearchTerm%'
UNION
SELECT A.Id, b.Id
FROM TableB b
INNER JOIN TableA a
ON a.Id = b.AId
WHERE
b.ValueB LIKE 'SearchTerm%'
) AS M (A_Id, B_Id)
-- Lookups
JOIN dbo.TableA AS TA ON TA.Id = M.A_Id
JOIN dbo.TableB AS TB ON TB.Id = M.B_Id;
Run Code Online (Sandbox Code Playgroud)
目标计划形状为:
这在实践中有多好取决于几个因素,包括LIKE谓词的选择性(以及它们总是前缀搜索)。
猜测的架构:
DROP TABLE IF EXISTS dbo.TableB, dbo.TableA;
CREATE TABLE dbo.TableA
(
Id integer NOT NULL PRIMARY KEY,
ValueA varchar(256) NULL INDEX iValueA,
Padding char(4000) NOT NULL DEFAULT '', -- other columns
/*INDEX i (ValueA) INCLUDE (Id)*/
);
CREATE TABLE dbo.TableB
(
Id integer NOT NULL PRIMARY KEY,
AId integer NOT NULL REFERENCES dbo.TableA (Id) INDEX iAId,
ValueB varchar(256) NULL /*INDEX iValueB*/,
Padding char(2000) NOT NULL DEFAULT '', -- other columns
INDEX i (ValueB) INCLUDE (AId)
);
UPDATE STATISTICS dbo.TableA WITH ROWCOUNT = 3000000, PAGECOUNT = 3000000;
UPDATE STATISTICS dbo.TableB WITH ROWCOUNT = 30000, PAGECOUNT = 30000;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
115 次 |
| 最近记录: |