使用CONTAINS进行全文搜索非常慢

时间:2017-10-08 00:27:14

标签: sql sql-server full-text-search azure-sql-database star-schema

我们尝试在Azure数据库上使用全文搜索,并在使用CONTAINS搜索时出现性能问题。

我们的数据具有星型模式,事实表启用了集群列存储索引,大约有4000万行。下面是我们如何在维度上使用CONTAINS并在Fact表上对不同查询进行聚合:

使用EXISTS查询1:

SELECT f.[FK_DimCompanyCodeId], SUM(f.NetValueInUSD)
FROM [SPENDBY].[FactInvoiceDetail] f

WHERE EXISTS (
        SELECT * FROM [SPENDBY].[DimCompanyCode] d

        WHERE f.[FK_DimCompanyCodeId] = d.Id
        AND CONTAINS(d.*, 'Comcast'))

GROUP BY f.[FK_DimCompanyCodeId]

ORDER BY SUM(f.NetValueInUSD) DESC

此查询似乎永远运行,永远不会返回结果。

外键FK_DimCompanyCodeId]上有非聚集索引,搜索Comcast时只返回一行:

SELECT id  FROM [SPENDBY].[DimCompanyCode] d
WHERE CONTAINS(d.*, 'Comcast');
-- will return id = 5

事实表大约有2700万行FK_DimCompanyCodeId = 5

使用INNER JOIN查询2:

SELECT f.[FK_DimCompanyCodeId], SUM(f.NetValueInUSD)
FROM [SPENDBY].[FactInvoiceDetail] f

INNER JOIN [SPENDBY].[DimCompanyCode] d ON (f.[FK_DimCompanyCodeId] = d.Id)
WHERE CONTAINS(d.*, 'Comcast')

GROUP BY f.[FK_DimCompanyCodeId]
ORDER BY SUM(f.NetValueInUSD) DESC

此查询似乎永远运行,并且永远不会返回结果。

使用#temp表查询3:

SELECT id INTO #temp FROM [SPENDBY].[DimCompanyCode] d
WHERE CONTAINS(d.*, 'Comcast');

SELECT f.[FK_DimCompanyCodeId], SUM(f.NetValueInUSD)
FROM [SPENDBY].[FactInvoiceDetail] f

WHERE EXISTS (
        SELECT * FROM #temp
        WHERE f.[FK_DimCompanyCodeId] = #temp.Id)

GROUP BY f.[FK_DimCompanyCodeId]

ORDER BY SUM(f.NetValueInUSD) DESC

非常快,5秒后返回结果。

为什么全文搜索在案例1和案例2中都很慢。

2 个答案:

答案 0 :(得分:1)

问题是竞争索引 - 一个用于JOIN,一个用于过滤器。也许子查询会说服SQL Server首先使用文本索引:

SELECT f.[FK_DimCompanyCodeId], SUM(f.NetValueInUSD)
FROM [SPENDBY].[FactInvoiceDetail] f JOIN
     (SELECT id
      FROM [SPENDBY].[DimCompanyCode] cc
      WHERE CONTAINS(cc.*, 'Comcast')
     ) cc
     ON cc.id = f.FK_DimCompanyCodeId
GROUP BY f.[FK_DimCompanyCodeId]
ORDER BY SUM(f.NetValueInUSD) DESC

如果您在FactInvoiceDetail(FK_DimCompanyCodeId)上有索引,那么它可能也有帮助。

答案 1 :(得分:0)

最终,我发现CONTAINS适用于特定列(例如Description):

SELECT f.[FK_DimCompanyCodeId], SUM(f.NetValueInUSD)
FROM [SPENDBY].[FactInvoiceDetail] f
WHERE  f.[FK_DimCompanyCodeId] IN  (
        SELECT d.Id FROM [SPENDBY].[DimCompanyCode] d
        WHERE CONTAINS(d.[Description], 'Comcast')
)
GROUP BY f.[FK_DimCompanyCodeId]
ORDER BY SUM(f.NetValueInUSD) DESC

为了搜索整个表格,CONTAINSTABLE将获得最佳性能并避免使用#temp表:

SELECT f.[FK_DimCompanyCodeId], SUM(f.NetValueInUSD)
FROM [SPENDBY].[FactInvoiceDetail] f
LEFT OUTER JOIN CONTAINSTABLE([SPENDBY].[DimCompanyCode], *, '"Comcast"') ct 
ON f.[FK_DimCompanyCodeId] = ct.[Key]
WHERE ct.[Key] IS NOT NULL
GROUP BY f.[FK_DimCompanyCodeId]
ORDER BY SUM(f.NetValueInUSD) DESC