[英]Speeding up a SQL search with multiple tables and joins
雖然我精通技術領域的不同領域,但我對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
先感謝您!
@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:許多鏈接。 (或者您可能需要很多:很多。)
這樣,它是一個簡單的JOIN
和電話號碼的單個測試。
並且它消除了電話號碼的所有15列。 而且,與手機數量少於15的人相比,它處理起來更為優雅。 它讓一個人擁有超過15個。
最直接的解決方案是使用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的較新版本對它們進行了一些優化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.