使用多个表和联接加速sql搜索

sirbozc5  于 2021-06-25  发布在  Mysql
关注(0)|答案(3)|浏览(353)

虽然我精通技术领域的不同领域,但我对sql还是新手。我做了大量的搜索,发现了许多类似的问题,不幸的是,我无法理解我所看到的,在与我的查询相关联的东西。所以请善待我。。。
我们办公室的新软件允许对我们的数据库创建新的查询。我创建了一个搜索,它会提示用户输入一个电话号码,查询会在我们系统中的所有帐户中搜索该电话号码,并显示拥有该电话号码的帐户。在我们的系统中大约有179000个帐户,查询是在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

提前谢谢!

dtcbnfnu

dtcbnfnu1#

@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
qmb5sa22

qmb5sa222#

“不要在列之间展开数组。”
重新构造架构。有一张主要是电话号码的table。它可能有一个从人到电话的1:many链接(或者你可能需要many:many.)
因此,这是一个简单的问题 JOIN 一次电话号码测试。
它去掉了所有15列的电话号码。而且,它更优雅地与手机数量少于15部的人打交道。它让一个人拥有超过15个。

s4n0splo

s4n0splo3#

最直接的解决方案是使用联合,如下所示:
(注意:查询实际上没有看上去那么复杂;为了清晰起见,我把每一个联合体的组成部分都放在了原来的部分。)

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

另外,通过将或子查询更改为in-list可以获得一定的速度;更新版本的mysql对这些做了一些优化。

相关问题