Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRM-20199 Contribution search performance #9631

Merged

Conversation

@eileenmcnaughton
Copy link
Contributor Author

@colemanw @monishdeb FYI - I am trying to clean up the contribution search class a bit in order to fix some of the performance issues. I dug into why some fields were manually declared in the hope of being a bit more meta-data-ey & found that it was because they were set to export = false. In each case a whole lot of handling had been added to compensate for it so I think we can add export = true more aggressively.

I'd like to remove the handling for contribution_check_number but it seems that as a result of it being there contribution_check_number is accepted & output (which is used by search fields & could possibly conflict with trxn_id I guess.....). I think the hated uniquenames are the right answer here + add a bit of handling in the contribution.get api to copy $result['contribution_check_number' to $result['check_number'] - this doesn't happen currently for contribution_source but perhaps it should.

That + dealing properly with the pseudoconstant fields (payment_instrument, financial_type, contribution_status is next)

Contribution is of course one of a handful of api using the query object....

@@ -157,100 +151,12 @@ public static function select(&$query) {
$query->_tables['civicrm_contribution'] = 1;
}

// LCD 716
$includeSoftCredits = self::isSoftCreditOptionEnabled($query->_params);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just moved

if (!empty($query->_returnProperties['contribution_campaign_title'])) {
$query->_select['contribution_campaign_title'] = "civicrm_campaign.title as contribution_campaign_title";
$query->_element['contribution_campaign_title'] = $query->_tables['civicrm_campaign'] = 1;
}

// Adding address_id in a way that is more easily extendable since the above is a bit ... wordy.
$supportedBasicReturnValues = array('address_id');
Copy link
Contributor Author

@eileenmcnaughton eileenmcnaughton Jan 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed now the field is set to export

}

//CRM-16116: get financial_type_id
if (!empty($query->_returnProperties['financial_type_id'])) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed now the field is set to export

@monishdeb
Copy link
Member

Jenkin test this please

@eileenmcnaughton eileenmcnaughton force-pushed the contribution_search branch 3 times, most recently from c582a7d to 38af28f Compare January 4, 2017 23:50
@eileenmcnaughton
Copy link
Contributor Author

Phew, I got it to pass. I do think handling oddness is better done near the 'edges' of the app - ie. forms & apis can handle field wierdness & pushing wierdness out from the BAO is generally good

@eileenmcnaughton eileenmcnaughton force-pushed the contribution_search branch 10 times, most recently from 7a18987 to bcd9856 Compare January 10, 2017 10:24
if (
(substr($name, 0, 12) == 'participant_') ||
(substr($name, 0, 7) == 'pledge_') ||
(substr($name, 0, 5) == 'case_') ||
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ie do not skip the loop for fields starting with contribution_ as many of them are in fact better dealt with in that context since they can be derived from metadata

@@ -680,15 +697,12 @@ public function selectClause($apiEntity = NULL) {
}
}

if (in_array($name, array('prefix_id', 'suffix_id', 'gender_id', 'communication_style_id'))) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consolidate this logic with general option-value pseudoconstant metadata based evaluation further down

if (
!empty($this->_paramLookup[$name])
|| !empty($this->_returnProperties[$name])
|| $this->pseudoConstantNameIsInReturnProperties($field)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$this->pseudoConstantNameIsInReturnProperties replaces the earlier in_array call

if ($fieldName == 'organization_name') {
$this->_select[$name] = "IF ( contact_a.contact_type = 'Individual', NULL, contact_a.organization_name ) as organization_name";
}
elseif ($fieldName != 'id') {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move all this stuff out of the 'contact-table-specific' & make it just 'metadata-based'

// If we have an option group defined then rather than joining the option value table in
// (which is an unindexed join) we render the option value on output.
// @todo - extend this to other pseudoconstants.
if ($this->pseudoConstantNameIsInReturnProperties($field)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By adding all option-value based fields (that get here) to the pseudoconstant array they become workable in the context of the $convertToPseudoFields fn

}
else {
$order = " ORDER BY contact_a.sort_name asc, contact_a.id";
}
}
if (!$order && empty($orderByArray)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactoring in this function ensures an array of order-by fields although it is still pretty funky. Previously the function did not iterate through all fields - just the first one in the string, to add special handling.

The handling we are adding is a way of avoiding joining the option_value table in when sorting by it. By rendering the values in php & using field($fieldName, 4,6,7) I was able to render the query without the join. Results in test were 10 times faster, in some cases much more.

@@ -825,15 +838,6 @@ public static function &exportableFields($checkPermission = TRUE) {
),
);

$contributionRecurId = array(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As part of this PR I declared this field as exportable so it no longer needs manual adding to exportable fields

$expFieldProduct = CRM_Contribute_DAO_Product::export();
$expFieldsContrib = CRM_Contribute_DAO_ContributionProduct::export();
$typeField = CRM_Financial_DAO_FinancialType::export();
$financialAccount = CRM_Financial_DAO_FinancialAccount::export();
$optionField = CRM_Core_OptionValue::getFields($mode = 'contribute');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as part of this PR I declared payment_instrument_id as exportable so it no longer needs manual adding

$expFieldProduct = CRM_Contribute_DAO_Product::export();
$expFieldsContrib = CRM_Contribute_DAO_ContributionProduct::export();
$typeField = CRM_Financial_DAO_FinancialType::export();
$financialAccount = CRM_Financial_DAO_FinancialAccount::export();
$optionField = CRM_Core_OptionValue::getFields($mode = 'contribute');
$contributionStatus = array(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now handled by the pseudoconstant - not needed as a manual add on

…ion search.

This involves setting payment instrument to exportable & remove hacks that were used in
place of doing that, and adding new logic to the order by to allow it to order without
joining the option value table (using the field() function).

I have observed one small regression which is the Qill showing 'Payment Method ID'
instead of payment method. I'm committed to fixing that but I would push
to merge this in advance of that because we are in the best place in the monthly
cycle to merge this and that is a very minor fallout.
@eileenmcnaughton eileenmcnaughton changed the title CRM-19815 Contribution search performance & CRM-19830 Contribution search de-crufting CRM-20199 Contribution search performance Mar 3, 2017
@eileenmcnaughton
Copy link
Contributor Author

@seamuslee001 this is the remaining work to remove the slow joins. I don't feel I can break it into any smaller chunks & I do think this is a good time of the cycle to merge it.

From the commit notes
This involves setting payment instrument to exportable & remove hacks that were used in
place of doing that, and adding new logic to the order by to allow it to order without
joining the option value table (using the field() function).

I have observed one small regression which is the Qill showing 'Payment Method ID'
instead of 'Payment Method'. I'm committed to fixing that but I would push
to merge this in advance of that because we are in the best place in the monthly
cycle to merge this and that is a very minor fallout.

@seamuslee001
Copy link
Contributor

@eileenmcnaughton i have tested this on export and search and all appears fine. I think we can address the Qill issue in another PR

@eileenmcnaughton eileenmcnaughton merged commit b733a3a into civicrm:master Mar 7, 2017
@eileenmcnaughton eileenmcnaughton deleted the contribution_search branch March 7, 2017 21:29
@seamuslee001
Copy link
Contributor

I did an export of a saved field mapping, There were no signs of fields missing and then on export fields were correctly populated as expected

@eileenmcnaughton
Copy link
Contributor Author

:-)

monishdeb pushed a commit to monishdeb/civicrm-core that referenced this pull request May 2, 2017
…arch

CRM-20199 Contribution search performance
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants