Hi,
From what I can see in the query debug data, it comes from a change with made last summer following this thread in order to allow URLs without the id to use translated aliases :
www.hikashop.com/forum/5-support-en-fran...ias-de-produits.html
For that to work properly (which wasn't the case until then), we have to load a cache of the all the aliases of all the products. Since you have a lot of products it requires loading a big table of data of 20000 entries in memory and that's what's slowing down the whole thing.
A simple solution to this is to turn off the "Remove products and categories id in URLs" setting in the HikaShop configuration.
That way, the URLs will include the id of the products and the system won't have to search for the matching alias.
For a more complex solution, I've rewritten the code:
function getOriginalId($type, $name, $dynamic=false) {
$lang = JFactory::getLanguage();
$tag = $lang->getTag();
if($this->falang) {
$lang_id = $this->getId($tag);
$condition = 'reference_field='.$this->database->Quote($type.'_alias').' AND value = '.$this->database->Quote(str_replace(':','-',$name));
if($dynamic) {
$name_regex = '^ *p?'.str_replace(array('-',':'),'.+',$name).' *$';
$condition = '((reference_field='.$this->database->Quote($type.'_alias').' AND (value = '.$this->database->Quote(str_replace(':','-',$name)).' OR value REGEXP '.$this->database->Quote($name_regex).')) OR (reference_field='.$this->database->Quote($type.'_name').' AND value REGEXP '.$this->database->Quote($name_regex).'))';
}
$query = 'SELECT reference_id FROM '.hikashop_table('falang_content',false).' WHERE language_id='.(int)$lang_id.' AND reference_table='.$this->database->Quote('hikashop_'.$type).' AND '. $condition;
$this->database->setQuery($query);
$retrieved_id = $this->database->loadResult();
return $retrieved_id;
}
static $elements = array();
if(!isset($elements[$type])) {
$condition = '';
if($type == 'product') {
$condition = ' WHERE product_type = \'main\'';
}
$query = 'SELECT '.$type.'_id as id,'.$type.'_alias,'.$type.'_name FROM '.hikashop_table($type). $condition;
$this->database->setQuery($query);
$elements[$type] = $this->database->loadObjectList('id');
}
if(empty($elements[$type]))
return false;
$class = hikashop_get('class.'.$type);
foreach($elements[$type] as $k => $v) {
if(!isset($v->alias)) {
$key = $type.'_id';
$elements[$type][$k]->$key = $v->id;
$class->addAlias($elements[$type][$k]);
}
if($elements[$type][$k]->alias == str_replace(':','-',$name)) {
return $k;
}
}
return false;
}
to:
function getOriginalId($type, $name, $dynamic=false, $forceRefresh=false) {
$lang = JFactory::getLanguage();
$tag = $lang->getTag();
if($this->falang) {
$lang_id = $this->getId($tag);
$condition = 'reference_field='.$this->database->Quote($type.'_alias').' AND value = '.$this->database->Quote(str_replace(':','-',$name));
if($dynamic) {
$name_regex = '^ *p?'.str_replace(array('-',':'),'.+',$name).' *$';
$condition = '((reference_field='.$this->database->Quote($type.'_alias').' AND (value = '.$this->database->Quote(str_replace(':','-',$name)).' OR value REGEXP '.$this->database->Quote($name_regex).')) OR (reference_field='.$this->database->Quote($type.'_name').' AND value REGEXP '.$this->database->Quote($name_regex).'))';
}
$query = 'SELECT reference_id FROM '.hikashop_table('falang_content',false).' WHERE language_id='.(int)$lang_id.' AND reference_table='.$this->database->Quote('hikashop_'.$type).' AND '. $condition;
$this->database->setQuery($query);
$retrieved_id = $this->database->loadResult();
return $retrieved_id;
}
if(!isset($_SESSION['hikashop_alias_cache']))
$_SESSION['hikashop_alias_cache'] = array();
if(!isset($_SESSION['hikashop_alias_cache'][$type]) || $forceRefresh) {
$condition = '';
if($type == 'product') {
$condition = ' WHERE product_type = \'main\'';
}
$query = 'SELECT '.$type.'_id as id,'.$type.'_alias,'.$type.'_name FROM '.hikashop_table($type). $condition;
$this->database->setQuery($query);
$_SESSION['hikashop_alias_cache'][$type] = $this->database->loadObjectList('id');
if(!empty($_SESSION['hikashop_alias_cache'][$type])) {
$class = hikashop_get('class.'.$type);
foreach($_SESSION['hikashop_alias_cache'][$type] as $k => $v) {
$key = $type.'_id';
$_SESSION['hikashop_alias_cache'][$type][$k]->$key = $v->id;
$class->addAlias($_SESSION['hikashop_alias_cache'][$type][$k]);
}
}
}
if(empty($_SESSION['hikashop_alias_cache'][$type]))
return false;
foreach($_SESSION['hikashop_alias_cache'][$type] as $k => $v) {
if($_SESSION['hikashop_alias_cache'][$type][$k]->alias == str_replace(':','-',$name)) {
return $k;
}
}
if(!$forceRefresh) {
return $this->getOriginalId($type, $name, $dynamic, true);
}
return false;
}
in the file administrator/components/com_hikashop/helpers/translation.php
That will move the cache of the aliases in the session instead of in a static variable. That way, the system will only have to load that table of aliases once per user session. So the first product page displayed will be slow, but after that, it should be fast again.
Could you try the modification on your end ? Does it help ?
Unfortunately, I don't see a solution where we wouldn't need to load the aliases table in memory in such cases.