I’m using rt 4.4.2, about 2 mln tickets, about 10 mln attachments.
Was using it with mysql 5.6 and sphinx for fulltext searching. Now migrated to mysql 5.7 and builtin fulltext search.
Unfortunately the problem is that mysql fulltext search is way slower than sphinx. Waaaay slower.
Simple “test” entered in upper-right search box in rt makes rt do a sql query which takes 14 minutes to finish (below) and that’s not all, it only counts tickets.
Is such behaviour expected and what can be improved?
11:13:44 mysql{17}> explain SELECT COUNT(DISTINCT main.id) FROM Tickets main JOIN Queues Queues_4 ON ( Queues_4.id = main.Queue ) JOIN Transactions Transactions_1 ON ( Transactions_1.ObjectType = 'RT::Ticket' ) AND ( Transactions_1.ObjectId = main.id ) JOIN Attachments Attachments_2 ON ( Attachments_2.TransactionId = Transactions_1.id ) JOIN AttachmentsIndex AttachmentsIndex_3 ON ( AttachmentsIndex_3.id = Attachments_2.id ) WHERE (main.IsMerged IS NULL) AND (main.Status != 'deleted') AND (main.Type = 'ticket') AND ( ( ( MATCH(AttachmentsIndex_3.Content) AGAINST ('test' IN BOOLEAN MODE) AND AttachmentsIndex_3.Content IS NOT NULL ) ) AND ( ( ( Queues_4.Lifecycle = 'assets' AND ( main.Status = 'new' OR main.Status = 'allocated' OR main.Status = 'in-use' ) ) OR ( Queues_4.Lifecycle = 'default' AND ( main.Status = 'new' OR main.Status = 'open' OR main.Status = 'stalled' ) ) OR ( Queues_4.Lifecycle = 'approvals' AND ( main.Status = 'new' OR main.Status = 'open' OR main.Status = 'stalled' ) ) ) ) );
+----+-------------+--------------------+------------+----------+---------------------------------+------------------+---------+---------------------------------+------+----------+-----------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------------------+------------+----------+---------------------------------+------------------+---------+---------------------------------+------+----------+-----------------------------------+
| 1 | SIMPLE | AttachmentsIndex_3 | NULL | fulltext | PRIMARY,AttachmentsIndex | AttachmentsIndex | 0 | const | 1 | 100.00 | Using where; Ft_hints: no_ranking |
| 1 | SIMPLE | Attachments_2 | NULL | eq_ref | PRIMARY,Attachments2 | PRIMARY | 4 | rt3.AttachmentsIndex_3.id | 1 | 100.00 | Using where |
| 1 | SIMPLE | Transactions_1 | NULL | eq_ref | PRIMARY,Transactions1 | PRIMARY | 4 | rt3.Attachments_2.TransactionId | 1 | 50.00 | Using where |
| 1 | SIMPLE | main | NULL | eq_ref | PRIMARY,Tickets1,tickets_status | PRIMARY | 4 | rt3.Transactions_1.ObjectId | 1 | 5.00 | Using where |
| 1 | SIMPLE | Queues_4 | NULL | eq_ref | PRIMARY | PRIMARY | 4 | rt3.main.Queue | 1 | 27.10 | Using where |
+----+-------------+--------------------+------------+----------+---------------------------------+------------------+---------+---------------------------------+------+----------+-----------------------------------+
5 rows in set, 1 warning (0.07 sec)
Note (Code 1003): /* select#1 */ select count(distinct `rt3`.`main`.`id`) AS `COUNT(DISTINCT main.id)` from `rt3`.`Tickets` `main` join `rt3`.`Queues` `Queues_4` join `rt3`.`Transactions` `Transactions_1` join `rt3`.`Attachments` `Attachments_2` join `rt3`.`AttachmentsIndex` `AttachmentsIndex_3` where ((`rt3`.`Queues_4`.`id` = `rt3`.`main`.`Queue`) and (`rt3`.`main`.`id` = `rt3`.`Transactions_1`.`ObjectId`) and (`rt3`.`Transactions_1`.`ObjectType` = 'RT::Ticket') and (`rt3`.`Transactions_1`.`id` = `rt3`.`Attachments_2`.`TransactionId`) and (`rt3`.`main`.`Type` = 'ticket') and isnull(`rt3`.`main`.`IsMerged`) and (`rt3`.`main`.`Status` <> 'deleted') and (match `rt3`.`AttachmentsIndex_3`.`Content` against ('test' in boolean mode)) and (`rt3`.`AttachmentsIndex_3`.`Content` is not null) and (((`rt3`.`Queues_4`.`Lifecycle` = 'assets') and ((`rt3`.`main`.`Status` = 'new') or (`rt3`.`main`.`Status` = 'allocated') or (`rt3`.`main`.`Status` = 'in-use'))) or ((`rt3`.`Queues_4`.`Lifecycle` = 'default') and ((`rt3`.`main`.`Status` = 'new') or (`rt3`.`main`.`Status` = 'open') or (`rt3`.`main`.`Status` = 'stalled'))) or ((`rt3`.`Queues_4`.`Lifecycle` = 'approvals') and ((`rt3`.`main`.`Status` = 'new') or (`rt3`.`main`.`Status` = 'open') or (`rt3`.`main`.`Status` = 'stalled')))) and (`rt3`.`AttachmentsIndex_3`.`id` = `rt3`.`Attachments_2`.`id`))
11:13:45 mysql{18}> SELECT COUNT(DISTINCT main.id) FROM Tickets main JOIN Queues Queues_4 ON ( Queues_4.id = main.Queue ) JOIN Transactions Transactions_1 ON ( Transactions_1.ObjectType = 'RT::Ticket' ) AND ( Transactions_1.ObjectId = main.id ) JOIN Attachments Attachments_2 ON ( Attachments_2.TransactionId = Transactions_1.id ) JOIN AttachmentsIndex AttachmentsIndex_3 ON ( AttachmentsIndex_3.id = Attachments_2.id ) WHERE (main.IsMerged IS NULL) AND (main.Status != 'deleted') AND (main.Type = 'ticket') AND ( ( ( MATCH(AttachmentsIndex_3.Content) AGAINST ('test' IN BOOLEAN MODE) AND AttachmentsIndex_3.Content IS NOT NULL ) ) AND ( ( ( Queues_4.Lifecycle = 'assets' AND ( main.Status = 'new' OR main.Status = 'allocated' OR main.Status = 'in-use' ) ) OR ( Queues_4.Lifecycle = 'default' AND ( main.Status = 'new' OR main.Status = 'open' OR main.Status = 'stalled' ) ) OR ( Queues_4.Lifecycle = 'approvals' AND ( main.Status = 'new' OR main.Status = 'open' OR main.Status = 'stalled' ) ) ) ) );
+-------------------------+
| COUNT(DISTINCT main.id) |
+-------------------------+
| 71 |
+-------------------------+
1 row in set (14 min 11.72 sec)
11:28:04 mysql{19}> show create table AttachmentsIndex;
±-----------------±------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
±-----------------±------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| AttachmentsIndex | CREATE TABLE AttachmentsIndex
(
id
int(10) unsigned NOT NULL AUTO_INCREMENT,
Content
longtext,
PRIMARY KEY (id
),
FULLTEXT KEY AttachmentsIndex
(Content
)
) ENGINE=InnoDB AUTO_INCREMENT=10932372 DEFAULT CHARSET=utf8 |
±-----------------±------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
Now the fun part. It doesn’t seem fulltext part to be the issue because
11:37:52 mysql{37}> select count(DISTINCT id) FROM AttachmentsIndex WHERE match(AttachmentsIndex.`Content`) against ('test' in boolean mode);
+--------------------+
| count(DISTINCT id) |
+--------------------+
| 44114 |
+--------------------+
1 row in set (0.00 sec)
which is fast, so the problem lies in the rest of query.