PDA

View Full Version : پردازش 800 هزار دیتا در یک حلقه



MeSaeid
چهارشنبه 02 اردیبهشت 1394, 18:29 عصر
سلام
من می خوام توی حلقه FOR یاdo-while که من از دومی استفاده می کنم ( چون سرعتش بیشتره ) یه حجم بزرگی از اطلاعات رو بگیرم و توی دیتا بیس ذخیره کنم
خب مشکل اینجاس که بعد یه مدت متوقف میشه چون زمان زیادی طول میکشه
راه حلی وجود داره ؟ یا باید از جاوا واسه این کار استفاده کنم ( چون شنیدم که واسه چنین کارایی خوب عمل میکنه ) ؟ در ضمن از set_time_limit هم استفاده کردم

amin1softco
چهارشنبه 02 اردیبهشت 1394, 18:44 عصر
چیزی که در منوال اومده نباید متوقف بشه


<?php
// Ignore user aborts and allow the script
// to run forever
ignore_user_abort(true);
set_time_limit(0);

echo 'Testing connection handling in PHP';

// Run a pointless loop that sometime
// hopefully will make us click away from
// page or click the "Stop" button.
while(1)
{
// Did the connection fail?
if(connection_status() != CONNECTION_NORMAL)
{
break;
}

// Sleep for 10 seconds
sleep(10);
}

// If this is reached, then the 'break'
// was triggered from inside the while loop

// So here we can log, or perform any other tasks
// we need without actually being dependent on the
// browser.
?>

http://php.net/manual/en/function.ignore-user-abort.php
http://reviewsignal.com/blog/2013/08/22/long-running-processes-in-php/ (http://php.net/manual/en/function.ignore-user-abort.php)

-سیّد-
پنج شنبه 03 اردیبهشت 1394, 00:16 صبح
من می خوام توی حلقه FOR یاdo-while که من از دومی استفاده می کنم ( چون سرعتش بیشتره )

این حرفتون به هیچ وجه صحیح نیست. سرعت اجرای for با do-while و یا هر نوع حلقه‌ی دیگه (foreach، while، ...) فرقی با هم ندارن. در واقع فرقشون در حدی نیست که بشه در نظر گرفت (فرض کنید یکیشون از اون یکی 0.000000001 ثانیه سریع‌تر باشه!).
یعنی اجرای یه دستور ساده مثل echo دهها برابر بیشتر از دستورات حلقه زمان می‌بره. توجه کنید که رایانه داره این کارا رو انجام می‌ده، نه آدمیزاد!



خب مشکل اینجاس که بعد یه مدت متوقف میشه چون زمان زیادی طول میکشه

اگه جواب دوستمون مشکل شما رو حل نکرد، می‌تونید کدتون رو اینجا بذارید (نه حتماً کاملش رو، حداقل بخش مرتبطش رو)؟ یا می‌تونید توضیح بدید چه اتفاقی می‌افته که متوقف می‌شه؟ خطا می‌ده؟ چه خطایی؟



یا باید از جاوا واسه این کار استفاده کنم ( چون شنیدم که واسه چنین کارایی خوب عمل میکنه ) ؟
بستگی به این داره که چی کار می‌خواین بکنین. اجرای یه حلقه توی زبون‌ها مختلف تقریباً هیچ فرقی با هم نمی‌کنه. مهم اینه که می‌خواین توی اون حلقه چی کار کنین. خوب معمولاً انجام یه کار ساده توی جاوا سخت‌تر از PHP هست، و توی ++C از هر دوی اینها سخت‌تر! ولی یه کارای خاص‌تری رو با PHP شاید نتونید راحت انجام بدید.
یا بعضی وقت‌ها برای انجام یه کاری، یه کتابخونه‌ی خیلی خوب توی یه زبون هست که در نتیجه انجام اون کار توی اون زبون برای آدم خیلی راحت‌تر می‌شه.

و البته در نهایت این رو هم بگم که PHP در اصل به عنوان یک زبان اسکریپتی و برای اجرا روی وب سرور طراحی شده. درسته که می‌تونید desktop application هم باهاش بنویسید (من خودم نوشتم، GUI هم داشت)، ولی برای این کار طراحی نشده و در نتیجه یه جاهایی آدم دستش یه مقدار بسته می‌شه.

MeSaeid
پنج شنبه 03 اردیبهشت 1394, 22:09 عصر
این حرفتون به هیچ وجه صحیح نیست. سرعت اجرای for با do-while و یا هر نوع حلقه‌ی دیگه (foreach، while، ...) فرقی با هم ندارن. در واقع فرقشون در حدی نیست که بشه در نظر گرفت (فرض کنید یکیشون از اون یکی 0.000000001 ثانیه سریع‌تر باشه!).
یعنی اجرای یه دستور ساده مثل echo دهها برابر بیشتر از دستورات حلقه زمان می‌بره. توجه کنید که رایانه داره این کارا رو انجام می‌ده، نه آدمیزاد!

ممنون ازپاسختون ، من یجا خونده بودم که داشتن حلقه ها رو مقایسه می کردن و do-while حدود 3 ثانیه تفاوت داشت با اونا ( در یک شرایط مساوی ) .
من از این جهت گفتم زبون جاوا که مثلا سرعتش بیشتره خب همونطور که میدونید php از لحاظ سرعت مشکل داره و فیسبوک یک مثال خوب واسه اینه و مجبور شده از زبان C هم در کنارش استفاده کنه ...

مشکل بنده هم حل شد ممنون

-سیّد-
پنج شنبه 03 اردیبهشت 1394, 23:08 عصر
من یجا خونده بودم که داشتن حلقه ها رو مقایسه می کردن و do-while حدود 3 ثانیه تفاوت داشت با اونا ( در یک شرایط مساوی ) .
می‌تونید منبع بدید؟ چون این خیلی به نظرم منطقی نمیاد. مگر این که شرایط واقعاً یکسان نباشه، یا micro-benchmark باشه. اینجا در مورد این که چه سوء تفاهم‌هایی ممکنه با یه micro-benchmark به وجود بیاد توضیح داده:
http://www.ibm.com/developerworks/library/j-jtp02225



من از این جهت گفتم زبون جاوا که مثلا سرعتش بیشتره خب همونطور که میدونید php از لحاظ سرعت مشکل داره و فیسبوک یک مثال خوب واسه اینه و مجبور شده از زبان C هم در کنارش استفاده کنه ...

نه واقعیتش اینو نمی‌دونم که php از لحاظ سرعت مشکل داره! چون نداره! :)
ببینید بستگی داره چی کار می‌خواین بکنین. فیس‌بوک front-end اش رو با php نوشته (که البته بعداً زبان hack رو روی php درست کرده)، و back-end اش رو با جاوا و زبون‌های دیگه.
هر زبونی برای یه کاری ساخته شده و معمولاً کارش رو خوب انجام می‌ده. بنابراین به طور کلی نمی‌شه گفت php مشکل سرعت داره. بله اگه بخواین با php یه search engine بنویسین قطعاً به هزاران مشکل برخورد می‌کنین، که یکیش سرعت هست!

اتفاقاً فیس بوک یه مثال عالی هست برای این که نشون بدیم با php هم می‌شه کد با سرعت فوق‌العاده زد. البته باز تأکید می‌کنم: front-end با سرعت خوب! نه back-end!

مهرداد سیف زاده
جمعه 04 اردیبهشت 1394, 08:38 صبح
اگر به سرور دسترسی دارید پس این کار رو پشت صحنه با c انجام بدید. در واقع این چنین بزرگ رو باید پست صحنه بصورت یک اجرای daemon انجام بدید و همچنین چند تا تجربه:
۱- اگر حجم دیتا بزرگ هست و قراره چندین رکورد از یک جدول با جدول دیگه join زده بشه به دلیل دیتای بزرگ join زیاد طول میکشه و سیستم کله میخوابه(cpu یه 100%) برای حل این مشکل رکوردهای جدول اول رو بردارید و در یک حلقه for با رکوردهای جدول دیگه مقایسه کنید. در واقع join اگر دیتا تا زیر ۱۰۰۰ باشه خوب کار میکنه ولی بعدش بصرت تصاعدی ضعیف میشه
۲- اگر قرار رکوردهای این جدول کاری روش انجام بشه و بعدش توی جدول دیگه ذخیره بشه در حلقه for به ازای هر رکورد دستور insert ندید بلکه شما کاری که میخواید روی رکوردها انجام بدید و هر ۱۰۰ تا در میون دستور insert بدید. این کار ساده هست شما یک آرایه تعریف میکنید و بعدش با هر بار جلو رفتن حلقه for تعداد ۱۰۰ تا توی آریه میریزید و بعد از این که تعداد رکوردهای آرایه به ۱۰۰ تا رسید اون وقت دستور insert رو میدید. با این کار شما ۱۰۰ دستور insert رو تبدیل به یک دستور insert کردید.
۳- نوع engine هم مهمه چون اگر مرحله insert بیشتر از InnoDB و اگر مرحله select بیشتره از MyISAM در مورد این هم توی وب جستجو کنید.

MeSaeid
شنبه 05 اردیبهشت 1394, 22:27 عصر
اگر به سرور دسترسی دارید پس این کار رو پشت صحنه با c انجام بدید. در واقع این چنین بزرگ رو باید پست صحنه بصورت یک اجرای daemon انجام بدید و همچنین چند تا تجربه:
۱- اگر حجم دیتا بزرگ هست و قراره چندین رکورد از یک جدول با جدول دیگه join زده بشه به دلیل دیتای بزرگ join زیاد طول میکشه و سیستم کله میخوابه(cpu یه 100%) برای حل این مشکل رکوردهای جدول اول رو بردارید و در یک حلقه for با رکوردهای جدول دیگه مقایسه کنید. در واقع join اگر دیتا تا زیر ۱۰۰۰ باشه خوب کار میکنه ولی بعدش بصرت تصاعدی ضعیف میشه
۲- اگر قرار رکوردهای این جدول کاری روش انجام بشه و بعدش توی جدول دیگه ذخیره بشه در حلقه for به ازای هر رکورد دستور insert ندید بلکه شما کاری که میخواید روی رکوردها انجام بدید و هر ۱۰۰ تا در میون دستور insert بدید. این کار ساده هست شما یک آرایه تعریف میکنید و بعدش با هر بار جلو رفتن حلقه for تعداد ۱۰۰ تا توی آریه میریزید و بعد از این که تعداد رکوردهای آرایه به ۱۰۰ تا رسید اون وقت دستور insert رو میدید. با این کار شما ۱۰۰ دستور insert رو تبدیل به یک دستور insert کردید.
۳- نوع engine هم مهمه چون اگر مرحله insert بیشتر از InnoDB و اگر مرحله select بیشتره از MyISAM در مورد این هم توی وب جستجو کنید.
فرمایش شما دست ، ولی ما اگه 100 تا داده توی آرایه ریختیم و بعد خواستین اینسرت کنیم باید توی حلقه foreach قرار بدیمش که دیگه تفاوتی در تعداد اینسرت ها ایجاد نمیشه فقط دیر به دیر این کارو می کنیم

bagherok
شنبه 05 اردیبهشت 1394, 22:50 عصر
فرمایش شما دست ، ولی ما اگه 100 تا داده توی آرایه ریختیم و بعد خواستین اینسرت کنیم باید توی حلقه foreach قرار بدیمش که دیگه تفاوتی در تعداد اینسرت ها ایجاد نمیشه فقط دیر به دیر این کارو می کنیم
نه دیگه
دیگه چه نیازی به foreach هست
همون آرایه رو اینسرت میکنید.

-سیّد-
شنبه 05 اردیبهشت 1394, 23:39 عصر
با استفاده از Multi-row insert می‌تونید این کار رو انجام بدید:
https://en.wikipedia.org/wiki/Insert_%28SQL%29#Multirow_inserts
http://www.w3schools.com/PHP/php_mysql_insert_multiple.asp

در ضمن اگه نوع پردازشی که می‌خواین انجام بدین خیلی سنگین و خاص نباشه، نیازی نیست درگیر پیچیدگی کد زدن به زبان‌هایی مانند ++C بشید و با PHP می‌تونید کارتون رو راه بندازید.

MeSaeid
یک شنبه 06 اردیبهشت 1394, 00:39 صبح
بله حق با شماست

مهرداد سیف زاده
یک شنبه 06 اردیبهشت 1394, 08:20 صبح
بله دیگه لازم نیست روی آرایه foreach بزنید من معمولا طوری آرایه رو تنظیم میکنم که هر ۱۰۰تا در میون با implode اون رو وارد دیتابیس میکنم.