【问题标题】:Last Name Search SQL performance improvement姓氏搜索 SQL 性能改进
【发布时间】:2016-06-03 01:57:58
【问题描述】:

在以下查询中查找输入,该查询利用表变量检索具有匹配 CustomerNumberID 的姓氏结果。

1.

INSERT INTO #MatchingIndividuals (CustomerNumberID)
    SELECT DISTINCT(c.CustomerNumberID)
    FROM CustomerNumber c
    WHERE c.CustomerTypeID = 1
        AND EXISTS (
            SELECT 1 
            FROM CustomerIndividualNameSearch cn
                INNER JOIN CustomerIndividualName cin
                    ON cn.CustomerIndividualNameID = cin.CustomerIndividualNameID
                CROSS JOIN #NameCriteria cnc
            WHERE cin.CustomerNumberID = c.CustomerNumberID
                AND cn.LastName LIKE cnc.LastName ESCAPE @escape)
    ORDER BY c.CustomerNumberID
    OFFSET @SKIP ROWS FETCH NEXT @ROWS ROWS ONLY

2。 #NameCriteria 声明为

SELECT LastName, FirstName, MiddleName
        FROM dbo.CustomerIndividualNameCriteriaExpansion(@LastName, @FirstName, @MiddleName, @ExactSearch, @LastNameThreshold, @escape)'

            SET @where = @where + '
        AND EXISTS (
            SELECT 1 
            FROM #NameCriteria cnc
                INNER JOIN CustomerIndividualNameSearch cn
                    ON ' + @namewhere + '
                INNER JOIN CustomerIndividualName cin
                    ON cn.CustomerIndividualNameID = cin.CustomerIndividualNameID
            WHERE cin.CustomerNumberID = c.CustomerNumberID)'

3.CustomerIndividualNameCriteriaExpansion 是一个内联表值函数,可扩展名字、中间名和姓氏以进行通配符名称搜索。

查询需要 30 秒或更长时间才能返回。有什么建议吗?

【问题讨论】:

  • 我们只是说CROSS JOIN #NameCriteria cnc 看起来很可疑。你了解 CROSS JOIN 的性能影响是什么吗?
  • 根据数据库管理器的不同,交叉连接可能会被规划器转换为内部连接。所以这是代码异味,但不一定是性能问题。但是,为了性能,请说明您正在使用哪个 RDBMS 并适当地标记问题,因为性能调整通常是非常特定于 RDBMS 的。
  • 根据问题中的代码添加了sql-servertsql标签
  • 获取执行计划并附上。没有它,我们只能猜测您的问题。
  • 我感觉您在简单查找方面做得太多了。考虑减少所涉及的嵌套级别、连接和数据的数量。另外,如果您提出问题,请提供所有信息。例如,我们只需猜测 CustomerIndividualNameSearch、CustomerIndividualName 表中存储的内容。此外,提供的 #NameCriteria 定义没有任何意义。

标签: sql sql-server tsql


【解决方案1】:

# 表往往相当慢 - 尝试使用 common table expression 代替。

WITH NameCriteria (LastName, FirstName, MiddleName) 
as
(
    SELECT LastName, FirstName, MiddleName
    FROM dbo.CustomerIndividualNameCriteriaExpansion(@LastName, @FirstName, @MiddleName, @ExactSearch, @LastNameThreshold, @escape)'
)

SELECT DISTINCT(c.CustomerNumberID)
FROM CustomerNumber c
WHERE c.CustomerTypeID = 1
    AND EXISTS (
        SELECT TOP 1 1 
        FROM CustomerIndividualNameSearch cn
            INNER JOIN CustomerIndividualName cin
                ON cn.CustomerIndividualNameID = cin.CustomerIndividualNameID
            CROSS JOIN NameCriteria cnc
        WHERE cin.CustomerNumberID = c.CustomerNumberID
            AND cn.LastName LIKE cnc.LastName ESCAPE @escape)
ORDER BY c.CustomerNumberID
OFFSET @SKIP ROWS FETCH NEXT @ROWS ROWS ONLY

接下来,我将查看 CROSS JOIN 语句 - 您希望将拥有的每条记录与每个名称标准进行比较,但这可能会导致大量记录进入您的 LIKE 语句。

如果模式以文本开头,Microsoft SQL 更擅长使用索引优化 LIKE,因此 'something%''%something' 更快 - 这将取决于 CustomerIndividualNameCriteriaExpansion 返回的内容。

最后,您有一个嵌套的 EXISTS 语句与外部表的连接 - 这些在查询计划中可能相当混乱 - 看看那里是否有一些缓慢的表扫描。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-04
    • 1970-01-01
    • 2023-03-19
    • 2011-09-08
    相关资源
    最近更新 更多