سؤال

هذا سؤال حول المقايضة.

تخيل شبكة اجتماعية.كل مستخدم لديه رسالة حالة، يمكنه تغييرها في أي وقت.كلما قام بتغييره، يتم إخطار جميع أصدقائه عبر الحائط (كما هو الحال في الفيسبوك).

لجعل هذا العمل.لدينا 3 جداول المستخدمين (المعرف، الاسم)، قوائم الأصدقاء (معرف المستخدم، معرف المستخدم الصديق)، الإخطارات (؟).

لنفترض الآن أن كل مستخدم لديه ما يقرب من 50 صديقًا في قائمة أصدقائه.أواجه معضلة - كيفية تنفيذ جدول الإشعارات.


الخيار الأول

CREATE TABLE Notifications
(
toUserId bigint NOT NULL,
[identity] bigint IDENTITY(1,1) NOT NULL,
fromUserId bigint NOT NULL,
data varchar(256) NOT NULL,
CONSTRAINT [PK_Notifications] PRIMARY KEY CLUSTERED (toUserId, [identity])
)

إرسال الإخطارات:

-- Get all friends of @fromUserId.
WITH Friends AS
   (SELECT FriendLists.friendUserId
 FROM FriendLists
 WHERE userId = @fromUserId)
-- Send updates to all friends.
SELECT
 friendUserId as toUserId,
 @fromUserId as fromUserId,
 @data as data
INTO Notifications
FROM Friends

في هذه الحالة، لكل تغيير في الحالة نقوم بإنشاء 50 سجلاً (على افتراض 50 صديقًا).هذا سيء.ومع ذلك، النقطة الجيدة هي أن استرداد الإشعارات لمستخدم معين يكون أمرًا سريعًا للغاية، نظرًا لوجود فهرس متفاوت المسافات في toUserId.

الخيار الثاني

CREATE TABLE Notifications
(
toUserId bigint NOT NULL,
[identity] bigint IDENTITY(1,1) NOT NULL,
fromUserId bigint NOT NULL,
data varchar(256) NOT NULL,
CONSTRAINT [PK_Notifications] PRIMARY KEY CLUSTERED ([identity])
)
CREATE NONCLUSTERED INDEX [IX_toUserId] ON Notifications (toUserId ASC)

إرسال الإخطارات:

-- Get all friends of @fromUserId.
WITH Friends AS
   (SELECT FriendLists.friendUserId
 FROM FriendLists
 WHERE userId = @fromUserId)
-- Send updates to all friends.
INSERT INTO Notifications(toUserId, fromUserId, data)
    VALUES(friendUserId, @fromUserId, @data)

نقوم هنا بإدراج سجل واحد فقط لكل تحديث للحالة.هذا جيد.النقطة السيئة هي أن استرجاع الإخطارات سيكون أبطأ، حيث لا يتم تجميع السجلات بواسطة toUserId.


الحصول على الإخطارات هو نفسه لكلا الطريقتين:

SELECT TOP(50) fromUserId, [identity], data
FROM Notifications
WHERE toUserId  = @toUserId

إذن ما هو رأيك في هذا؟

هل كانت مفيدة؟

المحلول

أولاً، ستكون عمليات القراءة دائمًا مرهقة مقارنة بعمليات الكتابة، لأن كل "جدار" ستتم رؤيته عدة مرات أكثر مما سيتم تحديثه.لذا من الأفضل أن تجعل القراءة سريعة.

ثانيًا، إحدى المشكلات المتأصلة في هذا النوع من مواقع الشبكات الاجتماعية الكبيرة هي توزيع البيانات (التقسيم، التقسيم، لن تتمكن قاعدة بيانات واحدة على الإطلاق من تخزين جميع الحسابات، وجميع الأصدقاء، وجميع الإشعارات) مما يعني أنه عند ظهور إشعار جديد تم وضعه على الحائط، يجب إخطار الأصدقاء به آخر الخوادم.وهذا يعني أن التحديثات غير متزامنة وتعتمد على المراسلة على أي حال.

لذلك سأختار بالتأكيد البنية المُحسّنة للقراءة.

أنصحك بمراجعة العروض التقديمية العامة التي قدمها العديد من الأشخاص المشاركين في تصميم مواقع مثل Facebook وMySpace، مثل هذه كريستا ستيلزمولر.يشرحون الكثير من التفكير والمنطق الذي يدخل في تصميمهم.

نصائح أخرى

التحديثات بطيئة جدًا مقارنة بالتحديدات ...بضعة أوامر من حيث الحجم.بالإضافة إلى ذلك، مع توسع موقعك، ستقوم بتخزين جميع عمليات الجلب في الذاكرة مؤقتًا، وبالتالي فإن سرعة التحديدات ستكون تافهة.

في هذه الحالة، يبدو إنشاء فهرس متفاوت المسافات على (toUser,identity) فكرة سيئة لأنه يجب بالفعل إدراج فهرس متفاوت المسافات بترتيب تصاعدي.بالطبع ستهتم لغة SQL بالحفاظ على ترتيب الجدول ولكن هذا يأتي بتكلفة أداء عالية (وهذا هو الهدف من سؤالك.) ولكن بشكل عام، لا يُنصح باستخدام الإدخالات المعروفة مسبقًا بأنها ليست بترتيب معين الفهارس المجمعة.هنا هو جيد جدا ثلاثة جزء شرط حول توصيات الفهرس المجمع.

بعد قولي هذا، سألتزم بعمود الهوية باعتباره الفهرس المجمع وأقوم بإنشاء فهرس غير مجمع على toUserId وربما عمود التاريخ والوقت.ومن خلال تضمين عمود التاريخ والوقت، يمكنك الاستعلام بشكل أكثر كفاءة عن البيانات الحديثة.

فيما يتعلق بالتحديثات البطيئة، تعد تحديثات الحالة على مواقع الشبكات الاجتماعية وضعًا مثاليًا لقوائم انتظار الرسائل.وبهذه الطريقة يمكنك ضبط قاعدة البيانات حسب الحاجة لجعل عمليات القراءة سريعة وإذا كان لها تأثير على أداء الكتابة، فلن يضطر المستخدم إلى المعاناة.من وجهة نظرهم، كان التحديث فوريًا على الرغم من أن الأمر قد يستغرق بضع دقائق حتى "يلتصق".

بالنسبة لقواعد البيانات الكبيرة جدًا، سأرجع إلى معلمي SQL الذين يمكنهم التحدث عن استراتيجيات التقسيم (جداول أصغر أكثر قابلية للإدارة للبيانات الأحدث، وجداول أكبر/مفهرسة بشكل كبير للبيانات الأقدم) وحلول النسخ المتماثل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top