Рейтинг
0.00
голосов: 0

О блоге

Всё, что касается модулей

Администраторы (1)

Модераторы (0)

Модераторов здесь не замечено

Читатели (0)

Читателей здесь не замечено

Битрикс подкидывает проблем: b_cache_tag занимает много места, сайт тормозит

В версии 12.5 (в 14 возможно исправили, не смотрел ещё), при включенном кешировании компонентов, и большой посещаемости, табличка b_cache_tag начала набирать 15к записей в полчаса, а там одно и тоже, уникальных записей от силы 20. Из-за этого «говна», сайт начал дико тупить, на генерацию страницы уходило по 2 секунды, из-за очень многих инсертов на каждом шагу. Нормальные люди, делают инсерт — если такой записи нет, в битриксе решили не парится и народ везде на форумах, предлагает по крону транкейтить таблицу (это тупо пиздец).

Пришлось переписать функцию «виновника торжества» EndTagCache, запись добавляется только при уникальности составляющих (ибо если её просто отключить, кеширование исходит на говно). Тупой инсерт превратился в умный и красивый

function EndTagCache() {
	global $DB;
	$this->InitCompSalt();

	if($this->bWasTagged) {
		$sqlSITE_ID = $DB->ForSQL(SITE_ID, 2);
		$sqlCACHE_SALT = $this->SALT;

		$strSqlPrefix = "INSERT ".($this->isMySql? "IGNORE": "").
				" INTO b_cache_tag (SITE_ID, CACHE_SALT, RELATIVE_PATH, TAG) VALUES";
		$strSqlPrefix2 = "INSERT ".($this->isMySql? "IGNORE": "").
				" INTO b_cache_tag (SITE_ID, CACHE_SALT, RELATIVE_PATH, TAG) ";

		$maxValuesLen = $this->isMySql? 2048: 0;
		$strSqlValues = $strSqlValues2 = "";

		foreach($this->comp_cache_stack as $arCompCache) {
			$path = $arCompCache[0];
			if(strlen($path)) {
				$this->InitDBCache($path);
				$sqlRELATIVE_PATH = $DB->ForSQL($path, 255);

				$sql = ",\n('".$sqlSITE_ID."', '".$sqlCACHE_SALT."', '".$sqlRELATIVE_PATH."',";
				$sql2 = " SELECT * FROM (SELECT '".$sqlSITE_ID."', '".$sqlCACHE_SALT."', '".$sqlRELATIVE_PATH."', '#TAG#') AS tmp ".
"WHERE NOT EXISTS ( ".
"    SELECT SITE_ID FROM b_cache_tag ".
"    WHERE CACHE_SALT = '".$sqlCACHE_SALT."' ".
"    AND RELATIVE_PATH = '".$sqlRELATIVE_PATH."' ".
"    AND TAG = '#TAG#' ".
") LIMIT 1; \n";

				foreach($arCompCache[1] as $tag => $t) {
					if(!isset($this->DBCacheTags[$path][$tag])) {
						$strSqlValues .= $sql." '".$DB->ForSQL($tag, 50)."')";
						$strSqlValues2 = $strSqlPrefix2.str_replace("#TAG#",$DB->ForSQL($tag, 50), $sql2);
						$DB->Query($strSqlValues2);
						if(strlen($strSqlValues) > $maxValuesLen) {
							//$DB->Query($strSqlPrefix.substr($strSqlValues, 2));
							$strSqlValues = "";
							
						}
						$this->DBCacheTags[$path][$tag] = true;
					}
				}
			}
		}
		if($strSqlValues <> '') {
			//$DB->Query($strSqlPrefix.substr($strSqlValues, 2));
		}
	}

	array_shift($this->comp_cache_stack);
}

В итоге
INSERT IGNORE INTO b_cache_tag (SITE_ID, CACHE_SALT, RELATIVE_PATH, TAG) 
VALUES('ar', '/e25', '/ar/bitrix/news.list/06f', 'iblock_id_5')

Превращается в
INSERT IGNORE INTO b_cache_tag (SITE_ID, CACHE_SALT, RELATIVE_PATH, TAG)  
SELECT * FROM (SELECT 'ar', '/e25', '/ar/bitrix/news.list/06f', 'iblock_id_5') AS tmp 
WHERE NOT EXISTS (
     SELECT SITE_ID FROM b_cache_tag
     WHERE CACHE_SALT = '/e25'
     AND RELATIVE_PATH = '/ar/bitrix/news.list/06f'
     AND TAG = 'iblock_id_5' ) 
LIMIT 1;


У новой функции есть один недостаток, она выполняется в цикле каждый раз (хотя циклов больше двух я не видел), тогда как старая группирует инсерты в 1 запрос. В конечном итоге, скорость выполнения этого запроса очень велика, что полностью нивелирует недостаток.

Bitrix: как сделать пейджер, если выбрал данные через $db->query

Для начала вам нужно сделать запрос с cnt, что бы знать сколько всего записей, дальше вы делаете запрос с лимитом (выводите нужную страницу), а дальше простая магия:

$cnt = new CDBResult;
$cnt->InitFromArray(range(1,$allItemsCnt));
$cnt->NavStart($itemsPerPage, false, (isset($_GET["PAGEN_1"]) ? $_GET["PAGEN_1"] : false));
$arResult["Nav"] = $cnt->GetPageNavStringEx($navComponentObject);
$arResult["NavExt"] = $navComponentObject->arResult;

Отправка писем используя шаблон

В главном модуле есть Почтовые события:
* Почтовые шаблоны /message_admin.php?lang=ru
* Типы почтовых событий /bitrix/admin/type_admin.php?lang=en

Что бы отправить письмо, используя шаблон, мы сначала создадим тип почтового события (например TEXT_MESSAGE с параметрами #TEXT_MESSAGE#, #MAIL# и #DATE#), а затем шаблон для него (Например «Сообщение с сайта сайт.орг», указав все параметры в тексте, а #MAIL# в поле кому).

Дальше всё просто, используя главный модуль (его класс CEvent), мы отправляем письмо по нашему шаблону
$arMail = array(
	"DATE" => date("Y/m/d",strtotime("+2 hours")),
	"MAIL" => "test@ukr.net",
	"TEXT_MESSAGE" => "Hello world"    	
);
CEvent::Send("TEXT_MESSAGE", array("en"), $arMail);
  • 0
  • 24 января 2010, 01:09
  • admin