$bean-save() is taking way too long per record in Sugarcrm





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















I am having a function that recalculates the value of calculated fields in given modules.
This works fine for small modules with small number of records.
However When I try this on bigger modules like Contacts or Accounts, saving each record take up to three seconds.



With more than 100,000 records this takes 83 Hours to process.



This is my code.



$moduleList = array("Accounts", "Quotes"); 

if (!defined('sugarEntry') || !sugarEntry)
die('Not A Valid Entry Point');

require_once('include/utils.php');
require_once('include/export_utils.php');
foreach( $moduleList as $module) {
print "Updating $module...n<br>";
$cnt = 0;
$moduleBean = BeanFactory::getBean($module);
$beanList = $moduleBean->get_full_list($order_by,$where);
if( $beanList != null ) {
foreach($beanList as $b) {
// These lines prevent the modified date and user from being changed.
$b->update_date_modified = false;
$b->update_modified_by = false;
$b->tracker_visibility = false;
$b->in_workflow = true;
$b->save();
$cnt++;
}
}
print "Finished updating: $cnt records.n<br>";


When I log the time each record takes it is then clear that $b->save(); is what takes too long.



Is there any way to speed this up ?










share|improve this question





























    1















    I am having a function that recalculates the value of calculated fields in given modules.
    This works fine for small modules with small number of records.
    However When I try this on bigger modules like Contacts or Accounts, saving each record take up to three seconds.



    With more than 100,000 records this takes 83 Hours to process.



    This is my code.



    $moduleList = array("Accounts", "Quotes"); 

    if (!defined('sugarEntry') || !sugarEntry)
    die('Not A Valid Entry Point');

    require_once('include/utils.php');
    require_once('include/export_utils.php');
    foreach( $moduleList as $module) {
    print "Updating $module...n<br>";
    $cnt = 0;
    $moduleBean = BeanFactory::getBean($module);
    $beanList = $moduleBean->get_full_list($order_by,$where);
    if( $beanList != null ) {
    foreach($beanList as $b) {
    // These lines prevent the modified date and user from being changed.
    $b->update_date_modified = false;
    $b->update_modified_by = false;
    $b->tracker_visibility = false;
    $b->in_workflow = true;
    $b->save();
    $cnt++;
    }
    }
    print "Finished updating: $cnt records.n<br>";


    When I log the time each record takes it is then clear that $b->save(); is what takes too long.



    Is there any way to speed this up ?










    share|improve this question

























      1












      1








      1


      1






      I am having a function that recalculates the value of calculated fields in given modules.
      This works fine for small modules with small number of records.
      However When I try this on bigger modules like Contacts or Accounts, saving each record take up to three seconds.



      With more than 100,000 records this takes 83 Hours to process.



      This is my code.



      $moduleList = array("Accounts", "Quotes"); 

      if (!defined('sugarEntry') || !sugarEntry)
      die('Not A Valid Entry Point');

      require_once('include/utils.php');
      require_once('include/export_utils.php');
      foreach( $moduleList as $module) {
      print "Updating $module...n<br>";
      $cnt = 0;
      $moduleBean = BeanFactory::getBean($module);
      $beanList = $moduleBean->get_full_list($order_by,$where);
      if( $beanList != null ) {
      foreach($beanList as $b) {
      // These lines prevent the modified date and user from being changed.
      $b->update_date_modified = false;
      $b->update_modified_by = false;
      $b->tracker_visibility = false;
      $b->in_workflow = true;
      $b->save();
      $cnt++;
      }
      }
      print "Finished updating: $cnt records.n<br>";


      When I log the time each record takes it is then clear that $b->save(); is what takes too long.



      Is there any way to speed this up ?










      share|improve this question














      I am having a function that recalculates the value of calculated fields in given modules.
      This works fine for small modules with small number of records.
      However When I try this on bigger modules like Contacts or Accounts, saving each record take up to three seconds.



      With more than 100,000 records this takes 83 Hours to process.



      This is my code.



      $moduleList = array("Accounts", "Quotes"); 

      if (!defined('sugarEntry') || !sugarEntry)
      die('Not A Valid Entry Point');

      require_once('include/utils.php');
      require_once('include/export_utils.php');
      foreach( $moduleList as $module) {
      print "Updating $module...n<br>";
      $cnt = 0;
      $moduleBean = BeanFactory::getBean($module);
      $beanList = $moduleBean->get_full_list($order_by,$where);
      if( $beanList != null ) {
      foreach($beanList as $b) {
      // These lines prevent the modified date and user from being changed.
      $b->update_date_modified = false;
      $b->update_modified_by = false;
      $b->tracker_visibility = false;
      $b->in_workflow = true;
      $b->save();
      $cnt++;
      }
      }
      print "Finished updating: $cnt records.n<br>";


      When I log the time each record takes it is then clear that $b->save(); is what takes too long.



      Is there any way to speed this up ?







      php sugarcrm






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 16 '18 at 19:37









      HamzaouiiiHamzaouiii

      1587




      1587
























          1 Answer
          1






          active

          oldest

          votes


















          2














          First of all I'd recommend finding out what part of the save takes so long, using the tool of your choice... profiler/debugger/custom Timers/etc.




          • Is it a hook? Optimize it or make a custom flag to skip it if not needed for the recalc.

          • Is it a query? Analyse the queries (EXPLAIN) to find out if adding indices to your database could help.

          • Is it excessive log output? Reduce it.

          • Is it the bean loading for related bean calculation? Optimize formulas or skip if not needed.


          Other things you could try:




          • Prefilter which beans you want to resave using a Query (e.g. maybe record recalc not necessary if in certain state or modified after a certain related bean etc?).

          • Trigger updating calculated fields in your code and check if (relevant) values of the bean where actually changed after, if not then there's no need to resave it and you can skip to the next record instead.

          • If this is just about updating non-related calculated fields even although related calculated fields exist, then you could decide to (temporarily?) set $sugar_config['disable_related_calc_fields'] to true. That way Sugar wouldn't have to load those related beans.


          If there is no hope left:




          • Consider running those tasks in parallel

          • Rewrite whatever you need to update using SQL/SugarQuery (may not be possible, depending on complexity and implications).


          Notes:




          • Be aware that get_full_list() is deprecated since at least Sugar 7.7 and replaced by SugarQuery and $bean->fetchFromQuery(). However I'd recommend using a Query to only retrieve the IDs and use BeanFactory::retrieveBean($module, $id) to load the beans, possibly dismissing them each after computation, using BeanFactory::unregisterBean($bean); unset($bean); to help the garbage collector with keeping a low memory profile.
            Also I did use get_full_list() and fetchFromQuery in the past with catastrophic side-effects due to beans not getting fully loaded when using that way instead of BeanFactory.
            All records lost their email-addresses(!) as a result. I was not pleased.

          • Sugar 8: Especially if you have a lot of contacts, bad default indices on the table erased_fields will slow things down a lot as soon as it has a single record in it. erased_fields only has a 2-column index by default (which isn't used in important queries though), so you'll have to add 2 individual indices for those 2 columns and things will be a lot faster again.






          share|improve this answer


























          • Hi @Jay Thank you for your help! Could you please maybe tell me how is it possible to run these tasks in parallel ?

            – Hamzaouiii
            Nov 18 '18 at 12:06











          • @Hamzaouiii Well, that's outside the scope of Sugar and its Schedulers and should be only used as last resort (also it's not cloud-capable as it requires execution on the system level). You'd have to create a PHP script that loads in the sugar environment (similar to gist.github.com/bickart/5468138 ) before doing recalculations for a single module or chunk e.g. given by a call argument. Then configure the apache user's cron to run the script for each of the required modules (or even one for each chunk of records if you want to have more than one job running at a time, per module).

            – Jay
            Nov 18 '18 at 12:18












          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53344305%2fbean-save-is-taking-way-too-long-per-record-in-sugarcrm%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2














          First of all I'd recommend finding out what part of the save takes so long, using the tool of your choice... profiler/debugger/custom Timers/etc.




          • Is it a hook? Optimize it or make a custom flag to skip it if not needed for the recalc.

          • Is it a query? Analyse the queries (EXPLAIN) to find out if adding indices to your database could help.

          • Is it excessive log output? Reduce it.

          • Is it the bean loading for related bean calculation? Optimize formulas or skip if not needed.


          Other things you could try:




          • Prefilter which beans you want to resave using a Query (e.g. maybe record recalc not necessary if in certain state or modified after a certain related bean etc?).

          • Trigger updating calculated fields in your code and check if (relevant) values of the bean where actually changed after, if not then there's no need to resave it and you can skip to the next record instead.

          • If this is just about updating non-related calculated fields even although related calculated fields exist, then you could decide to (temporarily?) set $sugar_config['disable_related_calc_fields'] to true. That way Sugar wouldn't have to load those related beans.


          If there is no hope left:




          • Consider running those tasks in parallel

          • Rewrite whatever you need to update using SQL/SugarQuery (may not be possible, depending on complexity and implications).


          Notes:




          • Be aware that get_full_list() is deprecated since at least Sugar 7.7 and replaced by SugarQuery and $bean->fetchFromQuery(). However I'd recommend using a Query to only retrieve the IDs and use BeanFactory::retrieveBean($module, $id) to load the beans, possibly dismissing them each after computation, using BeanFactory::unregisterBean($bean); unset($bean); to help the garbage collector with keeping a low memory profile.
            Also I did use get_full_list() and fetchFromQuery in the past with catastrophic side-effects due to beans not getting fully loaded when using that way instead of BeanFactory.
            All records lost their email-addresses(!) as a result. I was not pleased.

          • Sugar 8: Especially if you have a lot of contacts, bad default indices on the table erased_fields will slow things down a lot as soon as it has a single record in it. erased_fields only has a 2-column index by default (which isn't used in important queries though), so you'll have to add 2 individual indices for those 2 columns and things will be a lot faster again.






          share|improve this answer


























          • Hi @Jay Thank you for your help! Could you please maybe tell me how is it possible to run these tasks in parallel ?

            – Hamzaouiii
            Nov 18 '18 at 12:06











          • @Hamzaouiii Well, that's outside the scope of Sugar and its Schedulers and should be only used as last resort (also it's not cloud-capable as it requires execution on the system level). You'd have to create a PHP script that loads in the sugar environment (similar to gist.github.com/bickart/5468138 ) before doing recalculations for a single module or chunk e.g. given by a call argument. Then configure the apache user's cron to run the script for each of the required modules (or even one for each chunk of records if you want to have more than one job running at a time, per module).

            – Jay
            Nov 18 '18 at 12:18
















          2














          First of all I'd recommend finding out what part of the save takes so long, using the tool of your choice... profiler/debugger/custom Timers/etc.




          • Is it a hook? Optimize it or make a custom flag to skip it if not needed for the recalc.

          • Is it a query? Analyse the queries (EXPLAIN) to find out if adding indices to your database could help.

          • Is it excessive log output? Reduce it.

          • Is it the bean loading for related bean calculation? Optimize formulas or skip if not needed.


          Other things you could try:




          • Prefilter which beans you want to resave using a Query (e.g. maybe record recalc not necessary if in certain state or modified after a certain related bean etc?).

          • Trigger updating calculated fields in your code and check if (relevant) values of the bean where actually changed after, if not then there's no need to resave it and you can skip to the next record instead.

          • If this is just about updating non-related calculated fields even although related calculated fields exist, then you could decide to (temporarily?) set $sugar_config['disable_related_calc_fields'] to true. That way Sugar wouldn't have to load those related beans.


          If there is no hope left:




          • Consider running those tasks in parallel

          • Rewrite whatever you need to update using SQL/SugarQuery (may not be possible, depending on complexity and implications).


          Notes:




          • Be aware that get_full_list() is deprecated since at least Sugar 7.7 and replaced by SugarQuery and $bean->fetchFromQuery(). However I'd recommend using a Query to only retrieve the IDs and use BeanFactory::retrieveBean($module, $id) to load the beans, possibly dismissing them each after computation, using BeanFactory::unregisterBean($bean); unset($bean); to help the garbage collector with keeping a low memory profile.
            Also I did use get_full_list() and fetchFromQuery in the past with catastrophic side-effects due to beans not getting fully loaded when using that way instead of BeanFactory.
            All records lost their email-addresses(!) as a result. I was not pleased.

          • Sugar 8: Especially if you have a lot of contacts, bad default indices on the table erased_fields will slow things down a lot as soon as it has a single record in it. erased_fields only has a 2-column index by default (which isn't used in important queries though), so you'll have to add 2 individual indices for those 2 columns and things will be a lot faster again.






          share|improve this answer


























          • Hi @Jay Thank you for your help! Could you please maybe tell me how is it possible to run these tasks in parallel ?

            – Hamzaouiii
            Nov 18 '18 at 12:06











          • @Hamzaouiii Well, that's outside the scope of Sugar and its Schedulers and should be only used as last resort (also it's not cloud-capable as it requires execution on the system level). You'd have to create a PHP script that loads in the sugar environment (similar to gist.github.com/bickart/5468138 ) before doing recalculations for a single module or chunk e.g. given by a call argument. Then configure the apache user's cron to run the script for each of the required modules (or even one for each chunk of records if you want to have more than one job running at a time, per module).

            – Jay
            Nov 18 '18 at 12:18














          2












          2








          2







          First of all I'd recommend finding out what part of the save takes so long, using the tool of your choice... profiler/debugger/custom Timers/etc.




          • Is it a hook? Optimize it or make a custom flag to skip it if not needed for the recalc.

          • Is it a query? Analyse the queries (EXPLAIN) to find out if adding indices to your database could help.

          • Is it excessive log output? Reduce it.

          • Is it the bean loading for related bean calculation? Optimize formulas or skip if not needed.


          Other things you could try:




          • Prefilter which beans you want to resave using a Query (e.g. maybe record recalc not necessary if in certain state or modified after a certain related bean etc?).

          • Trigger updating calculated fields in your code and check if (relevant) values of the bean where actually changed after, if not then there's no need to resave it and you can skip to the next record instead.

          • If this is just about updating non-related calculated fields even although related calculated fields exist, then you could decide to (temporarily?) set $sugar_config['disable_related_calc_fields'] to true. That way Sugar wouldn't have to load those related beans.


          If there is no hope left:




          • Consider running those tasks in parallel

          • Rewrite whatever you need to update using SQL/SugarQuery (may not be possible, depending on complexity and implications).


          Notes:




          • Be aware that get_full_list() is deprecated since at least Sugar 7.7 and replaced by SugarQuery and $bean->fetchFromQuery(). However I'd recommend using a Query to only retrieve the IDs and use BeanFactory::retrieveBean($module, $id) to load the beans, possibly dismissing them each after computation, using BeanFactory::unregisterBean($bean); unset($bean); to help the garbage collector with keeping a low memory profile.
            Also I did use get_full_list() and fetchFromQuery in the past with catastrophic side-effects due to beans not getting fully loaded when using that way instead of BeanFactory.
            All records lost their email-addresses(!) as a result. I was not pleased.

          • Sugar 8: Especially if you have a lot of contacts, bad default indices on the table erased_fields will slow things down a lot as soon as it has a single record in it. erased_fields only has a 2-column index by default (which isn't used in important queries though), so you'll have to add 2 individual indices for those 2 columns and things will be a lot faster again.






          share|improve this answer















          First of all I'd recommend finding out what part of the save takes so long, using the tool of your choice... profiler/debugger/custom Timers/etc.




          • Is it a hook? Optimize it or make a custom flag to skip it if not needed for the recalc.

          • Is it a query? Analyse the queries (EXPLAIN) to find out if adding indices to your database could help.

          • Is it excessive log output? Reduce it.

          • Is it the bean loading for related bean calculation? Optimize formulas or skip if not needed.


          Other things you could try:




          • Prefilter which beans you want to resave using a Query (e.g. maybe record recalc not necessary if in certain state or modified after a certain related bean etc?).

          • Trigger updating calculated fields in your code and check if (relevant) values of the bean where actually changed after, if not then there's no need to resave it and you can skip to the next record instead.

          • If this is just about updating non-related calculated fields even although related calculated fields exist, then you could decide to (temporarily?) set $sugar_config['disable_related_calc_fields'] to true. That way Sugar wouldn't have to load those related beans.


          If there is no hope left:




          • Consider running those tasks in parallel

          • Rewrite whatever you need to update using SQL/SugarQuery (may not be possible, depending on complexity and implications).


          Notes:




          • Be aware that get_full_list() is deprecated since at least Sugar 7.7 and replaced by SugarQuery and $bean->fetchFromQuery(). However I'd recommend using a Query to only retrieve the IDs and use BeanFactory::retrieveBean($module, $id) to load the beans, possibly dismissing them each after computation, using BeanFactory::unregisterBean($bean); unset($bean); to help the garbage collector with keeping a low memory profile.
            Also I did use get_full_list() and fetchFromQuery in the past with catastrophic side-effects due to beans not getting fully loaded when using that way instead of BeanFactory.
            All records lost their email-addresses(!) as a result. I was not pleased.

          • Sugar 8: Especially if you have a lot of contacts, bad default indices on the table erased_fields will slow things down a lot as soon as it has a single record in it. erased_fields only has a 2-column index by default (which isn't used in important queries though), so you'll have to add 2 individual indices for those 2 columns and things will be a lot faster again.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 17 '18 at 12:05

























          answered Nov 17 '18 at 11:58









          JayJay

          1,346612




          1,346612













          • Hi @Jay Thank you for your help! Could you please maybe tell me how is it possible to run these tasks in parallel ?

            – Hamzaouiii
            Nov 18 '18 at 12:06











          • @Hamzaouiii Well, that's outside the scope of Sugar and its Schedulers and should be only used as last resort (also it's not cloud-capable as it requires execution on the system level). You'd have to create a PHP script that loads in the sugar environment (similar to gist.github.com/bickart/5468138 ) before doing recalculations for a single module or chunk e.g. given by a call argument. Then configure the apache user's cron to run the script for each of the required modules (or even one for each chunk of records if you want to have more than one job running at a time, per module).

            – Jay
            Nov 18 '18 at 12:18



















          • Hi @Jay Thank you for your help! Could you please maybe tell me how is it possible to run these tasks in parallel ?

            – Hamzaouiii
            Nov 18 '18 at 12:06











          • @Hamzaouiii Well, that's outside the scope of Sugar and its Schedulers and should be only used as last resort (also it's not cloud-capable as it requires execution on the system level). You'd have to create a PHP script that loads in the sugar environment (similar to gist.github.com/bickart/5468138 ) before doing recalculations for a single module or chunk e.g. given by a call argument. Then configure the apache user's cron to run the script for each of the required modules (or even one for each chunk of records if you want to have more than one job running at a time, per module).

            – Jay
            Nov 18 '18 at 12:18

















          Hi @Jay Thank you for your help! Could you please maybe tell me how is it possible to run these tasks in parallel ?

          – Hamzaouiii
          Nov 18 '18 at 12:06





          Hi @Jay Thank you for your help! Could you please maybe tell me how is it possible to run these tasks in parallel ?

          – Hamzaouiii
          Nov 18 '18 at 12:06













          @Hamzaouiii Well, that's outside the scope of Sugar and its Schedulers and should be only used as last resort (also it's not cloud-capable as it requires execution on the system level). You'd have to create a PHP script that loads in the sugar environment (similar to gist.github.com/bickart/5468138 ) before doing recalculations for a single module or chunk e.g. given by a call argument. Then configure the apache user's cron to run the script for each of the required modules (or even one for each chunk of records if you want to have more than one job running at a time, per module).

          – Jay
          Nov 18 '18 at 12:18





          @Hamzaouiii Well, that's outside the scope of Sugar and its Schedulers and should be only used as last resort (also it's not cloud-capable as it requires execution on the system level). You'd have to create a PHP script that loads in the sugar environment (similar to gist.github.com/bickart/5468138 ) before doing recalculations for a single module or chunk e.g. given by a call argument. Then configure the apache user's cron to run the script for each of the required modules (or even one for each chunk of records if you want to have more than one job running at a time, per module).

          – Jay
          Nov 18 '18 at 12:18




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53344305%2fbean-save-is-taking-way-too-long-per-record-in-sugarcrm%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Bressuire

          Vorschmack

          Quarantine