问题
I work on a small chat application with database. I create the database shown in the image.
I new to indexes and I want to choose the appropriate indexes for the query.
Can I use clustered index in the Messages table ? and if I can, Which column (or columns) should have clustered index ? or should I use non-clustered index ?
Update: The query that I user to get messages is :
Select TextContent From Messages where (SenderId='1' and ReciverID = '2') or (SenderId='2' and ReciverID = '1') order by date
The values for SenderID and ReciverID is just for clarification.
回答1:
You probably should add a surrogate primary key to your messages table and create an index:
ALTER TABLE messages ADD COLUMN id BIGINT NOT NULL IDENTITY
ALTER TABLE messages ADD CONSTRAINT pk_messages_id PRIMARY KEY (id)
CREATE INDEX ix_messages_sender_receiver_date (senderId, receiverId, date) ON messages
If you want to retrieve, say, just top 10 last messages from the conversation chain, it might help to rewrite your query a little:
SELECT m.*
FROM (
SELECT TOP 10
*
FROM (
SELECT date, id
FROM messages
WHERE senderId = 1 AND receiverId = 2
UNION
SELECT date, id
FROM messages
WHERE senderId = 2 AND receiverId = 1
) q
ORDER BY
date DESC, id DESC
) q
JOIN messages m
ON m.id = q.id
This way, SQL Server is more likely to merge join the two directions of the conversation rather than sorting them separately.
Alternatively, instead of sender and receiver, use user1
, user2
and direction
, so that user1 < user2
(always) and direction
defines whether the text goes from user1
to user2
or vise versa.
This way, you can always filter simply on user1 = 1 AND user2 = 2
, without having to worry about OR
or unions.
You can do that in computed columns which you can also index:
ALTER TABLE messages ADD COLUMN user1 AS CASE WHEN senderId < receiverId THEN senderId ELSE receiverId END
ALTER TABLE messages ADD COLUMN user2 AS CASE WHEN senderId > receiverId THEN senderId ELSE receiverId END
ALTER TABLE messages ADD COLUMN direction AS CASE WHEN senderId < receiverId THEN 0 ELSE 1 END
CREATE INDEX ix_messages_user1_user2_date ON messages (user1, user2, date)
then select:
SELECT *
FROM messages
WHERE user1 = 1
AND user2 = 2 -- make sure lower number goes to user1, higher number goes to user2
ORDER BY
date
来源:https://stackoverflow.com/questions/31149569/how-to-choose-indexes-for-chat-application-database