简体   繁体   中英

MYSQL Query, Optimize LIKE and NOT IN

I have a query I need to run which is currently running extremely slow. The table I am working with has nearly 1 million records.

What I need to do is search for items with a LIKE name : Example "SELECT name, other, stuff FROM my_table WHERE name LIKE '%some_name%'"

In addition it has to be able to exclude certain terms with wildcards from the search results so it turns into something like this :

SELECT name, other, stuff 
FROM my_table 
WHERE name LIKE '%some_name%' 
AND name NOT IN (SELECT name FROM my_table WHERE name LIKE '%term1%' AND name LIKE '%term2%' AND name LIKE '%term3%')

To top things off, I have two INNER JOINs and I have to execute it in PHP. I have indexes on the table for relevant columns. It is on a server that is fast for pretty much every other query I can throw at it.

The question is, is there a different method I could be using to do this type of query thats is quick?

UPDATES

This is my actual query after adding in FULLTEXT index to the chem table and trying the match function instead. NOTE : I don't have control over table/column names. I know they dont look nice.

CREATE FULLTEXT INDEX name_index ON chems (name)

SELECT f.name fname, f.state, f.city, f.id fid,
cl.alt_facilid_ida, cl.alt_facili_idb,
c.ave, c.name, c.id chem_id,
cc.first_name, cc.last_name, cc.id cid, cc.phone_work
FROM facilities f
INNER JOIN facilitlt_chemicals_c cl ON (f.id = cl.alt_facilid485ilities_ida)
INNER JOIN chems c ON (cl.alt_facili3998emicals_idb = c.id)
LEFT OUTER JOIN facilities_contacts_c con ON (f.id = con.alt_facili_ida)
LEFT OUTER JOIN contacts cc ON (con.alt_facili_idb = cc.id)
WHERE match(c.name) against ('+lead -gas' IN BOOLEAN MODE)

That is just an example of a simple query. The actual terms could be numerous.

You want to implement MySQL's full text capabilities on the columns you're searching. Read more about it here .

Moreover, you probably want to do a boolean search:

select
    t1.name,
    t1.stuff
from
    my_table t1
where
    match(t1.name) against ('+some_name -term1 -term2 -term3' in boolean mode)

I would suggest to use external Full-text engine like Lucene or Sphinx. Especially if you plan to fire search queries against relatively big datasets.

In Sphinx case you can use SELECT-like syntax called SphinxQL which will do exactly as required:

SELECT * FROM <sphinx_index_name> WHERE MATCH('some_name -term1 -term2 -term3');

as described in http://sphinxsearch.com/docs/current.html#extended-syntax (NOT operator in your case). Plus you could enable morphology support which might be helpful as well.

You can combine MySQL and Sphinx queries with http://sphinxsearch.com/docs/current.html#sphinxse

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM