The problem with an OR condition is that the DB has to evaluate everything.
So, as it must parse the whole tables, it skips the indexes, and goes in a table scan.
As you have noticed, table scan are baaaaaaad.
Try to use an union rather than OR:
Code:
SELECT *
FROM(
SELECT appr_agland.Account, appr_agland.Acres, appr_resident.Account, appr_resident.YearBuilt
FROM appr_agland
LEFT JOIN appr_resident
ON appr_agland.Account=appr_resident.Account
WHERE MATCH (appr_agland.Account) AGAINST('$search')
UNION
SELECT appr_agland.Account, appr_agland.Acres, appr_resident.Account, appr_resident.YearBuilt
FROM appr_agland
LEFT JOIN appr_resident
ON appr_agland.Account=appr_resident.Account
WHERE MATCH (appr_resident.Account) AGAINST('$search')
) AS global
and extend the union with your tables as needed.
Each query in the UNION is evaluated independently, and their results are associated.
For that, each query must have the same number of columns in the select, and they must be of the same types.
You cannot have a query that have a varchar filed in the second position, and a timestamp in another and use a union between the two.
A simple "UNION" merge duplicates. If you want to have them, use a "UNION ALL" keyword.
Just a side node, some DB transform implicitly an LEFT JOIN into a LEFT OUTER JOIN, which can be very costly if the table grows.
I personally likes to specify that I want an INNER JOIN or an LEFT INNER JOIN or a LEFT OUTER JOIN.
At least I'm certain of what the db does.
Now, about the query up there, it's surely is not optimal, but it should be much better than using OR in the WHERE clause.
Give it a try...