简体   繁体   中英

How can I speed up my query?

How can I speed up this query? I use MySQL 5.1, table 'schedule' has ~ 900 K rows, and my query takes more than minute to run:

SELECT doc_code, `DATE`, time2, pat_code, STATUS, 
       copiedto1, copiedto2, copiedto3, copiedto4, copiedto5
FROM SCHEDULE
WHERE 1=1
AND STATUS IN (5,6,30)
AND (doc_code="K9" OR copiedto1="K9" OR copiedto2="K9" 
     OR copiedto3="K9" OR copiedto4="K9" OR copiedto5="K9")
AND `date` BETWEEN "2010/04/11" AND "2011/04/11"
AND pat_code > 0
ORDER BY `date`, doc_code, time2

I experimented to add different indexes, but my query doesn't want to use any of them. Any help would be appreciated.

I would change it into

SELECT s.* FROM (

  SELECT doc_code, `DATE`, time2, pat_code, STATUS, 
    copiedto1, copiedto2, copiedto3, copiedto4, copiedto5
  FROM SCHEDULE
  WHERE STATUS IN (5,6,30)
  AND `date` BETWEEN "2010/04/11" AND "2011/04/11"
  AND pat_code > 0
  ORDER BY `date`, doc_code, time2 ) s

WHERE (s.doc_code="K9" OR s.copiedto1="K9" OR s.copiedto2="K9" 
 OR s.copiedto3="K9" OR s.copiedto4="K9" OR s.copiedto5="K9")

Somewhere deep in the MySQL docs I remember reading something about OR 's killing the use of indexes.
I have a feeling that is going on.
If you first do a query with all AND 's to limit the number of records
and then do the select with OR 's I hope your query will run faster.

EDIT

http://forge.mysql.com/wiki/Top10SQLPerformanceTips Says: avoid using IN on indexed fields, it kills the performance.
Anyway, there are so many selection criteria, the query optimizer does not know where to begin.
Note that if the query optimizer 'thinks' that a criterium will use more than 25-50% (I forgot the exact percentage) of all fields, no index will be used.

Alternatively you might use

SELECT s.* FROM (

  SELECT doc_code, `DATE`, time2, pat_code, STATUS, 
    copiedto1, copiedto2, copiedto3, copiedto4, copiedto5
  FROM SCHEDULE
  USE INDEX (someIndex,someOtherIndex)   #<<<<-------------
  WHERE STATUS IN (5,6,30)
  AND `date` BETWEEN "2010/04/11" AND "2011/04/11"
  AND pat_code > 0
  ORDER BY `date`, doc_code, time2 ) s

WHERE (s.doc_code="K9" OR s.copiedto1="K9" OR s.copiedto2="K9" 
 OR s.copiedto3="K9" OR s.copiedto4="K9" OR s.copiedto5="K9")

The Index names or not equal to the fields name the index indexes.
You can find the index names in the create statement of the table, or the explain output that goes with the explain select .

Be carefull with forcing indexes though, measure before you finalize.
And remember a forced index query that runs fast now may run slow when the data in the table(s) changes.

This is pretty optimal, did you index all of the columns in your WHERE clause?

You could try doing query in stages by prepopulating a schedule_k9 table that only has K9 codes or one that only has pat_codes > 0.

SELECT doc_code, DATE, time2, pat_code, STATUS, copiedto1, copiedto2, copiedto3, copiedto4, copiedto5
FROM SCHEDULE
AND (doc_code="K9" OR copiedto1="K9" OR copiedto2="K9" OR copiedto3="K9" OR copiedto4="K9" OR copiedto5="K9")
AND pat_code > 0
AND `date` BETWEEN "2010/04/11" AND "2011/04/11"
AND STATUS IN (5,6,30)
ORDER BY `date`, doc_code, time2

I would have to see a sample of your table to improve the query even more (because there might be a lot of rows with a certain pattern etc...)

You can use a different type of mysql database. Some have better read speeds, other's have better write speeds. Here is a good article about mysql database types: here

I recommend you use the MyISAM table type. Unfortunately, it doesn't work with indexes. You can change your table's format by running this:

ALTER TABLE SCHEDUALE CHANGE TYPE=MyISAM

(日期,状态)的综合索引应使您的查询更加生动。

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