1

I'm trying to optimize a MySQL query to speed up a Drupal view.

The tables are node, term_node and term_data. Node has about 500k rows, term_node about 800k and term_data about 300k.

Below the query:

    SELECT SQL_NO_CACHE DISTINCT(node.nid) AS nid
    FROM drupal_node node
    LEFT JOIN drupal_term_node term_node ON node.vid = term_node.vid
    LEFT JOIN drupal_term_data term_data ON term_node.tid = term_data.tid 
    WHERE (node.status = 1) AND (node.type in ('foto_foto')) 
    AND (
      (UPPER(term_data.name) LIKE UPPER('%Hanaa%') OR 
      UPPER(term_data.name) LIKE UPPER('%Bouchaib%')))
    GROUP BY nid
    LIMIT 0, 10;

This query takes about 11s to show up result. All the columns involved in the join are indexed, as well as term_data.name. node.vid, term_node.vid, term_node.tid and term_data.tid are int(10), term_data.name is a varchar(255).

The strange thing is, running the composing queries like:

SELECT SQL_NO_CACHE DISTINCT(term_node.tid)
FROM drupal_term_data term_data
LEFT JOIN drupal_term_node term_node ON term_node.tid = term_data.tid 
WHERE ((UPPER(term_data.name) LIKE UPPER('%Hanaa%') 
  OR UPPER(term_data.name) LIKE UPPER('%Bouchaib%')))
group by term_node.tid

and

SELECT SQL_NO_CACHE DISTINCT(node.nid) AS nid
FROM drupal_node node
LEFT JOIN drupal_term_node term_node ON node.vid = term_node.vid
WHERE (node.status = 1) AND (node.type in ('foto_foto')) 
GROUP BY nid

takes 0.23s for the firs and 0.12s for the last. So I'm expecting that the main query should run below 0.5s at least. It's like the optimizer had not ran on the query.

I've already ran ANALYZE and OPTIMIZE on the involved tables, and below is the result of EXPLAIN EXTENDED.

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: node
         type: range
possible_keys: vid,node_status_type,node_type
          key: node_status_type
      key_len: 102
          ref: NULL
         rows: 496217
     filtered: 100.00
        Extra: Using where
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: term_node
         type: ref
possible_keys: PRIMARY,vid
          key: vid
      key_len: 4
          ref: drupal_foto.node.vid
         rows: 7
     filtered: 100.00
        Extra: Using where
*************************** 3. row ***************************
           id: 1
  select_type: SIMPLE
        table: term_data
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: drupal_foto.term_node.tid
         rows: 1
     filtered: 100.00
        Extra: Using where
3 rows in set, 1 warning (0.00 sec)

The warning provide only a note level warning with code 1003.

4

1 回答 1

1

我想保证结果,但这里有一些可以尝试的方法:

  1. 因为查询在 term_data 上有一个比较过滤器,所以它不应该使用左连接。将左连接更改为内连接,因为它只会返回每个表中的两个表中的行,这将允许它首先通过术语表。

  2. Distinct 和 group by 是多余的。你不应该两者都需要。使用其中一种。

于 2012-06-16T23:35:00.910 回答