Forums / Developer / MySQL statements eZ Publish - howto?

MySQL statements eZ Publish - howto?

Author Message

Clemens T

Thursday 11 December 2008 2:54:17 am

Below, this code seems to be very slow, is there anyway to upgrade performance? For example instead of looping through all the attributes getting directly to the one attribute? But I don't know how...

		$objectAttributes =& $object->ContentObjectAttributes();
		foreach($objectAttributes as $objectAttribute)
		{
			//Fetch the object's attribute 'groups' (which is the related objects attribute)
			$name =& $objectAttribute->contentClassAttributeIdentifier();
			//eZDebug::writeNotice("ObjectAttributeName: $name","Workflow smInternalPressReleaseType");

			if($name == "groups")
			{
				$content = $objectAttribute->content();
				foreach( $content['relation_list'] as $relation)
				{
					//eZDebug::writeNotice("Relation ContentClassID: $relation["contentclass_identifier']","Workflow smInternalPressReleaseType");
					//filter the pr_groups from the related list
					if($relation["contentclass_identifier"] == "pr_group")
					{
						$contentobject_id = $relation["contentobject_id"];
						eZDebug::writeNotice("contentobject_id: $contentobject_id","Workflow smInternalPressReleaseType");

						$node_id = $relation["node_id"];
						eZDebug::writeNotice("node_id: $node_id","Workflow smInternalPressReleaseType");						
						/*
						 * Fetch all the PR_MAIL class ID=29 objects from the related node
						 */
						$subtreeFetchParams=array(
							'ClassFilterType' => 'include',
							'ClassFilterArray' => array(29),
							'status' => EZ_CONTENT_OBJECT_STATUS_PUBLISHED);
						
						$childNodes =& eZContentObjectTreeNode::subTree($subtreeFetchParams,$node_id);
						eZDebug::writeNotice("childNodes: $childNodes[0]","Workflow smInternalPressReleaseType");	
												
						foreach( $childNodes as $child )
						{								
							eZDebug::writeNotice("child: $child","Workflow smInternalPressReleaseType");	
						
							//Child is of type eZContentObjectTreeNode			
							if($child->hasContentObject())
							{
								//Fetch the eZContentObject of this eZContentObjectTreeNode
								$childContentObject =& $child->object();

								//Fetch the contentObjectAttributes
								$childAttributes = $childContentObject->ContentObjectAttributes();
								
								eZDebug::writeNotice("childAttributes: $childAttributes[0]","Workflow smInternalPressReleaseType");	
								eZDebug::writeNotice(print_r($childAttributes));
							
								foreach($childAttributes as $childAttribute)
								{
									//Fetch the object's attribute 'groups' (which is the related objects attribute)
									$childAttributename =& $childAttribute->contentClassAttributeIdentifier();									
									eZDebug::writeNotice("childAttributeName: $childAttributename","Workflow smInternalPressReleaseType");		
						
									//only fetch the e-mailaddress
									if($childAttributename=="email")
									{
										eZDebug::writeNotice("childAttributeName: $childAttribute->content()","Workflow smInternalPressReleaseType");			
										$emailsOfReceivers[] = $childAttribute->content();
									}
								}//foreach childattributes
							} //child->hasContentObject
			
						}//foreach childnodes
					}//if relation_list == pr_group
				}//foreach relation_list
			}//if name=="groups"
		}

Thanks as always!

André R.

Thursday 11 December 2008 4:04:55 am

custom sql..

On the "$node_id = $relation["node_id"];" line, get the path_string for the node so you can use it in where statment of your custom sql to get the email attributes, also use class id and class attribute id instead of identifiers in the sql where / join statments.
You can get this with eZContentObjectTreeNode::classAttributeIDByIdentifier and ::classIDByIdentifier before the loops.

eZ Online Editor 5: http://projects.ez.no/ezoe || eZJSCore (Ajax): http://projects.ez.no/ezjscore || eZ Publish EE http://ez.no/eZPublish/eZ-Publish-Enterprise-Subscription
@: http://twitter.com/andrerom

Clemens T

Thursday 11 December 2008 5:42:29 am

Thanks Andre, I've considered that option... but I believe it could make my code fail in the future, so that's why I've done the following changes (change foreach for a array key lookup). It's much faster now!

		//Reject if this object does not have a valid main node
		if(is_null($mainNodeID))
			return EZ_WORKFLOW_TYPE_STATUS_REJECTED;			
		
		$dataMap = $object->dataMap(); 

		if(array_key_exists( 'groups', $dataMap ) )
		{		
			$content = $dataMap['groups']->content();
			foreach( $content['relation_list'] as $relation)
			{
				//eZDebug::writeNotice($relation["contentclass_identifier"], "internal");		
				//filter the pr_groups from the related list
				if($relation["contentclass_identifier"] == "pr_group")
				{
					$contentobject_id = $relation["contentobject_id"];
					$node_id = $relation["node_id"];
					/*
					 * Fetch all the PR_MAIL class ID=29 objects from the related node
					 */
					$subtreeFetchParams=array(
						'ClassFilterType' => 'include',
						'ClassFilterArray' => array(29),
						'status' => EZ_CONTENT_OBJECT_STATUS_PUBLISHED);
					
					$childNodes =& eZContentObjectTreeNode::subTree($subtreeFetchParams,$node_id);				
					foreach( $childNodes as $child )
					{								
						//Child is of type eZContentObjectTreeNode			
						if($child->hasContentObject())
						{
							//Fetch the eZContentObject of this eZContentObjectTreeNode
							$childContentObject =& $child->object();
							$childDataMap = $childContentObject->dataMap(); 

							//eZDebug::writeNotice("childDataMap :".print_r($childDataMap, true), "internal");	
							if(array_key_exists( 'email', $childDataMap ) )
							{
								eZDebug::writeNotice("Un-uniqueified emailOfReceiver: ".$childDataMap['email']->content(),"Workflow smInternalPressReleaseType");									
								$emailsOfReceivers[] = $childDataMap['email']->content();
							}//array_key_exists (email)
						} //child->hasContentObject		
					}//foreach childnodes
				}//if relation_list == pr_group				
			}//foreach relation_list
		}//if array key exists (groups)

Clemens T

Monday 15 December 2008 4:02:41 pm

The peformance increase I got from editing the code didn't contribute enough to make the system stable enough. Could anyone help me build the SQL that this code produces, since it is the first time I'm attempting that. Or just some pointers on how to work with the MySQL database layer eZ Publish offers.

Thanks!

André R.

Wednesday 17 December 2008 9:10:03 am

This might help:

$node_id = $relation["node_id"];
$subtreeFetchParams = array(
        'ClassFilterType' => 'include',
        'ClassFilterArray' => array(29)
        );

$childNodes =& eZContentObjectTreeNode::subTree($subtreeFetchParams, $node_id);                              
foreach( $childNodes as $child )
{                                                               
    $emailAttribute =& $child->object()->fetchAttributesByIdentifier( array('email') );
    $emailsOfReceivers[] = $emailAttribute->content();
      
}//foreach childnodes

Remove the & after = if your on php5.
Note: If you don't need to check permission, then you can also set 'Limitation' => array() on subtreeFetchParams.

eZ Online Editor 5: http://projects.ez.no/ezoe || eZJSCore (Ajax): http://projects.ez.no/ezjscore || eZ Publish EE http://ez.no/eZPublish/eZ-Publish-Enterprise-Subscription
@: http://twitter.com/andrerom

Clemens T

Thursday 18 December 2008 3:54:59 am

Andre,

Thanks again for putting effort in helping me find a solution.

It most certainly increase the speed of the application, the final code:


					$node_id = $relation["node_id"];
					$subtreeFetchParams = array(
						'ClassFilterType' => 'include',
						'ClassFilterArray' => array(29),
						'Limitation' => array(),
					);
					$childNodes =& eZContentObjectTreeNode::subTree($subtreeFetchParams, $node_id);                              					
					foreach( $childNodes as $child )
					{                                                               
					   $chContentObject =& $child->object();
					   $datamap = $chContentObject->dataMap();
					   $emailsOfReceivers[] = $datamap['email']->content();
					}//foreach childnodes

Unfortunately, the $chContentObject had to be stored in between, before I could get the datamap, but this is already a great improvement. Thanks also for introducing the 'Limitation' = array() to me, because I was already logging a dedicated user in via:

		/*
		 * Log the current logged in user, in order to make sure that we are able to log
		 * him/her in after this event is done. Needed because we change users in the middle.
		 */
		$eZUser = eZUser::currentUser();
		$userID = eZUser::currentUserID();
		
		/*
		 * Login the user that is used for sending the press releases 
		 * (and will be able to read the newsitems / images)
		 *
		 * This is needed because this is being executed by a workflow.
		 */
		$loginResult = eZUser::loginUser("x_read","x");
		if(!$loginResult)
		{
			return $module->handleError( EZ_ERROR_KERNEL_ACCESS_DENIED, 'kernel' );
		}

and then logging out and re-setting the currently loggged in user, so this is a great contribution!

Thanks again :),
Clemens

eZ debug

Timing: Jan 31 2025 01:23:31
Script start
Timing: Jan 31 2025 01:23:31
Module start 'content'
Timing: Jan 31 2025 01:23:31
Module end 'content'
Timing: Jan 31 2025 01:23:32
Script end

Main resources:

Total runtime0.2005 sec
Peak memory usage8,192.0000 KB
Database Queries141

Timing points:

CheckpointStart (sec)Duration (sec)Memory at start (KB)Memory used (KB)
Script start 0.00000.0064 587.9531370.2891
Module start 'content' 0.00640.0130 958.24221,013.6563
Module end 'content' 0.01940.1810 1,971.89843,904.9609
Script end 0.2004  5,876.8594 

Time accumulators:

 Accumulator Duration (sec) Duration (%) Count Average (sec)
Ini load
Load cache0.00462.3027200.0002
Check MTime0.00130.6676200.0001
Mysql Total
Database connection0.00050.254910.0005
Mysqli_queries0.106353.00361410.0008
Looping result0.00130.64521390.0000
Template Total0.180590.110.1805
Template load0.00100.478410.0010
Template processing0.179689.586510.1796
Override
Cache load0.00070.324810.0007
Sytem overhead
Fetch class attribute can translate value0.00200.987310.0020
XML
Image XML parsing0.00030.154610.0003
General
dbfile0.00653.2584200.0003
String conversion0.00000.002130.0000
Note: percentages do not add up to 100% because some accumulators overlap

CSS/JS files loaded with "ezjscPacker" during request:

CacheTypePacklevelSourceFiles
CSS0extension/community/design/community/stylesheets/ext/jquery.autocomplete.css
extension/community_design/design/suncana/stylesheets/scrollbars.css
extension/community_design/design/suncana/stylesheets/tabs.css
extension/community_design/design/suncana/stylesheets/roadmap.css
extension/community_design/design/suncana/stylesheets/content.css
extension/community_design/design/suncana/stylesheets/star-rating.css
extension/community_design/design/suncana/stylesheets/syntax_and_custom_tags.css
extension/community_design/design/suncana/stylesheets/buttons.css
extension/community_design/design/suncana/stylesheets/tweetbox.css
extension/community_design/design/suncana/stylesheets/jquery.fancybox-1.3.4.css
extension/bcsmoothgallery/design/standard/stylesheets/magnific-popup.css
extension/sevenx/design/simple/stylesheets/star_rating.css
extension/sevenx/design/simple/stylesheets/libs/fontawesome/css/all.min.css
extension/sevenx/design/simple/stylesheets/main.v02.css
extension/sevenx/design/simple/stylesheets/main.v02.res.css
JS0extension/ezjscore/design/standard/lib/yui/3.17.2/build/yui/yui-min.js
extension/ezjscore/design/standard/javascript/jquery-3.7.0.min.js
extension/community_design/design/suncana/javascript/jquery.ui.core.min.js
extension/community_design/design/suncana/javascript/jquery.ui.widget.min.js
extension/community_design/design/suncana/javascript/jquery.easing.1.3.js
extension/community_design/design/suncana/javascript/jquery.ui.tabs.js
extension/community_design/design/suncana/javascript/jquery.hoverIntent.min.js
extension/community_design/design/suncana/javascript/jquery.popmenu.js
extension/community_design/design/suncana/javascript/jScrollPane.js
extension/community_design/design/suncana/javascript/jquery.mousewheel.js
extension/community_design/design/suncana/javascript/jquery.cycle.all.js
extension/sevenx/design/simple/javascript/jquery.scrollTo.js
extension/community_design/design/suncana/javascript/jquery.cookie.js
extension/community_design/design/suncana/javascript/ezstarrating_jquery.js
extension/community_design/design/suncana/javascript/jquery.initboxes.js
extension/community_design/design/suncana/javascript/app.js
extension/community_design/design/suncana/javascript/twitterwidget.js
extension/community_design/design/suncana/javascript/community.js
extension/community_design/design/suncana/javascript/roadmap.js
extension/community_design/design/suncana/javascript/ez.js
extension/community_design/design/suncana/javascript/ezshareevents.js
extension/sevenx/design/simple/javascript/main.js

Templates used to render the page:

UsageRequested templateTemplateTemplate loadedEditOverride
1pagelayout.tpl<No override>extension/sevenx/design/simple/templates/pagelayout.tplEdit templateOverride template
 Number of times templates used: 1
 Number of unique templates used: 1

Time used to render debug report: 0.0001 secs