PDA

View Full Version : سوال: کمک برای بهیه سازی حلقه ها



mamali-mohammad
چهارشنبه 17 اردیبهشت 1393, 23:42 عصر
سلام
این کد من هست :

$text = '12-name-y-86';$array = explode('-',$text);foreach($array as $value) { $sql = mysql_query("SELECT * FROM `table` WHERE `name`='$value' ORDER BY `id` LIMIT 3"); echo '***'.$value.'***'; echo '<br />'; while($row = mysql_fetch_array($sql)) { echo $row['title']; echo '<br />'; } echo '<br /><br />';}
در حالت کلی درسته و خروجی زیر رو میده :
12
title1
title2
title3


name
ti1
ti2
ti3


y
tle1
tle2
tle3


86
mytitle1
mytitle2
mytitle3

حالا اگه تعداد مقادیرمون زیاد باشه فشار به سرور میاد
چطوری میشه این کد رو بهینه تر کرد ؟

MMSHFE
پنج شنبه 18 اردیبهشت 1393, 10:15 صبح
این کد رو تست کنید:

$text = '12-name-y-86';
$in = '\'' . str_replace('-', '\',\'', $text) . '\'';
$sql = mysql_query("
SELECT `name`, SUBSTRING_INDEX(GROUP_CONCAT(DISTINCT `title` SEPARATOR ','), ',', 3) AS `titles`
FROM `groups`
WHERE (`name` IN ({$in}))
GROUP BY `name`
");
if($sql) {
while($row = mysql_fetch_assoc($sql)) {
echo '<p><strong>***' . $row['name'].'***</strong></p>' . PHP_EOL;
$titles = explode(',', $row['titles']);
foreach($titles as $title) {
echo '<p>' . $title . '</p>' . PHP_EOL;
}
}
mysql_free_result($sql);
}
دقت کنید که استفاده از mysql_fetch_array به تنهایی خودش سربار اضافه ایجاد میکنه. ضمن اینکه یکسری کارها رو بهتره با توابع داخلی MySQL انجام بدین.

mamali-mohammad
پنج شنبه 18 اردیبهشت 1393, 11:54 صبح
ممنون
اما این کد جواب نداد
کلا $sql نمیده و به داخل دستور if نمیره

MMSHFE
پنج شنبه 18 اردیبهشت 1393, 11:56 صبح
کد رو اصلاح کردم. دوباره استفاده کنید. اینجور وقتها یک mysql_error بگیرین ببینید خطا کجاست.

mamali-mohammad
پنج شنبه 18 اردیبهشت 1393, 11:57 صبح
این خطا رو میده :
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near

MMSHFE
پنج شنبه 18 اردیبهشت 1393, 12:46 عصر
پست قبل از خودتون رو بخونید.

mamali-mohammad
پنج شنبه 18 اردیبهشت 1393, 13:12 عصر
ممنون حل شد
فقط این کد سه تای اول رو میده
من باید سه تای آخر رو بگیرم
جسارتا یه توضیح کلی در مورد این کد میدید ؟
و یه سوال دیگه
من تست کردم سرعت کد شما کمتر از کد من هست
اما برای من فشار به سرور مهم هست
کد شما فشاری که به سرور وارد میکنه خیلی کمتره ؟
ممنون

engmmrj
پنج شنبه 18 اردیبهشت 1393, 15:17 عصر
SUBSTRING_INDEX(GROUP_CONCAT(DISTINCT `title` SEPARATOR ','), ',', 3)
این کد ها چیکار می کنن ؟:گیج:

shpegah
پنج شنبه 18 اردیبهشت 1393, 19:47 عصر
$text = '12-name-y-86';
$in = '\'' . str_replace('-', '\',\'', $text) . '\'';
$sql = mysql_query("
SELECT `name`, `title` FROM `table`
WHERE (`name` IN ({$in})) order by `name`,`id`Desc
");
if($sql) {
$nam='';$i=0;
while($row = mysql_fetch_assoc($sql)) {
if($nam<>$row['name'])
{
$i=0;
echo '<p><strong>***' . $row['name'].'***</strong></p>' . PHP_EOL;
}
if($i<3)
{
$i++;
echo '<p>' . $row['title'] . '</p>' . PHP_EOL;
}
$nam=$row['name'];
}
mysql_free_result($sql);
}


نظرتون نسبت به این کد چیه ؟
البته قسمت اعظمش کد آقای مهندس شهرکی هست

mamali-mohammad
پنج شنبه 18 اردیبهشت 1393, 20:38 عصر
این کد شما همه دیبتایس رو میکشه بیرون
ما فقط سه تای اخر رو میخوایم از هر مقدار

shpegah
پنج شنبه 18 اردیبهشت 1393, 22:28 عصر
بله ببخشید متوجه سه تای آخر نشده بودم درستش کردم ولی کد خوبی نشد اما بازم فکر کنم سرعتش بیشتر باشه چون یک حلقه کمتر داره

mamali-mohammad
پنج شنبه 18 اردیبهشت 1393, 22:39 عصر
ممنون دوست عزیز
توجه کنید ما فقط اطلاعاتی رو میخوایم بکشیم بیرون که در متغیر $text موجوده

shpegah
جمعه 19 اردیبهشت 1393, 07:15 صبح
کلا تغییرش دادم فکر کنم این بهینه ترین حالت باشه
من فکر میکنم کد شما وکد آقای شهرکی سه تای اولو میده نه آخر ولی این کد سه تای آخرو میده اگر سه تای اول را میخواهید Desc را حذف کنید

MMSHFE
جمعه 19 اردیبهشت 1393, 11:09 صبح
ممنون حل شد
فقط این کد سه تای اول رو میده
من باید سه تای آخر رو بگیرم
جسارتا یه توضیح کلی در مورد این کد میدید ؟
و یه سوال دیگه
من تست کردم سرعت کد شما کمتر از کد من هست
اما برای من فشار به سرور مهم هست
کد شما فشاری که به سرور وارد میکنه خیلی کمتره ؟
ممنون
شما باید بین فشار به سرور و سرعت یک حد تعادل ایجاد کنید. این کد کندتره چون SubQuery داره ولی همه اطلاعات یکجا توسط MySQL استخراج میشه و اگه جدول به شکل صحیح index گذاشته شده باشه، هم سرعتتون بالا میره و هم فشار به سرور کمتر میشه. در کل عدم استفاده از SubQuery سرعت رو در مقادیر کم بیشتر میکنه ولی در مقادیر زیاد نه. فرض کنید بخواین titleهای 50 تا name رو بدست بیارین. اونوقت باید 51 کوئری بفرستین.


SUBSTRING_INDEX(GROUP_CONCAT(DISTINCT `title` SEPARATOR ','), ',', 3)
این کد ها چیکار می کنن ؟:گیج:
این کد اول میاد بجای اینکه برای هر زوج name و title، یک رکورد استخراج کنه، همه اونها رو بصورت یک رکورد برمیگردونه که titleها با کاما به هم چسبیدن. بعد میاد تا زمان رسیدن به سومین کاما رو برمیگردونه (بجای LIMIT 3)
علت اینکه از این روش استفاده کردم اینه که MySQL از Limit روی Group By پشتیبانی نمیکنه (مثلاً نمیتونیم بگیم توی هر دسته 3 تا برگردونه).
اگه با دستورات MySQL و کلاً DBMS مورد استفاده به اندازه کافی آشنایی پیدا کنیم، دیگه لازم نیست خودمون روش اختراع کنیم چون معمولاً برای خیلی از کارها راهکار داخلی داره (که ما بی خبریم).

mamali-mohammad
جمعه 19 اردیبهشت 1393, 12:01 عصر
ممنون
پس اگه قرار باشه 100 تا مقدار رو برگردونیم کد شما خیلی فشار رو کمتر می کنه
فقط اگه بخوایم سه تای آخر رو بگیریم باید چیکار کنیم ؟ ( کد شما سه تای اول رو میگیره )

mamali-mohammad
جمعه 19 اردیبهشت 1393, 12:09 عصر
کلا تغییرش دادم فکر کنم این بهینه ترین حالت باشه
من فکر میکنم کد شما وکد آقای شهرکی سه تای اولو میده نه آخر ولی این کد سه تای آخرو میده اگر سه تای اول را میخواهید Desc را حذف کنید
ممنون کد شما درست هست
فقط الان بین مد شما و آقای شهریاری موندم
چون فشار به سرور خیلی برام اهمیت داره

MMSHFE
جمعه 19 اردیبهشت 1393, 12:27 عصر
ممنون
پس اگه قرار باشه 100 تا مقدار رو برگردونیم کد شما خیلی فشار رو کمتر می کنه
فقط اگه بخوایم سه تای آخر رو بگیریم باید چیکار کنیم ؟ ( کد شما سه تای اول رو میگیره )
میتونید توی GROUP_CONCAT قبل از SEPARATOR از ORDER BY استفاده کنید. ضمناً بنده شهرکی هستم. درمورد فشار به سرور با ab چک کردم کدی که من گذاشتم مصرف CPU و RAM کمتری داشت ولی سرعتش یکم کمتر بود.

mamali-mohammad
جمعه 19 اردیبهشت 1393, 12:47 عصر
ممنون
اینو زدم جواب نداد :

SUBSTRING_INDEX(GROUP_CONCAT(DISTINCT `name` ORDER BY `id` DESC SEPARATOR ','), ',', 3)

ببخشید ab چی هست ؟
روی لوکال میشه ازش استفاده کرد ؟

MRmoon
جمعه 19 اردیبهشت 1393, 14:08 عصر
ab یک فایل از فایل های آپاچی هست که میتونین تو دپوشه ی آپاچی پیداش کنید. به این صورته که شما آدرس یک صفحه رو میدید و اون یکسری اطلاعات رو براتون لیست می کنه.

نمونه استفاده
http://docs.phalconphp.com/en/latest/reference/benchmark/hello-world.html#yii-yii-debug-false-version-yii-1-1-13

mamali-mohammad
جمعه 19 اردیبهشت 1393, 14:50 عصر
ممنون
من easy php دارم ، دقیقا چطوری میشه استفاده کرد ؟

MRmoon
جمعه 19 اردیبهشت 1393, 21:38 عصر
تو پوشه ی آپاچی فایل ab.exe رو پیدا کنید و آدرسش بذارید تا راهنمایی کنم.

mamali-mohammad
جمعه 19 اردیبهشت 1393, 22:00 عصر
این مسیر ثبت شده : EasyPHP-5.3.3\apache\bin
با این کد تونستم تست کنم :
C:\Program\EasyPHP\apache\bin>ab -n 1 http://localhost/test/
اما php process دقیقا کدوم میشه ؟

shpegah
شنبه 20 اردیبهشت 1393, 07:28 صبح
میتونید توی GROUP_CONCAT قبل از SEPARATOR از ORDER BY استفاده کنید. ضمناً بنده شهرکی هستم. درمورد فشار به سرور با ab چک کردم کدی که من گذاشتم مصرف CPU و RAM کمتری داشت ولی سرعتش یکم کمتر بود.
به نظر عجیب نیست ؟البته مصرف RAM مسلما توی کدی که من گذاشتم زیادتره ولی مصرف cpu چون پیچیدگی کد شما بیشتره باید بالاتر باشه درکد شمابرای گروپ کردن وکانتکت کردن به کل رکوردها نیاز داره
اما تنها مصرف کد من همون order by هست ! لطفا شما موقع مقایسه قسمت order by id desc را از کد من حذف کنید تا دو تا کد از نظر منطق یکی شوند
اوردری که برای فیلد name مصرف میشه در درون گروپ کد شما هم نهفته است میمونه تعداد دور های حلقه که البته چون تعداد رکورد های من بیشتره مسلما cpu بیشتری مصرف میکنه ولی در کل بازهم نباید مصرف cpu من بیشتر باشه (سمت راست کد مهندس - سمت چپ کدی که نوشتم )

118831

فشار به سرور کدوم آیتمه ؟
processing همون تعداد محاسبات cpu منظوره ؟

mamali-mohammad
یک شنبه 21 اردیبهشت 1393, 10:36 صبح
سلام
آقای شهرکی عزیز یه کمک کنید ممنون میشم

MMSHFE
یک شنبه 21 اردیبهشت 1393, 12:25 عصر
من با این کد جواب گرفتم:

$text = '12-name-y-86';
$in = '\'' . str_replace('-', '\',\'', $text) . '\'';
$sql = mysql_query("
SELECT `name`, SUBSTRING_INDEX(GROUP_CONCAT(DISTINCT `title` ORDER BY `id` DESC SEPARATOR ','), ',', 3) AS `titles`
FROM `groups`
WHERE (`name` IN ({$in}))
GROUP BY `name`
");
if($sql) {
while($row = mysql_fetch_assoc($sql)) {
echo '<p><strong>***' . $row['name'].'***</strong></p>' . PHP_EOL;
$titles = explode(',', $row['titles']);
foreach($titles as $title) {
echo '<p>' . $title . '</p>' . PHP_EOL;
}
}
mysql_free_result($sql);
}

MMSHFE
یک شنبه 21 اردیبهشت 1393, 12:39 عصر
به نظر عجیب نیست ؟البته مصرف RAM مسلما توی کدی که من گذاشتم زیادتره ولی مصرف cpu چون پیچیدگی کد شما بیشتره باید بالاتر باشه درکد شمابرای گروپ کردن وکانتکت کردن به کل رکوردها نیاز داره
اما تنها مصرف کد من همون order by هست ! لطفا شما موقع مقایسه قسمت order by id desc را از کد من حذف کنید تا دو تا کد از نظر منطق یکی شوند
اوردری که برای فیلد name مصرف میشه در درون گروپ کد شما هم نهفته است میمونه تعداد دور های حلقه که البته چون تعداد رکورد های من بیشتره مسلما cpu بیشتری مصرف میکنه ولی در کل بازهم نباید مصرف cpu من بیشتر باشه (سمت راست کد مهندس - سمت چپ کدی که نوشتم )
فشار به سرور کدوم آیتمه ؟
processing همون تعداد محاسبات cpu منظوره ؟

Processing مدت زمانی هست که پردازش اسکریپت طول کشیده. ستونها هم به ترتیب مینیمم، میناگین، انحراف معیار مثبت یا منفی، میانه و ماکزیمم هستن.
البته یک مسئله دیگه هم هست توی بحث فشار به سرور که توی ab و Siege و... دیده نمیشه و باید با htop و امثال اون (توی لینوکس) و توی پردازشهای بالا رصد بشه و اونهم اینه که توی مدت زمانی که CPU درگیر بوده، چقدر از توانش مورد استفاده قرار گرفته. برای مثال، یک برنامه ممکنه 10 ساعت فقط دو تا عدد رو جمع بزنه ولی یک برنامه دیگه 10 دقیقه انتگرال نامعین تا رده 9 رو محاسبه کنه. در اینجا فشار برنامه دوم به سرور بیشتره چون توی اون 10 دقیقه تمام هسته های پردازنده رو درگیر کرده درحالی که در برنامه اول، سایر هسته های پردازنده برای جواب دادن به سایر کاربران آزاد بودن. با درنظر گرفتن این موارد که چک کردم و اینکه تمام فشار پردازشی ما در برنامه، کار با رشته هاست، گفتم که کد من فشار کمتری به سرور وارد میکنه. باز هم تأکید میکنم فشار به سرور به معنای زمان بیشتر اجرای کد نیست. مصرف رم هم عامل مهمی میتونه باشه (بخصوص توی تعداد رکوردهای زیاد). ازطرف دیگه یکسری پارامترهای دیگه هم در بهینگی مطرحه. برای مثال، اگه توی PHP با split متن رو تبدیل به آرایه میکردین و با یک شرط ساده name=$name بجای name in $in کارها انجام میشد (in خودش حلقه ایجاد میکنه و عملاً برنامه ها الآن حلقه تودرتو دارن). علت اینکه من از in استفاده کردم هم این بود که گفتن میخوان بار پردازشی سرور کم بشه و قطعاً در جریان هستین که وقتی یکسری محاسبات رو به MySQL بسپریم، مفسر PHP سرش خلوت میشه و میتونه به درخواست یکی دیگه که لزوماً ربطی به MySQL هم نداره، جواب بده. درهرحال بهینگی اسکریپت به پارامترهای زیادی بستگی داره و همونطور که گفتم، فقط زمان اجرا نباید مهم باشه (این هم بستگی به نیاز داره و ممکنه توی یک سایت، سرعت پاسخ مهمتر از فشار به سرور باشه).

mamali-mohammad
یک شنبه 21 اردیبهشت 1393, 16:05 عصر
خیلی لطف کردید
حالا من یه سوال دیگه کنم
اگه یه حلقه داشته باشیم و 100 تا دور بزنه و در هر دور یک بار به mysql جهت دریافت اطلاعات متصل بشه آیا فشار زیادی وارد میکنه ؟ ( کد خودم در پست اول )
جسارتا این کدتون title هارو بر نمیگردونه
ممنون بابت راهنماییتون

MMSHFE
دوشنبه 22 اردیبهشت 1393, 09:27 صبح
MySQL خودش مدیریت سشن داره و صدبار هم که بهش وصل بشین، اگه اتصال قبلی جوابگو باشه، همون رو برمیگردونه و اتصال جدید نمیسازه مگه اینکه خودتون با پارامتر چهارم دستور اتصال در PHP بهش بگین که اتصال جدید نیاز دارین. درمورد کد هم من تست کردم. بدون مشکل بود و title رو هم برمیگردوند. درصورت لزوم توی پیام خصوصی تیم ویور بدین که مشکل رو رفع کنم.

mamali-mohammad
دوشنبه 22 اردیبهشت 1393, 12:25 عصر
خب طبق کد اول من ، آیا مدیریت سشن رعایت میشه ؟

MMSHFE
دوشنبه 22 اردیبهشت 1393, 14:58 عصر
ربطی به کد نداره. همیشه رعایت میکنه. تنها چیزی که باعث میشه حتماً اتصال جدید ایجاد بشه اینه که موقع استفاده از mysql_connect پارامتر چهارم رو هم با مقدار true تعریف کنید.

mamali-mohammad
دوشنبه 22 اردیبهشت 1393, 15:00 عصر
ممنون
یعنی شما میگید کد اولی خودم با کد شما تاثیری در process php نداره ؟

MMSHFE
دوشنبه 22 اردیبهشت 1393, 15:09 عصر
مدیریت سشن چه ربطی به کدنویسی بهینه داره؟ مدیریت سشن MySQL فقط مربوطه به اتصالهای برقرار شده میشه نه کوئریهایی که میفرستیم.

mamali-mohammad
دوشنبه 22 اردیبهشت 1393, 15:10 عصر
من همون کوئری مد نظرمه !
در ابتدای برنامه یک با متصل شدیم
مشکل اصلی و اساسی من هیمن کوئری های زیادی هست که ارسال میشه

MMSHFE
دوشنبه 22 اردیبهشت 1393, 15:14 عصر
کوئری فرستادنهای زیاد خیلی هم خوب نیست ولی بهرحال وقتی میشه با یکبار کوئری فرستادن، همه نتایج دلخواه رو استخراج کرد، دلیلی نداره مدام کوئری بفرستیم. ضمناً ارسال کوئری با اتصال فرق داره.

mamali-mohammad
دوشنبه 22 اردیبهشت 1393, 16:58 عصر
ممنون جناب شهرکی
خیلی لطف کردید
جایی هم دیدم mysql_fetch_array رو به assoc تغییر دادید
دلیل خاصی داره ؟
این گزینه mysql_free_result کارش دقیقا چی هست ؟
ممنون
ببخشید خیلی سوال می کنم

MMSHFE
دوشنبه 22 اردیبهشت 1393, 17:47 عصر
mysql_fetch_array مصرف حافظه اش دوبرابر بقیه است. mysql_free_result هم حافظه اختصاص داده شده به خروجی mysql_query رو آزاد میکنه.

mamali-mohammad
پنج شنبه 25 اردیبهشت 1393, 15:22 عصر
ممنون
لطف کردید