As a lot of other people, I also have a very slow query. I have read several posts about this issue, but none does solve my problem.
I heb two tabeles that need to be joined and searched in. 1 table is a orders table, and the other one is a accounts tabel. Both myisam
engine.
Table orders
:
id | account_id | remark | datetime
--------------------------------------------------
1 | 1 | hello | 2015-11-24 12:05:01
Table accounts
id | firstname | lastname | remark
------------------------------------
1 | John | Doe | hello
Both tabels have about 400.000
records an in real they have some more columns. There are also indexes on the id
and account_id
columns. The remark
columns are FULLTEXT
Now I want to perform a query to find all orders where the accounts.remark
or orders.remark
contains te text hello
.
First, I used a simple LIKE
statement for this query. Which was fast enough because there where not so much orders. U used this query:
SELECT SQL_NO_CACHE
orders.id AS orderID,
accounts.id AS accountID
FROM
orders
JOIN accounts ON orders.account_id = accounts.id
WHERE
orders.remark LIKE '%hello%' OR
accounts.remark LIKE '%hello%'
Runtime: 1.66 seconds
Now I wanted to speed this query up with MATCH AGAINST
, which should be a lot faster. So I changed the query above to:
SELECT SQL_NO_CACHE
orders.id AS orderID,
accounts.id AS accountID
FROM
orders
JOIN accounts ON orders.account_id = accounts.id
WHERE
MATCH(orders.remark) AGAINST('+hello' IN BOOLEAN MODE) OR
MATCH(account.remark) AGAINST('+hello' IN BOOLEAN MODE)
Runtime: 1.84 seconds
As you can see, the MATCH AGAINST
is even slower than the LIKE
version. When I remove one of the MATCH against lines in the WHERE clause, it's super fast!
SELECT SQL_NO_CACHE orders.id AS orderID, accounts.id AS accountID
FROM orders
JOIN accounts ON orders.account_id = accounts.id
WHERE MATCH(orders.remark) AGAINST('+hello' IN BOOLEAN MODE)
Runtime: 0.0018 seconds
So, the query get's very slow when matching over multiple tables. What can I do to speed this up?
Thanks in advance!
The usual approach with OR's is to convert them to a UNION (MySQL sometimes does it implicitly, but not in this case):
SELECT
orders.id AS orderID,
accounts.id AS accountID
FROM
orders
JOIN accounts ON orders.account_id = accounts.id
WHERE
MATCH(orders.remark) AGAINST('+hello' IN BOOLEAN MODE)
UNION
SELECT
orders.id AS orderID,
accounts.id AS accountID
FROM
orders
JOIN accounts ON orders.account_id = accounts.id
WHERE
MATCH(account.remark) AGAINST('+hello' IN BOOLEAN MODE)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.