PDA

View Full Version : حرفه ای: php pagination - بار زیاد سرور



mn3250
چهارشنبه 02 دی 1388, 09:35 صبح
دوستان من اسکریپتی دارم که نتایج جستجو رو صفحه بندی میکنه. سئوالم اینه که آیا راهی وجود داره که لازم نباشه برای جابجایی بین صفحات تمام کوئری دوباره خونده بشه؟ چون با اینکه تعداد صفحات رو خیلی سریع پیدا میکنم اما برای پیمایش بین صفحات دوباره لازمه تمام دیتا خونده بشه تا به سطر مورد نظر برسیم.
اگر بهتر بخواهم توضیح بدم فرض کنید چند میلیون رکورد داریم و میخواهیم 30 تا 30 تا صفحه بندی کنیم. اگر رکورد یک میلیون تا یک میلیون و سی رو به صورت زیر بخوانم:
کوئری اول


$query = "SELECT count(*) FROM tbl1 WHERE time>'$searchis1' and time <'$searchis2'";

کوئری دوم


$query = "SELECT * FROM tbl1 WHERE time>'$searchis1' and time <'$searchis2' ORDER BY time limit 1000000,30";

متاسفانه PHP یا MYSQL تمام رکوردها تا یک میلیون و سی رو میخونه تا سی رکوردی که مورد نظره رو نمایش بده و این فشار زیادی به سرور وارد میکنه. اگر کسی دو کوئری با زمانهای مختلف بگیره (cache هم نداریم به این شکل) کلا سرور رو از کار می اندازه. در صورتیکه فقط 30 رکورد خونده میشه.
اگر دوستی راهنمایی کنه بسیار ممنون خواهم شد.

maysamscript
چهارشنبه 02 دی 1388, 09:59 صبح
کوئری دوم اینجوری باید باشه. شما دارید میگید 1000030 رکورد رو سلکت کنه!

$query = "SELECT * FROM tbl1 WHERE time>'$searchis1' and time <'$searchis2' ORDER BY time limit 1000000,30";

mn3250
چهارشنبه 02 دی 1388, 10:09 صبح
ممنون از پاسختون.
خطای تایپه ببخشید.
ناگفته نماند phpmyadmin هم با همین مشکل روبروست. البته پیام میده که این کوئری زمان زیادی خواهد برد. بنظرتون راهی میرسه؟

s_salavati2002
چهارشنبه 02 دی 1388, 10:39 صبح
دوستان من اسکریپتی دارم که نتایج جستجو رو صفحه بندی میکنه. سئوالم اینه که آیا راهی وجود داره که لازم نباشه برای جابجایی بین صفحات تمام کوئری دوباره خونده بشه؟ چون با اینکه تعداد صفحات رو خیلی سریع پیدا میکنم اما برای پیمایش بین صفحات دوباره لازمه تمام دیتا خونده بشه تا به سطر مورد نظر برسیم.
اگر بهتر بخواهم توضیح بدم فرض کنید صد میلیون رکورد داریم و میخواهیم 30 تا 30 تا صفحه بندی کنیم. اگر رکورد یک میلیون تا یک میلیون و سی رو به صورت زیر بخوانم:
کوئری اول


$query = "SELECT count(*) FROM tbl1 WHERE time>'$searchis1' and time <'$searchis2'";
کوئری دوم


$query = "SELECT * FROM tbl1 WHERE time>'$searchis1' and time <'$searchis2' ORDER BY time limit 1000000,30";
متاسفانه PHP یا MYSQL تمام رکوردها تا یک میلیون و سی رو میخونه تا سی رکوردی که مورد نظره رو نمایش بده و این فشار زیادی به سرور وارد میکنه. اگر کسی دو کوئری با زمانهای مختلف بگیره (cache هم نداریم به این شکل) کلا سرور رو از کار می اندازه. در صورتیکه فقط 30 رکورد خونده میشه.
اگر دوستی راهنمایی کنه بسیار ممنون خواهم شد.
اگر فیلد time ایندکس کنی نباید مشکلی پیش بیاد

mn3250
چهارشنبه 02 دی 1388, 10:58 صبح
ممنون.
صد البته ایندکس دارم.
مشکل با حجم بالای داده است. این دیتابیس چندین گیگابایت شده و بنظر میرسه mysql تمام دیتا رو میخونه و بعد 30 رکود مورد نظر رو نمایش میده.

maysamscript
چهارشنبه 02 دی 1388, 18:46 عصر
ببینید با این کوئری هم مشکل داره

SELECT count(*) FROM tbl1

maysamscript
چهارشنبه 02 دی 1388, 19:01 عصر
بنظر میرسه mysql تمام دیتا رو میخونه و بعد 30 رکود مورد نظر رو نمایش میده.
mysql چاره ای نداره که کل رکورد ها رو بخونه. چون شما دارید عمل مقایسه رو انجام میدید. برای این مقایسه از between هم میتونید استفاده کنید.

hidensoft
چهارشنبه 02 دی 1388, 19:49 عصر
شما باید حافظه خودتون رو مدیریت کنید تا از بروز مشکل و فشار زیاد روی سرور جلوگیری کنید.
در آینده مقاله ای رو در این رابطه ارائه خواهم داد. اما در حال حاضر به دلیل ناقص بودن اطلاعاتم از بیان آن عاجزم.

mn3250
چهارشنبه 02 دی 1388, 22:48 عصر
ممنون از همه دوستان.
between رو تست میکنم. متشکرم.
سرور در حد مطلوب بهینه سازی شده.
سرورم قاطی نداره. فرض نکردم. سی میلیون نه اما چند میلیون رکورد داره.
چندین گیگابایت دیتاست. خیلی هم کار بزرگی نیست. این مشکل واقعیست اما تستش هم کاری نداره.
کد هم همین دو کوئری هست و مقداری HTML برای نمایش.
بنظر میرسه phpmyadmin هم هنگام pagination به همین مشکل بر میخوره.

s_salavati2002
چهارشنبه 02 دی 1388, 23:46 عصر
between برات خیلی بهتر از limit کار میکنه
ولی به شرط اینکه وسطش خالی نداشته باشی

he3117
پنج شنبه 10 دی 1388, 17:21 عصر
می شه از چند تیبل هم استفاده کرد و مثلا در هر تیبل بیش از یک میلیون رکورد اضافه نکرد

he3117
پنج شنبه 10 دی 1388, 17:26 عصر
می شه از چند تیبل هم استفاده کرد و مثلا در هر تیبل بیش از یک میلیون رکورد اضافه نکرد

mn3250
یک شنبه 13 دی 1388, 13:00 عصر
ممنون از پاسختون.
اما یک میلیون هم همین مشکل رو داره مسئله اصلی اینه که mysql تمام رکوردها رو تا رکوردهای مورد نظر میخونه تا 30 رکورد رو برگردونه. با ده بیست کاربر همزمان کل سرور داون میشه.


پ ن - هنوز فرصت امتحان between دست نداده.

digitak
دوشنبه 14 دی 1388, 21:48 عصر
می تونی ID همه رکوردها رو بار اول که داری صفحه اول رو نشون بدی توی یه فایل text سیو کنی
توی صفحات دیگه ID ها رو بشموری و فرضا ID خط 10000 رو تا 30 تا بعدش بخونی و Query رو به این 30 تا محدود کنی !

یه کمی راه غیر عادی هست ولی جواب میده :لبخند:

narsic
سه شنبه 15 دی 1388, 10:04 صبح
می تونی ID همه رکوردها رو بار اول که داری صفحه اول رو نشون بدی توی یه فایل text سیو کنی
توی صفحات دیگه ID ها رو بشموری و فرضا ID خط 10000 رو تا 30 تا بعدش بخونی و Query رو به این 30 تا محدود کنی !

یه کمی راه غیر عادی هست ولی جواب میده :لبخند:
با سلام
این پیشنهاد هم میشه اما نه بایه فایل متنی بلکه به کمک یک بانک .
***فایل های متنی زمان بسیار زیادی برای نوشتن و خواندن میبرن .
و در پایان پیشنهاد من از چند دیتابیس بر روی چند سرور استفاده کنید (در صورتی که سرعت خیلی اهمیت داره ) . البته between هم پیشنهاد خوبی بود .
موفق باشید