dev/core#6679 - Full-text search: let each MATCH drive its own FULLTEXT index - #36451
Open
dstorozhuk wants to merge 1 commit into
Open
dev/core#6679 - Full-text search: let each MATCH drive its own FULLTEXT index#36451dstorozhuk wants to merge 1 commit into
dstorozhuk wants to merge 1 commit into
Conversation
|
🤖 Thank you for contributing to CiviCRM! ❤️ We will need to test and review this PR. 👷 Introduction for new contributors...
PR commands & links...
|
|
The issue associated with the Pull Request can be viewed at https://lab.civicrm.org/dev/core/-/issues/6679 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Fixes dev/core#6679.
The first query in
CRM_Contact_Form_Search_Custom_FullText_Activity::prepareQueries()puts its twomatchText()clauses on either side of anOR. Withenable_innodb_ftson those expand toMATCH … AGAINST, and MySQL cannot use a FULLTEXT index as an access path for aMATCHthat is only one side of anOR— so it scans every non-deleted activity instead. That one query is ~88% of the full-text search screen, which is why enabling InnoDB full-text search does not make the screen faster.Splitting the two branches into a
UNIONlets each drive its own index. Measured 44× overall across ten search terms on a database with ~76k contacts and ~169k activities, with byte-identical results.Before
EXPLAIN— the FULLTEXT index is inpossible_keysand is not chosen:Slow log, one search:
Query_time: 2.963 Rows_examined: 2735023.After
The two branches become a
UNION, andcivicrm_option_group/civicrm_option_valuemove into the e-mail branch — the only place they are used — joined on the activity type instead of cross-joined into every row.Slow log for the same search after the change:
Query_time: 0.009.Per search term, same box and data, best of 2:
End to end, the whole full-text search screen:
Technical Details
The
LEFT JOINs tocivicrm_email,civicrm_option_groupandcivicrm_option_valuebecomeINNER JOINs in the e-mail branch. That is equivalent because those tables are only referenced by that branch's own predicate: in the original query a row could only satisfy the secondORbranch whene.emailmatched andca.activity_type_id = ov.valueandov.name IN ('Inbound Email','Email'), all of which require the joins to have produced a row. The contact branch never referenced them at all.Results were verified as full result sets, not counts: ten search terms compared on both row count and
MD5(GROUP_CONCAT(id ORDER BY id))between the old and new query. All ten identical, including result sets of 11,168 and 16,621 ids.Comments
Only the
Activitypartial query has this shape.Contact,Case,Contribution,MembershipandParticipanteach have a singlematchText()call and already use their index — no change needed there.Measured on CiviCRM 6.16.5 with MySQL 8.0, PHP 8.3, Drupal 10.6; the query is unchanged in
master, which is what this PR targets.