使用多个表和连接加速SQL搜索

时间:2018-01-12 20:23:10

标签: mysql sql left-join query-performance

虽然我精通科技领域的不同领域,但我是SQL的新手。我做了很多搜索,发现了许多类似的问题,遗憾的是我无法理解我所看到的,将它与我的查询联系起来。所以请善待......

我们办公室的新软件允许为我们的数据库创建新查询。我创建了一个搜索,提示用户输入电话号码,查询将在我们的系统中搜索该电话号码的所有帐户,并显示具有该电话号码的帐户。我们的系统中有大约179,000个帐户,查询是在7个不同的表中的19个不同字段中检查提示中提供的电话号码。

搜索有效,但需要大约33秒,这在今天的年代和时代感觉太长了,特别是对于那个打电话的人,我们正在搜索他们的帐户。但也许这会得到它会得到的好处?我确实意识到我正在搜索大量信息。我也愿意将结果限制在过去7年的帐户中,但是当我添加这个限定符时,它只显示过去7年的结果,但它根本没有加快搜索速度,所以我把它拿走了退出。

有什么方法可以加快这个查询的速度吗?我们只搜索一个字段的简单手机搜索几乎是即时的,虽然我不希望这样,但我希望尽可能缩短查询时间。

以下是代码:

SELECT
    '[!Enter Phone Number|String|0]' AS 'Phone',
    COLLACCT@.RECNUM AS 'AccountNumber',
    COLLACCT@.COLLECTORNUMBER AS 'Collector',
    COLLDEBT@.LASTNAME || ' ' || COLLDEBT@.FIRSTNAME AS 'MakerName',
    COLLDEBT1@.LASTNAME || ' ' || COLLDEBT1@.FIRSTNAME AS 'Co-MakerName',
    COLLDEBT@.CITY AS 'City',
    COLLDEBT@.STATEANDZIP AS 'StateAndZip',
    COLLACCT@.MASTERACCOUNT AS 'DebtorNumber'
FROM COLLDEBT@
    LEFT JOIN COLLACCT@ ON COLLACCT@.MASTERACCOUNT = COLLDEBT@.RECNUM
    LEFT JOIN U_CELLPHN@ ON U_CELLPHN@.MASTERLINK = COLLDEBT@.RECNUM
    LEFT JOIN COLLDEBT1@ ON COLLDEBT1@.MASTER = COLLDEBT@.RECNUM
    LEFT JOIN U_SPOUSEINFO@ ON U_SPOUSEINFO@.MASTERLINK = COLLDEBT@.RECNUM
    LEFT JOIN U_ASTSCRN@ ON U_ASTSCRN@.MASTERLINK = COLLDEBT@.RECNUM
    LEFT JOIN U_ASTSCRNB@ ON U_ASTSCRNB@.MASTERLINK = COLLDEBT@.RECNUM
    LEFT JOIN AUXDEBTOR@ ON AUXDEBTOR@.DEBTORMASTER = COLLDEBT@.RECNUM
WHERE 
    COLLDEBT@.PHONE = Phone
    OR U_SPOUSEINFO@.SPOUSEPHN = Phone
    OR U_CELLPHN@.CELLMKR = Phone
    OR COLLDEBT1@.PHONE = Phone
    OR U_ASTSCRN@.PHONE0 = Phone
    OR U_ASTSCRN@.PHONE1 = Phone
    OR U_ASTSCRN@.PHONE2 = Phone
    OR U_ASTSCRN@.PHONE3 = Phone
    OR U_ASTSCRN@.PHONE4 = Phone
    OR U_ASTSCRN@.PHONE5 = Phone
    OR U_ASTSCRN@.PHONE6 = Phone
    OR U_ASTSCRN@.PHONE7 = Phone
    OR U_ASTSCRN@.PHONE8 = Phone
    OR U_ASTSCRN@.PHONE9 = Phone
    OR U_ASTSCRNB@.PHONE10 = Phone
    OR U_ASTSCRNB@.PHONE11 = Phone
    OR U_ASTSCRNB@.PHONE12 = Phone
    OR U_ASTSCRNB@.PHONE13 = Phone
    OR U_ASTSCRNB@.PHONE14 = Phone
    OR AUXDEBTOR@.EMPLOYERPHONE = Phone
 GROUP BY 
    MakerName
 ORDER BY 
    MakerName

提前谢谢!

3 个答案:

答案 0 :(得分:1)

@otisbartleh,只是为了突出我在评论中描述的方法的基本结构。我没有输入整个查询,所以我使用省略号来反映你填写的位置。

基本上你正在做的是首先从所有符合电话标准的表中获取一个帐号列表,然后,一旦你有一个匹配(和重复数据删除)的帐号列表(我认为应该这样)为了最小化,你基本上只是在查询表格以了解这些帐户的详细信息(应该很快)。

如果您每天多次运行此查询以查找不同的电话号码,您可能需要创建一个表格来索引数据库中的所有电话号码并将其与帐号相匹配(这可能需要一点点最初的时间),然后很容易查找匹配任何特定个人电话号码的帐户,因为您已准备好交叉参考表格。

WITH u_astscrn_matches AS
(
    SELECT  
        masterlink AS master_debtor_id
    FROM 
        U_ASTSCRN@
    WHERE   
        @phone IN (phone0, phone1, phone2, ...)
)
,u_astscrn_b_matches AS
(
    SELECT  
        masterlink AS master_debtor_id
    FROM 
        U_ASTSCRNB@
    WHERE   
        @phone IN (phone10, phone11, phone12, ...)
)   
...

,all_matches AS
(
    SELECT master_debtor_id FROM u_astscrn_matches
    UNION
    SELECT master_debtor_id FROM u_astscrn_b_matches
    UNION
    ...
)

SELECT
    ...

FROM
    all_matches AS am

LEFT JOIN
    COLLDEBT@ AS cd
    ON (cd.recnum = am.master_debtor_id)

LEFT JOIN
    ... --join onto other tables to get all the debtor details

答案 1 :(得分:0)

"不要在列之间显示数组。"

重构架构。有一张桌子主要用于电话号码。它可能有一个从人到手机的1:很多链接。 (或者你可能需要很多:很多。)

有了它,这是一个简单的JOIN和一个电话号码测试。

它取消了所有15列电话号码。它可以更轻松地与少于15部手机的人交流。它让一个人拥有超过15个。

答案 2 :(得分:0)

最直接的解决方案是使用UNION,如下所示:

(注意:查询实际上并不像看起来那么复杂;为了清楚起见,我将每个UNION部分替换为原始部分。)

SELECT
    '[!Enter Phone Number|String|0]' AS 'Phone',
    COLLACCT@.RECNUM AS 'AccountNumber',
    COLLACCT@.COLLECTORNUMBER AS 'Collector',
    COLLDEBT@.LASTNAME || ' ' || COLLDEBT@.FIRSTNAME AS 'MakerName',
    COLLDEBT1@.LASTNAME || ' ' || COLLDEBT1@.FIRSTNAME AS 'Co-MakerName',
    COLLDEBT@.CITY AS 'City',
    COLLDEBT@.STATEANDZIP AS 'StateAndZip',
    COLLACCT@.MASTERACCOUNT AS 'DebtorNumber'
FROM COLLDEBT@
    LEFT JOIN COLLACCT@ ON COLLACCT@.MASTERACCOUNT = COLLDEBT@.RECNUM
WHERE 
    COLLDEBT@.PHONE = Phone
    OR COLLDEBT@.RECNUM IN (        
        -- LEFT JOIN U_CELLPHN@ ON U_CELLPHN@.MASTERLINK = COLLDEBT@.RECNUM
        SELECT MASTERLINK FROM U_CELLPHN@  WHERE CELLMKR = Phone
        -- OR U_CELLPHN@.CELLMKR = Phone        
        UNION       
        -- LEFT JOIN COLLDEBT1@ ON COLLDEBT1@.MASTER = COLLDEBT@.RECNUM
        SELECT MASTER FROM COLLDEBT1@ WHERE PHONE = Phone
        -- OR COLLDEBT1@.PHONE = Phone
        UNION
        -- LEFT JOIN U_SPOUSEINFO@ ON U_SPOUSEINFO@.MASTERLINK = COLLDEBT@.RECNUM
        SELECT MASTERLINK FROM U_SPOUSEINFO@ WHERE SPOUSEPHN = Phone
        -- OR U_SPOUSEINFO@.SPOUSEPHN = Phone
        UNION
        -- LEFT JOIN U_ASTSCRN@ ON U_ASTSCRN@.MASTERLINK = COLLDEBT@.RECNUM
        SELECT MASTERLINK
        FROM U_ASTSCRN@ 
        WHERE PHONE0 = Phone
            OR PHONE1 = Phone
            OR PHONE2 = Phone
            OR PHONE3 = Phone
            OR PHONE4 = Phone
            OR PHONE5 = Phone
            OR PHONE6 = Phone
            OR PHONE7 = Phone
            OR PHONE8 = Phone
            OR PHONE9 = Phone
        -- OR U_ASTSCRN@.PHONE0 = Phone
        -- OR U_ASTSCRN@.PHONE1 = Phone
        -- OR U_ASTSCRN@.PHONE2 = Phone
        -- OR U_ASTSCRN@.PHONE3 = Phone
        -- OR U_ASTSCRN@.PHONE4 = Phone
        -- OR U_ASTSCRN@.PHONE5 = Phone
        -- OR U_ASTSCRN@.PHONE6 = Phone
        -- OR U_ASTSCRN@.PHONE7 = Phone
        -- OR U_ASTSCRN@.PHONE8 = Phone
        -- OR U_ASTSCRN@.PHONE9 = Phone
        UNION
        -- LEFT JOIN U_ASTSCRNB@ ON U_ASTSCRNB@.MASTERLINK = COLLDEBT@.RECNUM
        SELECT MASTERLINK
        FROM U_ASTSCRNB@ 
        WHERE PHONE10 = Phone
            OR PHONE11 = Phone
            OR PHONE12 = Phone
            OR PHONE13 = Phone
            OR PHONE14 = Phone
        -- OR U_ASTSCRNB@.PHONE10 = Phone
        -- OR U_ASTSCRNB@.PHONE11 = Phone
        -- OR U_ASTSCRNB@.PHONE12 = Phone
        -- OR U_ASTSCRNB@.PHONE13 = Phone
        -- OR U_ASTSCRNB@.PHONE14 = Phone
        UNION       
        -- LEFT JOIN AUXDEBTOR@ ON AUXDEBTOR@.DEBTORMASTER = COLLDEBT@.RECNUM
        SELECT DEBTORMASTER FROM AUXDEBTOR@ WHERE EMPLOYERPHONE = Phone
        -- OR AUXDEBTOR@.EMPLOYERPHONE = Phone
    )    
 GROUP BY 
    MakerName
 ORDER BY 
    MakerName

此外,通过将OR子查询更改为IN列表可以获得一些速度;最新版本的MySQL已对这些版本进行了一些优化。