问题
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