I am in a situation where I need to do a wildcard search. Full Text Index is no help as people are searching for part of a word and I can't strip the % from the start of the search to speed it up because they may be searching for the middle part.
There are two fields that need to be searched and a match in either should be returned. If I search for just one field it is very quick (there aren't many rows) but as soon as I search in both it's really slow.
I won't go into details, but to give an idea, when I have
... AND (T1.Field1 LIKE '%search%')
or
... AND (T2.Field1 LIKE '%search%')
It takes 0.0695 seconds
but when I do
... AND (T1.Field1 LIKE '%search%' OR T2.Field1 LIKE '%search%')
it takes 35 seconds
How can I optimize this and why does the OR increase the search time by so much?
The whole, unedited query as requested:
SELECT CDR.Status AS CDRStatus, D.VendorID, D.RevisionOfID, D.Revision, D.DocumentID, D.Title, D.OriginalFilename
FROM Documents AS D
LEFT JOIN CompanyDocumentReviews AS CDR ON CDR.DocumentID = D.DocumentID
LEFT JOIN Vendors AS V ON V.VendorID = D.VendorID
LEFT JOIN VendorAliases AS VA ON VA.Vendor1ID = V.VendorID AND VA.Vendor2ID != V.VendorID
LEFT JOIN Vendors AS V2 ON V2.VendorID = VA.Vendor2ID
WHERE D.Status != 'Deleted' AND (V1.VendorName LIKE '%search%' OR V2.VendorName LIKE '%search%')
The following recommendations will help you in your SQL tuning process.
You'll find 3 sections below:
ALTER TABLE `CompanyDocumentReviews` ADD INDEX `companydocumentrev_idx_documentid` (`DocumentID`);
ALTER TABLE `Documents` ADD INDEX `documents_idx_status` (`Status`);
ALTER TABLE `VendorAliases` ADD INDEX `vendoraliases_idx_vendor1id` (`Vendor1ID`);
ALTER TABLE `Vendors` ADD INDEX `vendors_idx_vendorid` (`VendorID`);
SELECT
CDR.Status AS CDRStatus,
D.VendorID,
D.RevisionOfID,
D.Revision,
D.DocumentID,
D.Title,
D.OriginalFilename
FROM
Documents AS D
LEFT JOIN
CompanyDocumentReviews AS CDR
ON CDR.DocumentID = D.DocumentID
LEFT JOIN
Vendors AS V
ON V.VendorID = D.VendorID
LEFT JOIN
VendorAliases AS VA
ON VA.Vendor1ID = V.VendorID
AND VA.Vendor2ID != V.VendorID
LEFT JOIN
Vendors AS V2
ON V2.VendorID = VA.Vendor2ID
WHERE
D.Status != 'Deleted'
AND (
V1.VendorName LIKE '%search%'
OR V2.VendorName LIKE '%search%'
)