Ускорение поиска SQL с несколькими таблицами и объединениями

0

Хотя я хорошо разбираюсь в разных областях технической вселенной, я новичок в SQL. Я много раз искал и нашел много похожих вопросов, к сожалению, я не смог понять, что я видел, связав это с моим запросом. Так что будьте добры...

Наше новое программное обеспечение в нашем офисе позволяет создавать новые запросы в нашей базе данных. Я создал поиск, который заставит пользователя ввести номер телефона, и запрос будет искать все учетные записи в нашей системе для этого номера телефона и отображать учетные записи, у которых был этот номер телефона. В нашей системе насчитывается около 179 000 учетных записей, и запрос проверяет номер телефона, указанный в подсказке, в 19 разных полях в 7 разных таблицах.

Поиск работает, но занимает около 33 секунд, который сегодня и днем кажется слишком длинным, особенно для человека, который звонил, за счет которого мы ищем. Но может быть, это так хорошо, как это получится? Я понимаю, что просматриваю много информации. Я также был бы открыт для ограничения результатов по счетам за последние 7 лет, но когда я добавил этот классификатор, он показал только результаты за последние 7 лет, но он не ускорил поиск вообще, поэтому я принял это обратно.

Есть ли способ ускорить этот запрос? Наш простой поиск по телефону, который ищет только одно поле, почти мгновен, и, хотя я этого не ожидаю, мне бы хотелось как можно больше сократить время запроса.

Вот код:

SELECT
    '[!Enter Phone Number|String|0]' AS 'Phone',
    [email protected] AS 'AccountNumber',
    [email protected] AS 'Collector',
    [email protected] || ' ' || [email protected] AS 'MakerName',
    [email protected] || ' ' || [email protected] AS 'Co-MakerName',
    [email protected] AS 'City',
    [email protected] AS 'StateAndZip',
    [email protected] AS 'DebtorNumber'
FROM COLLDEBT@
    LEFT JOIN COLLACCT@ ON [email protected] = [email protected]
    LEFT JOIN U_CELLPHN@ ON [email protected] = [email protected]
    LEFT JOIN COLLDEBT1@ ON [email protected] = [email protected]
    LEFT JOIN U_SPOUSEINFO@ ON [email protected] = [email protected]
    LEFT JOIN U_ASTSCRN@ ON [email protected] = [email protected]
    LEFT JOIN U_ASTSCRNB@ ON [email protected] = [email protected]
    LEFT JOIN AUXDEBTOR@ ON [email protected] = [email protected]
WHERE 
    [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
    OR [email protected] = Phone
 GROUP BY 
    MakerName
 ORDER BY 
    MakerName

Заранее спасибо!

  • 0
    Если нужна другая информация, дайте мне знать. К сожалению, я не могу предоставить примеры реальных учетных записей из-за правил соответствия, но могу сделать все возможное, чтобы помочь ассистенту. ха-ха
  • 5
    Это много телефонов. Как ваша индексация выглядит для этих таблиц? Есть ли шанс, что вы могли бы улучшить схему, чтобы хранить только один телефон на запись в новой блестящей (и проиндексированной) «телефонной» таблице?
Показать ещё 16 комментариев
Теги:
left-join
query-performance

3 ответа

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
  • 0
    Я попробую эти предложения и сообщу. Я ценю это.
0

Msgstr "Не массировать массив по столбцам".

Перестройте схему. У вас есть таблица в основном для телефонных номеров. Вероятно, у него может быть связь 1: много людей с телефонами. (Или вам может понадобиться много: много.)

При этом это простой JOIN и один тест для номера телефона.

И он избавляется от всех 15 столбцов для телефонных номеров. И он более грациозно работает с людьми с менее чем 15 телефонами. И это позволяет человеку иметь более 15.

0

Самое прямое решение - использовать UNION, например:

(Примечание. Запрос на самом деле менее сложный, чем кажется, я оставил в оригинальных экземплярах каждый элемент UNION для ясности.)

SELECT
    '[!Enter Phone Number|String|0]' AS 'Phone',
    [email protected] AS 'AccountNumber',
    [email protected] AS 'Collector',
    [email protected] || ' ' || [email protected] AS 'MakerName',
    [email protected] || ' ' || [email protected] AS 'Co-MakerName',
    [email protected] AS 'City',
    [email protected] AS 'StateAndZip',
    [email protected] AS 'DebtorNumber'
FROM COLLDEBT@
    LEFT JOIN COLLACCT@ ON [email protected] = [email protected]
WHERE 
    [email protected] = Phone
    OR [email protected] IN (        
        -- LEFT JOIN U_CELLPHN@ ON [email protected] = [email protected]
        SELECT MASTERLINK FROM U_CELLPHN@  WHERE CELLMKR = Phone
        -- OR [email protected] = Phone        
        UNION       
        -- LEFT JOIN COLLDEBT1@ ON [email protected] = [email protected]
        SELECT MASTER FROM COLLDEBT1@ WHERE PHONE = Phone
        -- OR [email protected] = Phone
        UNION
        -- LEFT JOIN U_SPOUSEINFO@ ON [email protected] = [email protected]
        SELECT MASTERLINK FROM U_SPOUSEINFO@ WHERE SPOUSEPHN = Phone
        -- OR [email protected] = Phone
        UNION
        -- LEFT JOIN U_ASTSCRN@ ON [email protected] = [email protected]
        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 [email protected] = Phone
        -- OR [email protected] = Phone
        -- OR [email protected] = Phone
        -- OR [email protected] = Phone
        -- OR [email protected] = Phone
        -- OR [email protected] = Phone
        -- OR [email protected] = Phone
        -- OR [email protected] = Phone
        -- OR [email protected] = Phone
        -- OR [email protected] = Phone
        UNION
        -- LEFT JOIN U_ASTSCRNB@ ON [email protected] = [email protected]
        SELECT MASTERLINK
        FROM U_ASTSCRNB@ 
        WHERE PHONE10 = Phone
            OR PHONE11 = Phone
            OR PHONE12 = Phone
            OR PHONE13 = Phone
            OR PHONE14 = Phone
        -- OR [email protected] = Phone
        -- OR [email protected] = Phone
        -- OR [email protected] = Phone
        -- OR [email protected] = Phone
        -- OR [email protected] = Phone
        UNION       
        -- LEFT JOIN AUXDEBTOR@ ON [email protected] = [email protected]
        SELECT DEBTORMASTER FROM AUXDEBTOR@ WHERE EMPLOYERPHONE = Phone
        -- OR [email protected] = Phone
    )    
 GROUP BY 
    MakerName
 ORDER BY 
    MakerName

Кроме того, некоторую скорость можно получить, изменив подзапросы OR в списки IN; более поздние версии MySQL сделали некоторые оптимизации для них.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню