استخدام T-SQL AVG أو أخذ المتوسط بعد إرجاع النتائج باستخدام LINQ
-
20-09-2019 - |
سؤال
لدي إجراء مخزن يستخدم طريقة عرض لسحب 6 متوسطات.قاعدة بيانات SQL هي SQL Server 2000.عندما أقوم بتشغيله في محلل الاستعلام، يستغرق الأمر حوالي 9 ثوانٍ.ما الذي يمكنني فعله للحصول على أداء أفضل؟هل يجب علي إرجاع الصفوف باستخدام LINQ وتحديد المتوسط بهذه الطريقة؟هل سيكون أسرع؟
فيما يلي مثال على sproc الحالي الخاص بي:
create procedure [TestAvg]
(
@CustomerNumber int
)
as
select
(select AVG(OrderTime) from OrderDetails where ProductID = 12 and DateDiff(day, DateFulfilled, GetDate()) <= 7 and CustomerNumber = @CustomerNumber) as P12D7,
(select AVG(OrderTime) from OrderDetails where ProductID = 12 and DateDiff(day, DateFulfilled, GetDate()) <= 30 and CustomerNumber = @CustomerNumber) as P12D30,
(select AVG(OrderTime) from OrderDetails where ProductID = 12 and DateDiff(day, DateFulfilled, GetDate()) <= 90 and CustomerNumber = @CustomerNumber) as P12D90,
(select AVG(OrderTime) from OrderDetails where ProductID = 16 and DateDiff(day, DateFulfilled, GetDate()) <= 7 and CustomerNumber = @CustomerNumber) as P16D7,
(select AVG(OrderTime) from OrderDetails where ProductID = 16 and DateDiff(day, DateFulfilled, GetDate()) <= 30 and CustomerNumber = @CustomerNumber) as P16D30,
(select AVG(OrderTime) from OrderDetails where ProductID = 16 and DateDiff(day, DateFulfilled, GetDate()) <= 90 and CustomerNumber = @CustomerNumber) as P16D90
واسمحوا لي أيضًا أن أوضح وجهة النظر المذكورة أعلاه.نظرًا لأن هذا هو SQL Server 2000، فلا يمكنني استخدام طريقة عرض مفهرسة لأنها تستخدم استعلامًا فرعيًا.أفترض أنه يمكن إعادة كتابة هذا لاستخدام الصلات.ومع ذلك، في المرة الأخيرة التي أخذنا فيها استعلامًا وأعدنا كتابته لاستخدام الصلات، كانت البيانات مفقودة (لأن الاستعلام الفرعي يمكن أن يُرجع قيمة فارغة تؤدي إلى حذف الصف بأكمله).
المحلول
أود أن أوصي بإدخال البيانات في جدول var أولاً، وربما جدولين vars، و1 لـ 12 و1 لـ 16 ProductID.من هذه الجداول، احسب المتوسطات كما هو مطلوب، ثم ارجع إلى tose من sp.
DECLARE @OrderDetails12 TABLE(
DateFulfilled DATETIME,
OrderTime FLOAT
)
INSERT INTO @OrderDetails12
SELECT DateFulfilled,
OrderTime
FROM OrderDetails
WHERE ProductID = 12
AND DateDiff(day, DateFulfilled, GetDate()) <= 90
and CustomerNumber = @CustomerNumber
DECLARE @OrderDetails16 TABLE(
DateFulfilled DATETIME,
OrderTime FLOAT
)
INSERT INTO @OrderDetails16
SELECT DateFulfilled,
OrderTime
FROM OrderDetails
WHERE ProductID = 16
AND DateDiff(day, DateFulfilled, GetDate()) <= 90
and CustomerNumber = @CustomerNumber
كما أن إنشاء الفهارس الصحيحة على الجدول سيساعد كثيرًا.
نصائح أخرى
ما هي كمية البيانات التي تغادر خادم قاعدة البيانات إذا كانت غير مجمعة، وما هي المدة اللازمة للقيام بهذه العملية؟سيوجه الاختلاف في حجم البيانات ما إذا كان وقت الحساب على الخادم يفوق وقت النقل والحساب المحلي.
أيضا - انظر إلى ذلك DATEDIFF
الاستخدام وتغييره ليكون أسهل لجعله قابلاً للتحسين (جرب DateFullfilled >= SomeCalculatedDate1 بدلاً من DATEDIFF
) - راجع خطة التنفيذ الخاصة بك للتأكد من أنها قادرة على استخدام بحث الفهرس (الأفضل) أو فحص الفهرس (جيد) بدلاً من table_scan.
تأكد أيضًا من وجود فهرس على CustomerNumber، ProduceID، DateFulfilled.