سؤال

ما هي الطريقة الأكثر فعالية لإجراء استعلام ترحيل الصفحات في SQLServer 2000؟

حيث يكون "استعلام الترحيل" معادلاً لاستخدام عبارة LIMIT في MySQL.

يحرر:هل يمكن أن يكون الإجراء المخزن أكثر كفاءة من أي استعلام قائم على المجموعة في هذه الحالة؟

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

المحلول

ترحيل من Resultsets كبير والفائز يستخدم ROWCOUNT. أيضا هناك نسخة المعمم لمزيد من الاستفسارات المعقدة. ولكن إعطاء القروض إلى جاسمين موهاريموفيتش : ل)

DECLARE @Sort /* the type of the sorting column */
SET ROWCOUNT @StartRow
SELECT @Sort = SortColumn FROM Table ORDER BY SortColumn
SET ROWCOUNT @PageSize
SELECT ... FROM Table WHERE SortColumn >= @Sort ORDER BY SortColumn

وهذه المادة تحتوي على شفرة المصدر بأكمله.

يرجى قراءة "تحديث 2004/05/05" المعلومات. !

نصائح أخرى

وأعتقد استعلام SELECT TOP n متداخلة هو على الأرجح الطريقة الأكثر فعالية لتحقيق ذلك.

SELECT TOP ThisPageRecordCount *
FROM Table
WHERE ID NOT IN (SELECT TOP BeforeThisPageRecordCount ID FROM Table ORDER BY OrderingColumn)
ORDER BY OrderingColumn

واستبدال ThisPageRecordCount مع العناصر في الصفحة وBeforeThisPageRecordCount مع (PageNumber - 1) * items-per-page.

وبالطبع هو أفضل وسيلة في SQL Server 2005 لاستخدام وظيفة ROW_NUMBER() في CTE.

وكفاءة الاستعلام حقا يتوقف على كيفية بناء الجدول المصدر. إذا، نقول لديك مفتاح أساسي يسمى ID وهو الهوية، <م> و انها فهرس متفاوت المسافات، <م> و يمكن أن نفترض أن لا أحد كان يفعله IDENTITY_INSERTs على ذلك، يمكنك القيام به استعلام مثل:

وSELECT TOP XXX من الجدول حيث ID>LastPagesID؛

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

أعتقد أن ما لديك هنا حقًا هو سبب مقنع للترقية إلى SQL 2005.

في SQL 2005 يمكن القيام بذلك بسرعة وسهولة باستخدام:

select ROW_NUMBER() over (order by [MyField]) as rowNum, *
from [MyTable]
where rowNum between @firstRow and @lastRow

إذا كنت متمسكًا حقًا بـ SQL 2000، فسأشعر بالقلق - فلن تدعمه Microsoft بشكل كامل لفترة أطول نظرًا لأنه قد مضى الآن جيلان.

أخشى أنه لن تكون هناك طريقة واحدة أفضل للقيام بذلك - فكل الحلول هي عبارة عن اختراقات نوعًا ما.

ربما تكون إجابة @ Petar Petrov هي الأكثر اتساقًا:

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

أعتقد أنك تنظر إلى بضع ساعات من التغيير والتبديل باستخدام محلل الاستعلام في كل مرة.لن يُحدث proc المخزن فرقًا كبيرًا في كلتا الحالتين - فمن غير المرجح أن يكون التخزين المؤقت لخطة الاستعلام هو عنق الزجاجة.

وهذا هو العام ل SQL Server 2000 إجراء مخزن من شأنها أن تؤدي ترقيم الصفحات على أي جدول. الإجراء المخزن يقبل اسم الجدول، والأعمدة لإخراج (التخلف لجميع الأعمدة في الجدول)، اختياري شرط WHERE، وهو ترتيب اختياري، رقم الصفحة لاسترداد وعدد الصفوف في كل صفحة.

    CREATE PROCEDURE [dbo].[GetPage]
    @pTableName VARCHAR(30),
    @pColumns VARCHAR(200) = '*',
    @pFilter VARCHAR(200) = '',
    @pSort VARCHAR(200) = '',
    @pPage INT = 1,
    @pPageRows INT = 10
    AS

    SET NOCOUNT ON
    DECLARE @vSQL VARCHAR(4000)
    DECLARE @vTempTable VARCHAR(30)
    DECLARE @vRowStart INT
    DECLARE @vTotalRows INT

    SET @vTempTable = '##Tmp' + CAST(DATEPART(YYYY, GETDATE()) AS VARCHAR(4)) +
    CAST(DATEPART(MM, GETDATE()) AS VARCHAR(2)) +
    CAST(DATEPART(DD, GETDATE()) AS VARCHAR(2)) +
    CAST(DATEPART(HH, GETDATE()) AS VARCHAR(2)) +
    CAST(DATEPART(MI, GETDATE()) AS VARCHAR(2)) +
    CAST(DATEPART(SS, GETDATE()) AS VARCHAR(2)) +
    CAST(DATEPART(MS, GETDATE()) AS VARCHAR(3))

    SET @vSQL = 'SELECT ' + @pColumns + ', IDENTITY(INT, 1, 1) AS ROWID INTO ' + @vTempTable + ' FROM ' + @pTableName

    IF @pFilter != '' AND @pFilter IS NOT NULL
    SET @vSQL = @vSQL + ' WHERE ' + @pFilter

    IF @pSort != '' AND @pSort IS NOT NULL
    SET @vSQL = @vSQL + ' ORDER BY ' + @pSort

    EXECUTE (@vSQL)

    -- Get the total number of rows selected
    SET @vTotalRows = @@ROWCOUNT

    -- If page number = 0, set it to the first page
    IF @pPage = 0
    SET @pPage = 1

    -- If page number is beyond the last page, set page to the last page
    IF (@pPage * @pPageRows) > @vTotalRows
    BEGIN
    SET @pPage = @vTotalRows / @pPageRows
    IF (@vTotalRows % @pPageRows) != 0
    SET @pPage = @pPage + 1
    END

    SET @vRowStart = ((@pPage - 1) * @pPageRows) + 1
    SET @vSQL = 'SELECT * FROM ' + @vTempTable + ' WHERE ROWID BETWEEN ' + CAST(@vRowStart AS VARCHAR(10)) +
    ' AND ' + CAST((@vRowStart + @pPageRows - 1) AS VARCHAR(10)) + ' ORDER BY ROWID'
    EXECUTE (@vSQL)

    SET @vSQL = 'DROP TABLE ' + @vTempTable
    EXECUTE (@vSQL)

GO

إليك بعض الأمثلة على كيفية استخدام باستخدام قاعدة البيانات Northwing:

EXECUTE [dbo].[GetPage] 'Customers', '*', '', '', 1, 10
EXECUTE [dbo].[GetPage] 'Customers', '*', '', 'CustomerID DESC', 1, 10

لتأكيد، وهذا ليس عملي ولكن من باب المجاملة http://www.eggheadcafe.com/PrintSearchContent.asp؟LINKID=1055

وابتهاج، جون

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