建議的方法都不是最佳的存儲方式。 最好的方法是在會話的基礎上使用動態表格的條形段。
這與範式的原型: -
- 做一個談話多個參與者。
- 選項確認聊天。
- 動作更新選項。
- 發佈附件的選項。
- 選項可以分享您當前位置的地圖座標。
- 離開聊天的選項。
類型
Coordinates(
lat FLOAT(10, 6) NOT NULL ,
lng FLOAT(10, 6) NOT NULL
)
架構
dbo.User(UserId,<..Details..>)
dbo.Conversation(ConversationId,Title,CreationDate,LastActivityDate)
指數:LastActivityDate,的conversationId表
dbo.Participants(ConversationId,UserId)
收集 - 動態創建
msg.msg_*ConversationId*(MessageId,FromUserId,Message,Attachment,LocationCoordinates,Action,LogDate,AcknowledgeDate)
抽象
usp_TouchMessage(@Which):
if (not exists (select 1 from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA+'.'+TABLE_NAME = 'msg.msg_'+CAST(@Which as nvarchar(max)))
begin
@dynamic_sql = 'create table msg.msg_'+CAST(@Which as nvarchar(max))+' (MessageId uniqueidentifier,FromUserId uniqueidentifier,Message nvarchar(max),Attachment BLOB,LocationCoordinates Coordinates,Action nvarchar(max),LogDate DateTime, AcknowledgeDate DateTime);';
exec(@dynamic_sql);
@dynamic_sql = 'CREATE TRIGGER msg.trig_msg_'+CAST(@Which as nvarchar(max))+' ON msg.msg_'+CAST(@Which as nvarchar(max))+' AFTER INSERT AS Delete From msg.msg_'+CAST(@Which as nvarchar(max))+' where MessageId in (Select MessageId,ROW_NUMBER() OVER (order by LogDate Desc,AcknowledgeDate Desc,MessageId Desc) RN from msg.msg_'+CAST(@Which as nvarchar(max))+') where RN>=5000';
exec(@dynamic_sql);
end
usp_GetParticipants(@Where) :
Select User.UserId,User.FullName
from Participants
inner join Users on (
Participants.UserId = Users.UserId
And Participants.ConversationId = @Where
);
usp_AddParticipants(@Who, @Where) :
insert into Participants(ConversationId,UserId) values (@Where, @Who);
@action = (select User.FullName + ' has joined the chat' from User where User.UserId = @Who);
update Conversation set LastActivityDate = GETUTCDATE() where ConversationId = @conversation_id;
exec usp_TouchMessage(@Where);
@dynamic_sql = 'insert into msg.msg_'+CAST(@Where as nvarchar(max))+' (MessageId,FromUserId,Action,LogDate) values (NewId(),@Who,@Action,GETUTCDATE())';
sp_executesql @dynamic_sql, N'@Who uniqueidentifier,@Action nvarchar(max)', @Who = @Who, @Action = @Action;
usp_GetConversationList() :
With Participation As (
Select User.UserId,User.FullName,Participants.ConversationId
from Participants
inner join Users on (Participants.UserId = Users.UserId)
) select Conversation.*,
(STUFF((
SELECT ',' + CAST([FullName] AS nvarchar(max))
FROM Participation
WHERE (Participation.ConversationId = Conversation.ConversationId)
FOR XML PATH ('')
),1,1,'')) ParticipantList
from Conversation
order by Conversation.LastActivityDate;
usp_GetConversationById(@Which,@Lite = 0,@Page = 1) :
Select User.UserId,User.FullName
from Participants
inner join Users on (Participants.UserId = Users.UserId and Participants.ConversationId = @Which);
@dynamic_sql = 'select * from
(select u.UserId,u.FullName,m.MessageId,'
+(case when @Lite=1 then 'm.Message,m.LocationCoordinates,m.Attachment,m.Action,' else '' end)
+'m.LogDate,m.AcknowledgeDate, ROW_NUMBER() Over (order by m.LogDate Desc,m.AcknowledgeDate Desc,m.MessageId Desc) RN
From msg.msg_'+CAST(@Which AS nvarchar(max))+' m
inner join User u on (m.FromUserId = u.UserId)
) tmp
where RN Between ((@Page-1)*20+1) AND (@Page*20+1)
';
sp_executesql @dynamic_sql, N'@Page bigint', @Page = @Page;
If @Page = 1 And @Lite=0
begin
@dynamic_sql = 'update msg.msg_'+CAST(@Which as nvarchar(max))+' Set AcknowledgeDate = GETUTCDATE() where AcknowledgeDate is null and FromUserId <> @Who';
sp_executesql @dynamic_sql, N'@Who uniqueidentifier', @Who = @Who;
end
usp_GetConversation(@Who,@WithWhome,@Lite = 0,@Page = 1) :
@conversation_id = (
Select top 1 ConversationId
from Participants self
inner join Participants partner
on (self.ConversationId = partner.ConversationId and self.UserId = @Who and partner.UserId = @WithWhome)
where (Select count(1) from Participants where ConversationId = self.ConversationId) = 2
);
if(@conversation_id is not null)
then
exec usp_GetConversationById(@conversation_id, @Lite, @Page);
end
usp_PostConversationById(@Who,@Which,@WhatMessage,@WhichLocation,@WhatAttachment) :
update Conversation set LastActivityDate = GETUTCDATE() where ConversationId = @Which;
exec usp_TouchMessage(@Which);
@dynamic_sql = 'insert into msg.msg_'+CAST(@Which as nvarchar(max))+' (MessageId,FromUserId,Message,Attachment,LocationCoordinates,LogDate) values (NewId(),@Who,@WhatMessage,@WhichLocation,@WhatAttachment,GETUTCDATE())';
sp_executesql @dynamic_sql, N'@Who uniqueidentifier,@WithWhome uniqueidentifier,@WhatMessage nvarchar(max),@WhichLocation Coordinates,@WhatAttachment BLOB', @Who = @Who, @WhatMessage = @WhatMessage, @WhichLocation = @WhichLocation, @WhatAttachment = @WhatAttachment;
usp_PostConversation(@Who,@WithWhome,@WhatMessage,@WhichLocation,@WhatAttachment) :
@conversation_id = (
Select top 1 ConversationId
from Participants self
inner join Participants partner
on (self.ConversationId = partner.ConversationId and self.UserId = @Who and partner.UserId = @WithWhome)
where (Select count(1) from Participants where ConversationId = self.ConversationId) = 2
);
if(@conversation_id is not null)
then
@conversation_id = newid()
insert into Conversation(ConversationId,CreationDate) values (@conversation_id,GETUTCDATE());
exec usp_AddParticipants(@Who,@conversation_id);
exec usp_AddParticipants(@WithWhome,@conversation_id);
end
exec usp_PostConversationById(@Who,@conversation_id,@WhatMessage,@WhichLocation,@WhatAttachment);
usp_UpdateConversationAlias(@Who,@Which,@WithWhat) :
@action = (select User.FullName + ' has changed title'+isnull(' from <b>'+Conversation.Title+'</b>','')+isnull(' to <b>'[email protected]+'</b>','') from User inner join Conversation on (Conversation.ConversationId = @Which and User.UserId = @Who));
update Conversation set LastActivityDate = GETUTCDATE(), Title = @WithWhat where ConversationId = @conversation_id;
if (not exists (select 1 from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA+'.'+TABLE_NAME = 'msg.msg_'+CAST(@Which as nvarchar(max)))
exec usp_TouchMessage(@Which);
@dynamic_sql = 'insert into msg.msg_'+CAST(@Which as nvarchar(max))+' (MessageId,FromUserId,Action,LogDate) values (NewId(),@Who,@Action,GETUTCDATE())';
sp_executesql @dynamic_sql, N'@Who uniqueidentifier,@Action nvarchar(max)', @Who = @Who, @Action = @Action;
usp_LeaveConversation(@Who,@Which) :
delete from Participants where ConversationId = @Where and UserId = @Who;
if(not exists (Select 1 From Participants Where ConversationId = @Which))
begin
@dynamic_sql = 'drop table msg.msg_'+CAST(@Which as nvarchar(max))+';
exec @dynamic_sql;
delete from Conversation where ConversationId = @Which;
end
else
begin
@action = (select User.FullName + ' has left the chat' from User where User.UserId = @Who);
update Conversation set LastActivityDate = GETUTCDATE() where ConversationId = @conversation_id;
exec usp_TouchMessage(@Which);
@dynamic_sql = 'insert into msg.msg_'+CAST(@Which as nvarchar(max))+' (MessageId,FromUserId,Action,LogDate) values (NewId(),@Who,@Action,GETUTCDATE())';
sp_executesql @dynamic_sql, N'@Who uniqueidentifier,@Action nvarchar(max)', @Who = @Who, @Action = @Action;
end
爲什麼 「不是在客戶端」?有沒有特定的理由不這樣做?是否還有其他要求提供純粹的「用戶自由」服務?順便說一下,什麼是巨大的?你的服務器是如何配置的? – 2011-12-28 12:21:36
最自然的解決辦法是從你的問題1(b)。如果僅在兩個用戶之間發生「對話」,則他們的ID和自動增量字段可以形成體面的主鍵。或者如果你有一個對話的概念(即對話=一個聊天會話),那麼你用它作爲ID。爲什麼這會很慢? – ArjunShankar 2011-12-28 12:22:10
我不會過分擔心1b的速度。即使對話持續數年,每天有幾百封郵件,但您想要一次查看所有郵件的機率很小。即使用戶打開完整歷史記錄的聊天窗口,您也可以輕鬆地在當前視口周圍預取幾行內容。無論如何,MySQL能夠比任何人都可以更快地獲得線路。 – Fredrik 2011-12-28 12:22:54