-
-
Notifications
You must be signed in to change notification settings - Fork 824
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
Speed boost for civicrm/ajax/checkemail #15824
Conversation
(Standard links)
|
@colemanw do you have any thoughts - it looks a bit hairy from a maintenance point of view since we haven't hacked in ft indexes into any other random places & it's not using an api |
This is a critical UX improvement for us so I think it's worth maintaining? Our fundraising team won't have to waste extra hours when sending emails :) I'd be happy to do more work on incorporating use of ft indexes into APIs or whatever else is helpful. |
Would it be worth adding a comment in the code linking back to this PR? I think the PR description by mfb is very helpful, but just from reading the code, I would be wondering why it's written that way. |
I can give this a spin. |
Note that the way we fixed the query in quicksearch was to use a UNION rather than an OR - which was not dependent on mysql settings |
OK I have another idea for this - instead of using the fulltext index, we could do UNION query on sort_name and first_name, and only search from the start of the name column i.e. |
@mfb the quicksearch code respects the setting for adding a wildcard at the beginning - I'm sure you have that setting disabled, as we do, but it would be consistent to respect it. |
I tried this out and found that when a user types the first letter say "m", many hundreds of thousands of results are returned by each subquery of the UNION - this data has to be loaded into a temporary table before it's eventually limited to 20 rows. It can take 25 seconds for the query to run, which is not great for live typing. The simple way to avoid this is to add a LIMIT clause to each subquery, so there is no part of the query returning huge amounts of data. Then the UNION query is lightning fast. But, do you think we could drop support for the Because it would be tricky to use LIMIT clauses on the subqueries and make the offset work as expected. Maybe we can also drop support for the noemail $_GET parameter? I don't see evidence of that string anywhere in Civi. |
So this is only called from one place
And I can't see how noemail or offset could be set from there |
4e7e2ff
to
b813e2c
Compare
Ok it's now working nice'n'fast with UNION query. I added support for searching by first_name, but it's not required if we want to limit the search to sort_name and email. |
I don't have a strong feeling on first name - this looks generally good to me & if @jitendrapurohit (or maybe @pfigel given it touches on performance & security) are able to review I'd be happy to merge it |
For a future PR - maybe we could allow users to search for contacts by typing "{first_name} {last_name}" in addition to "{last_name}, {first name}" ? |
I applied this PR and looked into the queries that are formed when I enter first 4 letters of my name(jite) in the I executed these queries on a database having >516k rows in Before the patch -
After -
which is ~1 sec more than the previous query. If I remove the clause of
I tried this for 4-5 times and the result was similar in all the cases. Not sure I was able to test the improved performance on the results here. When viewing the loading of emails on UI, I think it was slightly faster before the patch. @mfb Do you think I've missed anything here OR pls let me know how you see different behavior on your side. |
@jitendrapurohit you need to turn off the setting for adding a wildcard at the beginning to see the huge speed boost. (I would say that setting should be the default, but that's for another PR.) |
Test 2 with Query formed -
That is surely a huge improvement noticed here related to fetching the emails when the wildcard setting is off. Also tested some basic functionalities after the PR and looks fine to me. If we're ok to ignore the wildcard performance, I think it is good to merge 👍 |
I think maybe I should back out the search by first name to avoid that slowdown with the include wildcard setting turned on? This would need an additional index to make faster.. so could be worked on in a separate PR. |
@mfb thanks for your work on this! In general, fields like |
Yes I don't think I should add this feature here (but I would like to work on this in the future, since typical email UIs do allow users to do a quick search/entry via "{first_name} {last_name}") |
* Remove support for unused $_GET params. * Build a UNION query on email and sort_name. * Respect includeWildCardInName setting.
c9e6bc2
to
3c0dc53
Compare
@colemanw display_name isn't useful for searching because it looks like |
This was pretty hard to read because it included a big cleanup in the same PR as the main change. However, I worked through it & I agree the removed code is not used and once I'd resolved that it got pretty readable :-) It looks like you backed out changing fields (per discussed above) and went for respecting the DB setting - which is also respected in quicksearch so users of DBs with that enabled will be used to it. There are more questions here - should the function exist at all , the ones above etc. But I think this change is appropriate to merge as it improves code quality and fixes the performance issue in a way that is consistent with quick search |
Overview
This PR provides some speed boosts for the civicrm/ajax/checkemail endpoint (used, for example, when adding a cc: email address to an email message).
Before
Whatever text was entered will be searched anywhere in the email or name columns via LIKE query. This is slow because no index is used. When adding a cc: email address, it can take a minute for ajax search results to show up on a large Civi database (millions of contacts). In addition, for each letter the user types, an additional long-running query is spawned (their old ajax requests continue to run in the background on the server).
After