سؤال

أعلم أنه إذا قمت بتشغيل هذا الاستعلام

select top 100 * from mytable order by newid()

سيحصل على 100 سجل عشوائي من طاولتي.

ومع ذلك، فأنا في حيرة من أمري بشأن كيفية العمل، لأنني لا أرى ذلك newid() في ال select قائمة.يمكن للشخص أن يفسر؟هل هناك شيء خاص عنه newid() هنا؟

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

المحلول

أعرف ما الذي يفعله NewID () ، أحاول فقط أن أفهم كيف سيساعد ذلك في الاختيار العشوائي.هل (1) سيحدد عبارة SELECT كل شيء من mytable ، (2) لكل صف محدد ، على identediveier فريد من نوعه تم إنشاؤه بواسطة NewID () ، (3) فرز الصفوف بواسطة هذا idqueidentifier و (4) اختار الجزء العلوي 100 من القائمة المرتبة؟

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

SELECT TOP 100 * 
FROM master..spt_values 
ORDER BY NEWID()

يضيف عامل التشغيل العددي الحسابي NEWID() عمود لكل صف (2506 في الجدول في استعلام المثال الخاص بي) ثم يتم فرز الصفوف في الجدول حسب هذا العمود مع تحديد أفضل 100 صف.

لا يحتاج SQL Server فعليًا إلى فرز المجموعة بأكملها من المواضع 100 إلى الأسفل لذا فهو يستخدم TOP N عامل الفرز الذي يحاول تنفيذ عملية الفرز بأكملها في الذاكرة (للقيم الصغيرة N)

Plan

نصائح أخرى

بشكل عام يعمل مثل هذا:

  • جميع الصفوف من طاولتي هو "حلقات"
  • يتم تنفيذ NEWID() لكل صف
  • يتم فرز الصفوف حسب رقم عشوائي من NEWID ()
  • تم تحديد 100 الصف الأول

المفتاح هنا هو وظيفة NEWID، التي تنشئ معرفًا فريدًا عالميًا (GUID) في الذاكرة لكل صف.حسب التعريف، يعد المعرّف الفريد العمومي (GUID) فريدًا وعشوائيًا إلى حد ما؛لذلك، عند الفرز حسب هذا المعرف الفريد العمومي (GUID) باستخدام عبارة ORDER BY، ستحصل على ترتيب عشوائي للصفوف في الجدول.إن الحصول على أعلى 10 بالمائة (أو أي نسبة تريدها) سيمنحك عينة عشوائية من الصفوف في الجدول.

تم اقتراح استعلام NEWID؛إنه بسيط ويعمل بشكل جيد جدًا مع الطاولات الصغيرة.ومع ذلك، فإن الاستعلام NEWID له عيب كبير عند استخدامه للجداول الكبيرة.تؤدي عبارة ORDER BY إلى نسخ كافة الصفوف الموجودة في الجدول إلى قاعدة بيانات tempdb، حيث يتم فرزها.وهذا يسبب مشكلتين:عادةً ما تكون عملية الفرز ذات تكلفة عالية مرتبطة بها.يمكن أن يستخدم الفرز الكثير من عمليات الإدخال / الإخراج للقرص ويمكن تشغيله لفترة طويلة.في أسوأ السيناريوهات، يمكن أن تنفد مساحة tempdb.في أفضل السيناريوهات، يمكن أن يشغل tempdb مقدارًا كبيرًا من مساحة القرص التي لن تتم استعادتها أبدًا بدون أمر تقليص يدوي.ما تحتاجه هو طريقة لتحديد الصفوف بشكل عشوائي والتي لن تستخدم tempdb ولن تصبح أبطأ بكثير مع زيادة حجم الجدول.إليك فكرة جديدة حول كيفية القيام بذلك:

SELECT * FROM master..spt_values
  WHERE (ABS(CAST(
  (BINARY_CHECKSUM(*) *
  RAND()) as int)) % 100) < 10

الفكرة الأساسية وراء هذا الاستعلام هي أننا نريد توليد رقم عشوائي بين 0 و 99 لكل صف في الجدول، ثم اختيار جميع تلك الصفوف التي يكون رقمها العشوائي أقل من قيمة النسبة المحددة.في هذا المثال، نريد تحديد 10 بالمائة تقريبًا من الصفوف عشوائيًا؛لذلك، نختار جميع الصفوف التي يقل رقمها العشوائي عن 10.

مثل MSDN يقول:

NewID () يخلق قيمة فريدة من نوع typeidentifier.

وسيتم فرز الجدول الخاص بك حسب هذه القيم العشوائية.

يستخدم select top 100 randid = newid(), * from mytable order by randidسيتم توضيحك حينها..

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