user3259992
user3259992

Reputation: 53

How to optimize mysql query?

This query is taking long time to execute. Anybody tell me how to optimize this query?

SELECT distinct(node.nid) AS nid ,
       CAST((LENGTH(node_data_field_pdfextract.field_pdfextract_value) - LENGTH(REPLACE(LOWER(node_data_field_pdfextract.field_pdfextract_value) , 'test', ''))) / LENGTH('test') AS UNSIGNED ) AS name_match ,
       node.title AS node_title,
       node_data_field_first_name.field_cj_article_author_name_value,
       node_data_field_first_name.field_first_name_value
FROM ram_node node
LEFT JOIN
  (SELECT td.tid,
          tn.vid AS revision
   FROM ram_term_data td
   INNER JOIN ram_term_node tn ON tn.tid = td.tid
   WHERE td.vid IN (12,
                    15,
                    14)) term_data_node ON node.vid = term_data_node.revision
LEFT JOIN ram_content_type_cj_article node_data_field_first_name ON node.vid = node_data_field_first_name.vid
LEFT JOIN ram_node_revisions node_revisions ON node.vid = node_revisions.vid
LEFT JOIN ram_term_node term_node ON node.vid = term_node.vid
LEFT JOIN ram_term_data term_data ON term_node.tid = term_data.tid
LEFT JOIN ram_content_field_pdfextract node_data_field_pdfextract ON node.vid = node_data_field_pdfextract.vid
LEFT JOIN ram_uc_products uc_products ON node.vid = uc_products.vid
WHERE (node.status = 1)
  AND (node.type IN ('cj_article'))
  AND ((UPPER(node_revisions.body) LIKE UPPER('%test%'))
       OR UPPER(node_data_field_pdfextract.field_pdfextract_value) LIKE UPPER('%test%'))
  AND (UPPER(node.title) LIKE UPPER('%%'))
ORDER BY name_match DESC;

Upvotes: 1

Views: 110

Answers (1)

Paul Maxwell
Paul Maxwell

Reputation: 35553

stage 1, remove all unnecessary joins. You are only using node and node_data_field_pdfextract in the select clause and the where clause.

stage 2, because you are referencing node_data_field_pdfextract in the where clause there isn't any point in using a left join on that table, use the more efficient INNER JOIN instead.

step 3, is distinct really required? it requires a lot of resources. if it isn't required get rid of it.

step 4, are all the uses of UPPER() required in the where clause? when applying functions to a field use of any index on that field is denied causes full table scans in most cases. Do away with those functions if this is at all possible. Consider storing the data in UPPER and indexing that perhaps.

for steps 1,2 & 3:

SELECT
      node.nid                                                                                                            AS nid
    , CAST((LENGTH(node_data_field_pdfextract.field_pdfextract_value) 
     - LENGTH(REPLACE(LOWER(node_data_field_pdfextract.field_pdfextract_value), 'test', ''))) / LENGTH('test') AS UNSIGNED) AS name_match
    , node.title                                                                                                            AS node_title
    , node_data_field_first_name.field_cj_article_author_name_value
    , node_data_field_first_name.field_first_name_value
FROM ram_node node
      INNER JOIN ram_content_field_pdfextract node_data_field_pdfextract
                  ON node.vid = node_data_field_pdfextract.vid
WHERE node.status = 1
      AND node.type IN ('cj_article')
      AND (
             UPPER(node_revisions.body) LIKE UPPER('%test%')
            OR 
             UPPER(node_data_field_pdfextract.field_pdfextract_value) LIKE UPPER('%test%')
           )
      AND UPPER(node.title) LIKE UPPER('%%')
ORDER BY
      name_match DESC;

By the way SELECT distinct(node.nid)

those parentheses are just ignored by the parser. Distinct is NOT a function.

DISTINCT qualifies SELECT (i.e. think of "SELECT DISTINCT" as a pair of words) plus:

SELECT DISTINCT is a "row operator"; it is performed over all parts of the row and certainly not just the field you placed in parentheses.

I suggest you stop using those parentheses because it is making you think it does things which it simply will not do.

Upvotes: 1

Related Questions