10

我在 SQL Server 2008R2 上的一个简单表上有一个自由文本目录:

CREATE FULLTEXT CATALOG customer_catalog;
CREATE FULLTEXT INDEX ON customer
 ( 
   name1
 ) 
  KEY INDEX customer_pk
  ON customer_catalog;
ALTER FULLTEXT INDEX ON customer START UPDATE POPULATION;

如果我执行以下三个查询,前两个查询几乎立即返回,而最后一个查询在一个有 100,000 条记录的表上需要大约 14 秒:

SELECT
        customer_id
    FROM
        customer
    WHERE
        CONTAINS(customer.*, 'nomatch');

SELECT
        customer_id
    FROM
        customer
    WHERE
        customer.customer_id = 0;

SELECT
        customer_id
    FROM
        customer
    WHERE
        CONTAINS(customer.*, 'nomatch')
            OR customer.customer_id = 0;

以下是查询计划:

在此处输入图像描述

为什么第三个查询这么慢?我可以做些什么来改进它还是需要拆分查询?

4

3 回答 3

4

“OR”逻辑条件通常使查询运行非常缓慢: / 通常,最好的选择是使用 UNION (ALL)。

就你而言,我很好奇你的用法

SELECT
    customer_id
FROM
    customer
WHERE
    customer.customer_id = 0;

它只会产生一个零列表(可能是空的)。是否计算(!)有多少客户的 id = 0?是否检查是否有任何客户的 id 为 0?

如果不是要计算零而是要知道它们是否存在,那么这个查询应该是有效的:

SELECT
    customer_id
FROM
    customer
WHERE
    CONTAINS(customer.*, 'nomatch')
    AND customer.customer_id <> 0
UNION ALL
SELECT TOP(1)
    0
FROM
    customer
WHERE
    customer.customer_id = 0

否则有效的查询是这个:

SELECT
    customer_id
FROM
    customer
WHERE
    CONTAINS(customer.*, 'nomatch')
    AND customer.customer_id <> 0
UNION ALL
SELECT
    0
FROM
    customer
WHERE
    customer.customer_id = 0

(我刚刚删除了 TOP 子句)

于 2013-05-13T09:50:54.977 回答
4

很难说原因,但似乎 SQL Server 选择了一个低效的查询计划。以下是一些建议:

更新表上的统计信息:

UPDATE STATISTICS dbo.customer

统计数据更新后,您可以再次尝试查询,看看是否有改进。

还有一点是,对于组合OR语句,SQL Server 使用的是索引扫描,而不是查找。您可以尝试FORCESEEK提示,看看是否有所作为:

SELECT customer_id
FROM customer WITH (FORCESEEK)
WHERE CONTAINS(customer.*, 'nomatch')
OR customer.customer_id = 0;

正如您所提到的,另一种选择是拆分语句。以下UNION执行与前两个语句的组合一样好:

SELECT customer_id FROM customer
WHERE CONTAINS(customer.*, 'nomatch')

UNION

SELECT customer_id FROM customer
WHERE customer.customer_id = 0

更新- 将上述查询更改为UNION而不是UNION ALL.

正如@PondLife 在评论中指出的那样,我的意思是UNION在上面的查询中做 a 而不是UNION ALL. 想了想,我也试了UNION ALL一下,好像更快了。这假设您不关心重复的 ID:

SELECT customer_id FROM customer
WHERE CONTAINS(customer.*, 'nomatch')

UNION ALL

SELECT customer_id FROM customer
WHERE customer.customer_id = 0
于 2013-05-10T20:35:52.170 回答
3

根据您的 MS SQL 2008 R2 服务包版本,您的问题可能与以下 Microsoft Connect 问题有关:“混合查询”的全文性能

根据 MS Connect 条目,安装 SQL Server 2008 R2 的最新累积更新包后问题应该会消失。

于 2013-05-17T21:44:54.120 回答