-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Description
We are experiencing long delays when selecting contacts to create new shares for. Searching takes about 20-30 seconds after the user has finished typing.
Our installation runs Nextcloud 16 with PHP 7.3 and MariaDB 10.3. We have 22k rows in oc_cards and 140k rows in oc_cards_properties.
Testing the queries created by OCA\DAV\CardDAV\CardDavBackend->search manually showed that each one takes about 4 seconds to complete, like this one:
SELECT `c`.`carddata`, `c`.`uri` FROM `oc_cards` `c` WHERE `c`.`id` IN (SELECT DISTINCT `cp`.`cardid` FROM `oc_cards_properties` `cp` WHERE (`cp`.`addressbookid` = 'XXX') AND ((`cp`.`name` = 'EMAIL') OR (`cp`.`name` = 'FN')) AND (`cp`.`value` COLLATE utf8mb4_general_ci LIKE '%pattern%'));
As LIKE statements can only make use of indizes if they do not start with a % wildcard, each query has to to a full table scan.
I tried to compare this with a FTS index on the oc_cards_properties.value field and using MATCH ... AGAINST ... instead of LIKE:
CREATE FULLTEXT INDEX oc_cards_properties_name_FTS ON nextcloud.oc_cards_properties (value);
SELECT `c`.`carddata`, `c`.`uri` FROM `oc_cards` `c` WHERE `c`.`id` IN (SELECT DISTINCT `cp`.`cardid` FROM `oc_cards_properties` `cp` WHERE (`cp`.`addressbookid` = 'XXX') AND ((`cp`.`name` = 'EMAIL') OR (`cp`.`name` = 'FN')) AND (MATCH(`cp`.`value`) AGAINST('pattern')));
Now the query took only ~220ms instead of 4000ms.
Would you consider switching to Full-Text-Search, at least for MySQL/MariaDB? Large installations like ours would certainly benefit from it. Doctrine support for MATCH is available in https://github.com/beberlei/DoctrineExtensions.