Sql Server производительность запросов? - PullRequest
2 голосов
/ 11 февраля 2010

У меня есть контакты, которые могут входить в несколько групп и иметь более одного запроса. Мне нужно просто получить контакты для определенной группы, у которых нет особых запросов.

Как улучшить производительность этого запроса:

SELECT  top 1 con_name ,
        con_id
FROM    tbl_group_to_contact gc
        INNER JOIN tbl_contact c ON gc.con_id = c.id
WHERE   group_id = '81'
        AND NOT c.id IN ( SELECT    con_id
                          FROM      tbl_request_to_contact
                          WHERE     request_id = '124' )

Когда я запускаю этот запрос с планом объяснения, он показывает, что этот запрос:

SELECT    con_id
                          FROM      tbl_request_to_contact
                          WHERE     request_id = '124'

дорого с использованием поиска по индексу.

 |--Top(TOP EXPRESSION:((1)))
       |--Nested Loops(Left Anti Semi Join, OUTER REFERENCES:([c].[id]))
            |--Nested Loops(Inner Join, OUTER REFERENCES:([gc].[con_id], [Expr1006]) WITH UNORDERED PREFETCH)
            |    |--Clustered Index Scan(OBJECT:([db_newsletter].[dbo].[tbl_group_to_contact].[PK_tbl_group_to_contact_1] AS [gc]),  WHERE:([db_newsletter].[dbo].[tbl_group_to_contact].[group_id] as [gc].[group_id]=(81)) ORDERED FORWARD)
            |    |--Clustered Index Seek(OBJECT:([db_newsletter].[dbo].[tbl_contact].[PK_tbl_contact] AS [c]), SEEK:([c].[id]=[db_newsletter].[dbo].[tbl_group_to_contact].[con_id] as [gc].[con_id]) ORDERED FORWARD)
            |--Top(TOP EXPRESSION:((1)))
                 |--Clustered Index Seek(OBJECT:([db_newsletter].[dbo].[tbl_request_to_contact].[PK_tbl_request_to_contact] AS [cc]), SEEK:([cc].[request_id]=(124)),  WHERE:([db_newsletter].[dbo].[tbl_contact].[id] as [c].[id]=[db_newsletter].[dbo].[tbl_request_to_contact].[con_id] as [cc].[con_id]) ORDERED FORWARD)

Ответы [ 3 ]

2 голосов
/ 11 февраля 2010

Ваш запрос в порядке, просто создайте следующие индексы:

tbl_request_to_contact (request_id, con_id)
tbl_group_to_contact (group_id, con_id)

Поскольку таблицы, по-видимому, являются таблицами ссылок, вы хотите сделать эти композиции первичными ключами:

ALTER TABLE tbl_request_to_contact ADD CONSTRAINT pk_rc PRIMARY KEY (request_id, con_id)
ALTER TABLE tbl_group_to_contact ADD CONSTRAINT pk_gc (group_id, con_id)

, убедившись, что request_id и group_id идут первыми.

Также, если ваши request_id и group_id являются целыми числами, передайте целые числа в качестве параметров, а не строки:

SELECT  con_name, con_id
FROM    tbl_group_to_contact gc
JOIN    tbl_contact c
ON      c.id = gc.con_id
WHERE   group_id = 81
        AND c.id NOT IN
        (
        SELECT  con_id
        FROM    tbl_request_to_contact
        WHERE   request_id = 124
        )

, или может произойти неявное преобразование, делающее индексы непригодными.

Обновление:

Из вашего плана я вижу, что вы пропускаете индекс по tbl_group_to_contact. Для фильтрации групп требуется полное сканирование таблицы.

Создать индекс:

CREATE UNIQUE INDEX ux_gc ON tbl_group_to_contact (group_id, con_id)
0 голосов
/ 11 февраля 2010

Я согласен с @Quassnoi с индексами. Кроме того, вы можете использовать левое объединение, чтобы показывать только тех пользователей, у которых нет запросов. Обычно это имеет лучшую производительность, чем подзапрос.

Для чего нужен request_id = '124'? Другой идентификатор запроса не имеет значения?

SELECT  con_name ,
        con_id
FROM    tbl_group_to_contact gc
        INNER JOIN tbl_contact c ON gc.con_id = c.id
        LEFT JOIN tbl_request_to_contact rtc ON gc.con_id = rtc.con_id
WHERE   group_id = '81' and rtc.request_id IS NULL 
0 голосов
/ 11 февраля 2010

Возможно, вы захотите запустить помощник по настройке базы данных SQL Server .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...