ورود

View Full Version : مشکل در ذخیره و گزارش گیری رکوردها ی بیش از 700 هزار تا



mohammadgij
شنبه 25 مهر 1383, 08:59 صبح
سلام
من یه سیستمی دارم که توی اون سیستم یه کارتابل وجود داره. متاسفانه به علت طراحی نادرست طراح این برنامه الان دچار مشکل شدم.مشکل من اینه که من یه جدول Master با تعداد رکورد 110 هزار و یه جدول Detail با تعداد رکورد 700 هزار و یه جدول دیگه به نام تامین اعتبارها با تعداد رکورد 150 هزار دارم.از طرف دیگه یه جدول رابط هم دارم که به طور مثال برای هر رکورد Master بین 4-8 رکورد توی اون هست که مشخص کننده گردش هر رکورد برای Master هستش.جداول Master / detail / gardesh همه با یک فیلد به نام nvcExpNum با هم ارتباط دارند و جدول DETAIL هم با فیلدی به نام nvcBBCode .
من به تعداد رکوردهای جدول Master نیاز دارم. از طرفی میخوام بدونم که جمع مبالغ در Detail برای هر رکورد Master چقدر هست.از طرف دیگه در جدول گردش هم گردش این رکورد نباید تمام شده باشد و جمع مبالغ مربوط به nvcBBCode هم برام مهمه در یک کلام Stored Procedure من این قطعه زیر هستش :




ALTER Procedure dbo.H_COUNTSENDDOCUMENTSErsali_SP2
@USERCODE integer,
@OPTION tinyint

As
Declare @Logic as Bit
SET @Logic=0

IF (@OPTION>1)
BEGIN
SET @Logic=1
SET @OPTION=@OPTION-2
END
SELECT dbo.TRANSFERDOCUMENT_TABLE.CODE, dbo.TRANSFERDOCUMENT_TABLE.YEARD, dbo.TRANSFERDOCUMENT_TABLE.EXPNUM,
dbo.TRANSFERDOCUMENT_TABLE.EXPDATE, MAX(dbo.TRANSFERDOCUMENT_TABLE.USERPOSITION) AS MaxPosition,
dbo.DOCUMENT_TABLE.PAYDESCRIPTION, dbo.DOCUMENT_TABLE.RECNAME, MAX(dbo.TRANSFERDOCUMENT_TABLE.CONFIRMDATE)
AS CONFIRMDATE, MAX(dbo.TRANSFERDOCUMENT_TABLE.CONFIRMTIME) AS CONFIRMTIME, dbo.DOCUMENT_TABLE.EXPSYSTEM,
dbo.TRANSFERDOCUMENT_TABLE.CENTERCODE, dbo.DOCUMENT_TABLE.DOCUMENTTYPE, dbo.DOCUMENT_TABLE.DOCUMENTNUM,
dbo.TRANSFERDOCUMENT_TABLE.RECIEVEDATE, dbo.TRANSFERDOCUMENT_TABLE.RECIEVETIME,
dbo.TRANSFERDOCUMENT_TABLE.TRANSFERDATE, dbo.TRANSFERDOCUMENT_TABLE.TRANSFERTIME, MAX(MaxBBCode.HazineNo) AS HazineNo,
SumAmountBest.SumAmount, CaptionObj.ObjectCaption, dbo.DOCUMENT_TABLE.PROVIDERCODE1, dbo.DOCUMENT_TABLE.SUPERVISORCODE1,
dbo.DOCUMENT_TABLE.MASTERCODE1, dbo.DOCUMENT_TABLE.MANAGERCODE1, dbo.DOCUMENT_TABLE.PROVIDERCODE2,
dbo.DOCUMENT_TABLE.SUPERVISORCODE2, dbo.DOCUMENT_TABLE.MASTERCODE2, dbo.DOCUMENT_TABLE.MANAGERCODE2,
dbo.DOCUMENT_TABLE.UNITCODE, dbo.DOCUMENT_TABLE.ExpNumDasti
FROM dbo.TRANSFERDOCUMENT_TABLE INNER JOIN
dbo.DOCUMENT_TABLE ON dbo.DOCUMENT_TABLE.EXPNUM = dbo.TRANSFERDOCUMENT_TABLE.EXPNUM INNER JOIN
(SELECT TRANSFERDOCUMENT_TABLE.EXPNUM, MAX(TRANSFERDOCUMENT_TABLE.USERPOSITION) AS MINUSERPOSITION
FROM TRANSFERDOCUMENT_TABLE INNER JOIN
DOCUMENT_TABLE ON DOCUMENT_TABLE.EXPNUM = TRANSFERDOCUMENT_TABLE.EXPNUM
WHERE NOT (TRANSFERDOCUMENT_TABLE.CONFIRMDATE IS NULL) AND (DOCUMENT_TABLE.LOGICALDELETE = 0) AND
(TRANSFERDOCUMENT_TABLE.USERPOSITION < 0) AND (TRANSFERDOCUMENT_TABLE.bitMasterConfirmd = 1) AND
(dbo.fnAddDayPlus(TRANSFERDOCUMENT_TABLE.CONFIRMDA TE, 10) >= dbo.fnChangeToShamsiDate(Year(GetDate()),
Month(GetDate()), Day(GetDate())))
GROUP BY TRANSFERDOCUMENT_TABLE.EXPNUM) MINPOSITIONS ON
dbo.TRANSFERDOCUMENT_TABLE.EXPNUM = MINPOSITIONS.EXPNUM AND
dbo.TRANSFERDOCUMENT_TABLE.USERPOSITION - @OPTION = MINPOSITIONS.MINUSERPOSITION LEFT OUTER JOIN
(SELECT ExpNum, BBCode
FROM Sanad.dbo.DOCUMENTDETAIL_TABLE
WHERE NOT Sanad.dbo.DOCUMENTDETAIL_TABLE.BBCODE IS NULL
GROUP BY ExpNum, BBCode) DetBBCode ON dbo.DOCUMENT_TABLE.EXPNUM = DetBBCode.ExpNum LEFT OUTER JOIN
(SELECT BUDJET.dbo.B_BudjetBook_Table.BBCode, MAX(BUDJET.dbo.B_BudjetBook_Table.HazinehNo) AS HazineNo
FROM BUDJET.dbo.B_BudjetBook_Table
GROUP BY BUDJET.dbo.B_BudjetBook_Table.BBCode) MaxBBCode ON DetBBCode.BBCode = MaxBBCode.BBCode INNER JOIN
(SELECT ObjectId, ObjectCaption
FROM Security.dbo.ObjectTree_Table) CaptionObj ON dbo.DOCUMENT_TABLE.EXPSYSTEM = CaptionObj.ObjectId INNER JOIN
(SELECT Cast(SUM(AmountBest) AS Float) AS SumAmount, ExpNum
FROM Sanad.dbo.DocumentDetail_Table
GROUP BY EXPNUM) SumAmountBest ON dbo.DOCUMENT_TABLE.EXPNUM = SumAmountBest.ExpNum
WHERE (dbo.TRANSFERDOCUMENT_TABLE.USERCODE = @USERCODE) AND (dbo.TRANSFERDOCUMENT_TABLE.EXPNUM IN
(SELECT DISTINCT EXPNUM
FROM TRANSFERDOCUMENT_TABLE
WHERE USERPOSITION = 4 AND NOT (CONFIRMDATE IS NULL))) AND (NOT (dbo.TRANSFERDOCUMENT_TABLE.CONFIRMDATE IS NULL)) OR
(dbo.TRANSFERDOCUMENT_TABLE.USERCODE = @USERCODE) AND (dbo.TRANSFERDOCUMENT_TABLE.EXPNUM = MINPOSITIONS.EXPNUM) AND
(NOT (dbo.TRANSFERDOCUMENT_TABLE.CONFIRMDATE IS NULL)) AND (dbo.TRANSFERDOCUMENT_TABLE.EXPNUM IN
(SELECT DISTINCT EXPNUM
FROM TRANSFERDOCUMENT_TABLE
WHERE USERPOSITION = 4 AND NOT (CONFIRMDATE IS NULL))) AND (@OPTION = 1) AND
(dbo.TRANSFERDOCUMENT_TABLE.USERPOSITION - @OPTION = MINPOSITIONS.MINUSERPOSITION) OR
(dbo.TRANSFERDOCUMENT_TABLE.USERCODE = @USERCODE) AND (NOT (dbo.TRANSFERDOCUMENT_TABLE.EXPNUM IN
(SELECT EXPNUM
FROM TRANSFERDOCUMENT_TABLE
WHERE NOT (CONFIRMDATE IS NULL) AND UserPosition = - 7))) AND (dbo.TRANSFERDOCUMENT_TABLE.EXPNUM IN
(SELECT DISTINCT EXPNUM
FROM TRANSFERDOCUMENT_TABLE
WHERE USERPOSITION = 4 AND NOT (CONFIRMDATE IS NULL))) AND (@OPTION = 1) AND (dbo.DOCUMENT_TABLE.LOGICALDELETE = 0) AND
(dbo.TRANSFERDOCUMENT_TABLE.USERPOSITION = - 7)
GROUP BY dbo.TRANSFERDOCUMENT_TABLE.CODE, dbo.TRANSFERDOCUMENT_TABLE.YEARD, dbo.TRANSFERDOCUMENT_TABLE.EXPNUM,
dbo.TRANSFERDOCUMENT_TABLE.EXPDATE, dbo.DOCUMENT_TABLE.PAYDESCRIPTION, dbo.DOCUMENT_TABLE.RECNAME,
dbo.DOCUMENT_TABLE.EXPSYSTEM, dbo.TRANSFERDOCUMENT_TABLE.CENTERCODE, dbo.DOCUMENT_TABLE.DOCUMENTTYPE,
dbo.DOCUMENT_TABLE.DOCUMENTNUM, dbo.TRANSFERDOCUMENT_TABLE.RECIEVEDATE, dbo.TRANSFERDOCUMENT_TABLE.RECIEVETIME,
dbo.TRANSFERDOCUMENT_TABLE.TRANSFERDATE, dbo.TRANSFERDOCUMENT_TABLE.TRANSFERTIME, SumAmountBest.SumAmount,
CaptionObj.ObjectCaption, dbo.DOCUMENT_TABLE.PROVIDERCODE1, dbo.DOCUMENT_TABLE.SUPERVISORCODE1,
dbo.DOCUMENT_TABLE.MASTERCODE1, dbo.DOCUMENT_TABLE.MANAGERCODE1, dbo.DOCUMENT_TABLE.PROVIDERCODE2,
dbo.DOCUMENT_TABLE.SUPERVISORCODE2, dbo.DOCUMENT_TABLE.MASTERCODE2, dbo.DOCUMENT_TABLE.MANAGERCODE2,
dbo.DOCUMENT_TABLE.UNITCODE, dbo.DOCUMENT_TABLE.ExpNumDasti

Return




این پروسیجر وقتی که تعداد رکوردهای Detail کمتر از 100 هزار تا هست عالی جواب میده اما به محض اینکه بالاتر میره خطای (اگه اشتباه نکنم) Timout Expired میده. چه طور باید این مشکل رو حل کنم.


سوال دیگم هم اینه که آیا درسته که من اطلاعات تمام سال ها رو در این جداول نگه دارم یا باید یک جدول هیستوری درست کنم و فقط اطلاعات سال جاری توی این جداول باشه و برای گزارشات از یک View که بین این جداول Union زده استفاده کنم.
لطفا راهنماییم کنید

AminSobati
شنبه 25 مهر 1383, 19:06 عصر
دوست عزیزم،
زمانی که سرعت Query روی دیتابیس کاهش پیدا میکنه، تنها در صورتی میتونین سرعت رو بهتر کنین که اشکال کار در ایندکسهای نامناسب باشه، نه در افزایش حجم اطلاعات. اگر تمام ایندکسها به طور دقیق و صحیح ساخته شدن ولی حجم اطلاعات شما در یک SELECT به تعداد بالایی میرسه، نباید انتظار داشته باشید با همون امکانات سخت افزاری قبلی، نتیجه خوبی بدست بیارین.
اما از طرفی افزایش حجم اطلاعات اجتناب ناپذیره. پس تنها کاری که میشه کرد Partition کردن اطلاعات هست. کاری که در مورد View گفتین، صحیح ترین و اصولی ترین راه هستش. در Books Online، مبحثی با عنوان Partitioned View وجود داره که حتما مطالعه بفرمایید.
در شرکتهای زیادی با این مشکل مواجه بودم که انتظار داشتن یک Query با برگرداندن حدودا 200 هزار رکورد، در چند ثانیه جواب بده! این تنها با افزایش امکانات سخت افزاری مثل CPU، Memory و داشتن RAID امکان پذیره. تازه این در زمانی هستش که شما پشت سرور چنین Query رو انجام میدین. اگر Client شما در شبکه LAN وجود داره، زمانی چند برابر اجرای خود Query طول میکشه تا نتیجه از سرور به کلاینت برسه!
به همین دلیل اطلاعات هر سال رو باید آرشیو کرد. همین نیازها هست که باعث میشه علم دیتابیس به دو شاخه اصلی OLTP و OLAP تقسیم بشه. اصولا سروری که برای OLTP استفاده میشه دارای Live Data (اطلاعاتی که مرتبا تحت Update و Insert کاربرها قرار گرفتن) هستش و طراحی جداول و ایندکسها در اون متفاوته از OLAP (در بر گیرنده Archived Data).
موفق باشید،
امین ثباتی MCSD