We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 16289
    • 121 Posts
    Заметил, что сниппет Jot генерирует огромное количество запросов. Кэшированный вызов у меня отказался работать, к тому же я подключл AJAX.
    Итого, просмотрев лог, я ужаснулся: на каждый комментарий сниппет обращался с запросо к БД для вытаскивания информации о юзере, что написал комментарий.
    Просмотрев шаблон, наткнулся на конструкцию:
    [+comment.createdby:userinfo=`username`:ifempty=`[+comment.custom.name:ifempty=`[+jot.guestname+]`:esc+]`+][+comment.createdby:isnt=`0`:then=``:+]

    Она и есть причиной этого. При парсинге pHx модификатор :userinfo обращается к базе для получения юзер инфы.
    Идея оптимизации - получать эту инфу с одного запроса, где формируется массив с комментариями с помощью `inner join`. Но задача усугубляется существованием менеджеров и веб юзеров, у которых, как известно, id для Jot отличаются знаком (для веб юзеров он отрицательный).
    Кто-то задумывался над этим?
      How could number of mysql queries be more than number of tables in DB???
      • 16289
      • 121 Posts
      Подолбавшись немного, снизил количество запросов, заменив функции в jot.db.class.inc.php своими:

      function CJotDataDb() {
      		global $modx;
      		$this->tbl["check"] = $GLOBALS['table_prefix']."jot_fields";
      		$this->tbl["content"] = $modx->getFullTableName('jot_content');
      		$this->tbl["subscriptions"] = $modx->getFullTableName('jot_subscriptions');
      		$this->tbl["fields"] = $modx->getFullTableName('jot_fields');
      		$this->tbl["manager_users"] = $modx->getFullTableName('manager_users');
      		$this->tbl["user_attributes"] = $modx->getFullTableName('user_attributes');
      		$this->tbl["web_users"] = $modx->getFullTableName('web_users');
      		$this->tbl["web_user_attributes"] = $modx->getFullTableName('web_user_attributes');
      		$this->cache["userpostcount"] = array();
      		$this->isNew = false;
      	}


      function GetComments($docid,$tagid,$viewtype,$sort,$offset,$length) {
      		global $modx;
      		$tbl = $this->tbl["content"];
      		$where = NULL;
      		if ($length > 0 ) { $limit = " limit $offset, $length"; }
      		
      		$orderby = " order by createdon desc ";
      		$tblcustom = "";
      		if (strlen($sort) > 3) {
      			$orderby = array();
      			$tblcustom = array();
      			$obparts = explode(",", $sort);
      			$c = 0;
      			foreach ($obparts as $obpart) {
      				$x = explode(":", $obpart);
      				if($x[0]{0} == "#") {
      					$c++;
      					$fld = str_replace("#","",$x[0]);
      					$tblcustom[] = "left join " . $this->tbl["fields"] . " as " . "c" . $c . " on c". $c . ".id = a.id and c". $c . ".label = '" . $fld . "'";
      					$orderby[] = "c" . $c . ".content" . " " . $this->getOrderByDirection($x[1]);					
      				} else {
      				$orderby[] = $x[0] . " " . $this->getOrderByDirection($x[1]);
      				}
      			}
      			$orderby = " order by " . implode(", ",$orderby);
      			$tblcustom = implode(" ",$tblcustom);
      		} 		
             $user_data_tbl="left join " . $this->tbl["manager_users"] . " as mu on mu.id=a.createdby "
      					."left join " . $this->tbl["user_attributes"] . " as mua on mua.id=mu.id "
      					."left join " . $this->tbl["web_users"] . " as wu on wu.id=-a.createdby "
      					."left join " . $this->tbl["web_user_attributes"] . " as wua on wua.id=wu.id ";
      		switch ($viewtype) {
                              case 2:
                                      $where = " and a.published >= 0 "; // Mixed
                                      break;
                              case 0:
                                      $where = " and a.published >= 0 "; // Unpublished
                                      break;
                              case 1:
                              default:
                                      $where = " and a.published = 1 "; // Published
                      }
                      
      		if ($docid == '*')
                              $sql = "select a.*, b.published, mu.*, mua.*, wu.*, wua.* AS docpublished from " . $tbl . " as a " . $tblcustom . " "
                                              .$user_data_tbl." 
                                              left join modx_site_content AS b ON a.uparent = b.id 
                                              where tagid = '" . $tagid ."' and mode = '0' and b.published='1' " . $where . $orderby . $limit;
                      else
                              $sql = "select a.*, mu.*, mua.*, wu.*, wua.* from " . $tbl . " as a " . $tblcustom . " ".$user_data_tbl." where uparent = '$docid' and tagid = '" . $tagid ."' and mode = '0' " . $where . $orderby . $limit;
      		#print $sql;		
      		return $this->GetCommentsArray($sql);
      	}

      function GetCommentsArray($query) {
      		global $modx;
      		$rs = $modx->db->query($query);	
      		$comments = array();
      		$ids = array();
      		
      		
      		$array_fields_my=array();   // массив полей
      		
      		$all_fields=$modx->db->getColumnNames($rs); // получаем массив полей
      		foreach($all_fields as $key=>$field)  // перебираем массив полей ик повторяющимя полям приписываем префикс web - надо, чтобы поля веб юзера не перекрывали полей менеджера
      		{
      		    if(isset($array_fields_my[$field])) $array_fields_my['web_'.$field]=$key;		    
      		    else    							$array_fields_my[$field]=$key;	
      		    		
      		}
      		$array_fields_my=array_flip($array_fields_my);
      			
      		while ($row = $modx->db->getRow($rs,'num')) {
      			$ids[] = $row["id"];			
      			foreach ($array_fields_my as $key=>$value) // получаем массив с нужными полями уже со значениями
      			{
      				$row[$value]=$row[$key];		
      				unset($row[$key]);	
      			}
      			$comments[] = $row;				
      		}
      		
      		
      		$custom = $this->getCustomFieldsArray($ids);
      		
      		$arrComments = array();
      		foreach($comments as $comment) {
      			$comment["custom"] = $custom[$comment["id"]];
      			$comment["userpostcount"] = $this->getUserPostCount($comment["createdby"],$comment["uparent"],$comment["tagid"]);
      			$arrComments[] = $comment;
      		}  
      		return $arrComments;
      	}


      В плейсхолдер [+comment+] заносится вся инфа о юзере, включая аватары, данные о регистраци.....
      Данные о Web юзерах находятся в плейсхолдерах с префиксом ’web_’ : ([+comment.web_username+] , [+comment.web_photo+]... ) . Менеджеры без префикса.
      Итак, чтобы вставить, например, имя, надо добавить в шаблон такое:
      [+comment.username:ifempty=`[+comment.web_username:ifempty=`[+comment.custom.name:ifempty=`[+jot.guestname+]`:esc+]`+]`+]
      Это позволяет снизить запросы на количество комментариев на странице и вдобавок получить всю инфу о пользователе. У меня количество запросов упало на 20 штук!


        How could number of mysql queries be more than number of tables in DB???
        • 897
        • 1,620 Posts
        а время работы скрипта и время создания страницы снизилось?
          "Und wenn du lange in einen Abgrund blickst, blickt der Abgrund auch in dich hinein."

          Не используйте Revo для "просто сайтов". Используйте Evo

          Who can defeat the Russian bear?
          • 16289
          • 121 Posts
          Немного, порядка 0.1 с
            How could number of mysql queries be more than number of tables in DB???
            • 16289
            • 121 Posts
            Просто ньюанс в том, что у меня запрос выборки по полям юзера осуществляется через "*", и массив с данными по одному комментарию достигает 72 значений.
            Нужно запрашивать, только необходимые поля, тогда и ресурса меньше уйдет.
            Например, сделать переменную сниппета &user_fields, и вытаскивать, только поля занесенные туда. Производительность заметно увеличится.
              How could number of mysql queries be more than number of tables in DB???
              • 29487
              • 385 Posts
              Таблицы user_attributes и web_user_attributes по internalKey должны сцепляться, насколько я понимаю, а не по id:
              ."left join " . $this->tbl["user_attributes"] . " as mua on mua.id=mu.id "
              


              Здесь ошибка, должно быть равенство:
              $where = " and a.published >= 0 "; // Unpublished


              Это какой-то левый запрос в таблицу без префикса, его тут быть не должно:
              if ($docid == '*')
              $sql = "select a.*, b.published, mu.*, mua.*, wu.*, wua.* AS docpublished from " . $tbl . " as a " . $tblcustom . " "
              .$user_data_tbl." 
              left join modx_site_content AS b ON a.uparent = b.id 
              where tagid = '" . $tagid ."' and mode = '0' and b.published='1' " . $where . $orderby . $limit;
              


              В этом месте отваливаются custom-поля, так массив уже не ассоциативный:
              while ($row = $modx->db->getRow($rs,'num')) {
              $ids[] = $row["id"];
              


              ==========================================

              Идея с префиксом web_ мне не понравилась, порождает дополнительные условия.
              Я бы сделал по-другому, в функции GetComments заменил только sql-запрос, то есть вместо $sql="select ... поставил
              		$user_data_tbl="left join " . $modx->getFullTableName('manager_users') . " as mu on mu.id=a.createdby "
              			."left join " . $modx->getFullTableName('user_attributes') . " as mua on mua.internalKey=mu.id ";
              		$webuser_data_tbl="left join " . $modx->getFullTableName('web_users') . " as wu on wu.id=-a.createdby "
              			."left join " . $modx->getFullTableName('web_user_attributes') . " as wua on wua.internalKey=wu.id ";
              		
              		$sql = "(select a.*,mu.username,mua.fullname,mua.email,mua.role,mua.gender,mua.country,mua.photo
              		from " . $tbl . " as a " .$user_data_tbl." ".$tblcustom. " where a.createdby>=0 and uparent = '" . $docid . "' and tagid = '" . $tagid ."' and mode = '0' " . $where . ") 
              		union (select a.*,wu.username,wua.fullname,wua.email,wua.role,wua.gender,wua.country,wua.photo  
              		from " . $tbl . " as a " .$webuser_data_tbl." ".$tblcustom. " where a.createdby<0 and uparent = '" . $docid . "' and tagid = '" . $tagid ."' and mode = '0' " . $where . ")"
              		. $orderby . $limit;
              

              Запрос возможно не очень удачный, может кто-то подскажет лучше. Здесь я выбираю только те поля, что могут оказаться полезными.
              Теперь можно использовать [+comment.username+] и прочее без префикса.

              Больше ничего бы не трогал. Единственное, в Функции GetCommentsArray есть $comment["userpostcount"] в цикле, который тоже генерирует кучу запросов, вот его нужно переписать. Но у меня userpostcount не используется, поэтому я просто закомментировал эту строчку.
                • 16289
                • 121 Posts

                Здесь ошибка, должно быть равенство:
                $where = " and a.published >= 0 "; // Unpublished


                Это у меня почему-то так было


                Это какой-то левый запрос в таблицу без префикса, его тут быть не должно:

                if ($docid == '*')
                $sql = "select a.*, b.published, mu.*, mua.*, wu.*, wua.* AS docpublished from " . $tbl . " as a " . $tblcustom . " "
                .$user_data_tbl." 
                left join modx_site_content AS b ON a.uparent = b.id 
                where tagid = '" . $tagid ."' and mode = '0' and b.published='1' " . $where . $orderby . $limit;

                Ну это для себя сделал, чтоб выводить последние комментврии со всех страниц.

                В этом месте отваливаются custom-поля, так массив уже не ассоциативный:

                while ($row = $modx->db->getRow($rs,'num')) {
                $ids[] = $row["id"]
                ;

                В этом месте у меня ’assoc’ отказывался работать, а с ’num’ все равно возвращал ассоциативный массив.

                В общем главное было затронуть тему, так Вы очень хорошо улучшили.


                  How could number of mysql queries be more than number of tables in DB???