Порядок сортировки первичного ключа SQL - PullRequest
2 голосов
/ 03 сентября 2010

Я использую MS SQL server 2005

У меня есть таблица с 3 столбцами, в которой я храню отображение сообщений пользователя, например:

msg_for msg_from msg_id 
bob     bob      1 
bob     john     1 
bob     steve    1 
bob     bob      2 
bob     john     2 
bob     bob      3 
bob     john     3 
bob     steve    3

PK находится в 3 столбцах, а msg_id - это таблица FK to messages, в которой хранятся сообщения

Выше указано физическое хранилище, которое я вижу в соответствии с PK на 3 столбцах

Теперь мой запрос ДОЛЖЕН возвращать сообщения для данного пользователя с последней версией сообщения (порядок по msg_id DESC)

bob john  3
bob steve 3
bob john  2
bob steve 2
bob john  1
bob steve 1

Эта таблица сопоставления содержит миллионы строк. Я вижу, что 95% стоимости - это сортировка результата.

Возможно ли, чтобы PK или какой-либо другой способ физически хранили данные таким образом (избегайте SORT)?

msg_for msg_from msg_id
bob     bob      3
bob     john     3
bob     steve    3
bob     bob      2
bob     john     2
bob     bob      1
bob     john     1
bob     steve    1

Спасибо

Ответы [ 4 ]

4 голосов
/ 03 сентября 2010

Да.

Когда вы устанавливаете первичный ключ (или любой индекс), вы можете определить это

ALTER TABLE dbo.[Messages] ADD CONSTRAINT [PK_Messages] PRIMARY KEY CLUSTERED 
(
    msg_for ASC, msg_from ASC, msg_id DESC
)

SQL Server может сканировать в любом направлении, поэтому имеет смысл, если вы хотите управлять комбинацией порядка сортировки для нескольких столбцов.

Редактировать: Вы говорите в комментариях, что проблемный запрос

select top 10 msg_id 
from message_user 
where msg_for = @user_name 
and msg_from <> @user_name 
order by msg_id DESC

Проблема здесь не в восходящем, нисходящем.

Чтобы привести аналогию. Телефонные книги перечислены по фамилии, по порядку имен, но если вам необходимо узнать последние 10 лексикографических имен в каталоге, вам нужно будет отсканировать всю книгу. Это было бы неизбежно независимо от того, были ли имена в каждом разделе перечислены в порядке возрастания или убывания.

Аналогично, составные индексные ключи должны быть msg_for, msg_id, msg_from, чтобы оптимально удовлетворить этот запрос, а не msg_for, msg_from, msg_id При этом последнем порядке все равно потребуется сканировать весь раздел индекса, удовлетворяющий критериям msg_for = @user_name, поскольку он не может знать если будет еще более позднее msg_id, принадлежащее более позднему msg_from Кроме того, независимо от того, в каком направлении msg_id отсортировано в их отдельных подразделах, для последовательного сканирования части msg_for = @user_name индекса все равно потребуется сортировать их как фрагментированные, находясь в подразделах согласно msg_from.

3 голосов
/ 03 сентября 2010

Единственный способ гарантировать порядок в наборе результатов - использовать ORDER BY.

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

1 голос
/ 04 сентября 2010

Что ж, неудивительно, что сортировка длится вечно. Типы Varchar / string обычно являются типами, которые очень тяжелы, когда дело доходит до сортировки, будь то SQL или любой другой язык программирования в этом отношении. По возможности используйте для таких вещей целочисленные типы.

Я предлагаю вам использовать интегральные значения для идентификации членов. Есть таблица Members (MemberId INT, MemberName VARCHAR, etc), таблица Messages (MessageId INT, MessageBody VARCHAR, etc), а затем таблица соединения, скажем Correspondence с (SenderMemberId INT, RecipientMemberId INT, MessageId INT). Сортировка по интегральным значениям будет намного быстрее.

Я думаю, что вы можете легко реорганизовать ваши данные, чтобы соответствовать такой новой структуре.

0 голосов
/ 03 сентября 2010

В зависимости от вашей СУБД, вы можете использовать кластеризованный индекс для достижения этого.

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