【发布时间】:2017-05-30 10:46:58
【问题描述】:
我想知道最有效的方法是优化 SQL Server 中的数据库模型,以便在开始时使用通配符进行 LIKE 查询。我不是数据库专家,因此欢迎所有关于使用索引或其他优化的建议。
情况: 我有一个包含以下列的表格“产品”:
ShortNameEN (varchar(50))
ShortNameFR (varchar(50))
ShortNameDE (varchar(50))
ShortNameNL (varchar(50))
LongNameEN (varchar(250))
LongNameFR (varchar(250))
LongNameDE (varchar(250))
LongNameNL (varchar(250))
此表包含 300000+ 条记录。
我需要编写一个选择语句来查找包含 搜索字符串的记录(仅在 ShortNameEN 中)。 我的查询是
SELECT *
FROM Products
WHERE ShortNameEN LIKE '%searchstring%'
当然,这个查询非常慢。在 ShortNameEN 上添加索引将无济于事,因为由于第一个通配符,它们不会被使用。
问题 1: 将 ShortNameEN 列与表的其余部分分开是否有意义?我不知道磁盘访问/行大小/页面大小以及这将如何影响性能。也许还有其他与文件系统相关的优化可以提高性能?
临时解决方案
我找到了一个创造性的“三元组”解决方案,但对我的模型产生了相当大的影响。为此,我创建了第二个表“ProductNameFragments”,它引用了我的初始表,并按以下方式分解了每个 ShortNameEN:
ProductId = 123、ShortNameEN = 'PRINTER' 的示例
ProductId | NameFragment
123 | PRINTER
123 | RINTER
123 | INTER
123 | NTER
123 | TER
123 | ER
123 | R
Product 表上的触发器将同步 ProductNameFragments 表。
这样我就可以加入我的两个表,并在没有初始通配符的情况下进行查询。
SELECT p.*
FROM Product p, ProductNameFragment pnf
WHERE p.Id = pnf.ProductId
AND pnf.NameFragment LIKE '%searchstring%'
初步测试表明,这显着提高了我的搜索查询性能。
问题 2:我应该在 ProductNameFragment 上使用常规索引还是聚集索引?更新/删除/插入产品时,这将如何影响性能? 更新一个产品名称时,这可能会导致 ProductNameFragments 表中的 50 次删除和 50 次插入。我可以强制索引只更新一次吗?
最后,由于复杂性,我宁愿不使用“三元组”解决方案。因此,任何提示或技巧都非常受欢迎。
提前谢谢
史蒂文
【问题讨论】:
-
今日提示:切换到现代、明确的
JOIN语法。更容易编写(没有错误),更容易阅读和维护,如果需要更容易转换为外连接。 -
全文搜索更适合搜索全词。 'Printer' 在这里可能不是最好的例子,但在 %int% 上搜索应该是可能的。
标签: sql sql-server performance sqlperformance