2012-04-05 67 views
0
SELECT COUNT(`t`.id) 
FROM `product` `t` 
INNER JOIN `category` `c1` ON (`c1`.id ='15') 
LEFT JOIN `category` `c2` ON (`c2`.`parent_category_id` = '15') 
LEFT JOIN `category` `c3` ON (`c3`.`parent_category_id` = `c2`.`id`) 
LEFT JOIN `category` `c4` ON (`c4`.`parent_category_id` = `c3`.`id`) 
LEFT JOIN `category` `c5` ON (`c5`.`parent_category_id` = `c4`.`id`) 
LEFT JOIN `category` `c6` ON (`c6`.`parent_category_id` = `c5`.`id`) 
LEFT JOIN `category` `c7` ON (`c7`.`parent_category_id` = `c6`.`id`) 
WHERE 
t.category_id IN (c2.id,c3.id,c4.id,c5.id,c6.id,c7.id) 
AND (t.mod='Accepted') 

我有一个类别和产品表,类别表具有parent_category_id它引用相同的类别表,但表明该记录是子类别。如何改进此查询。发送数据太慢

SHOW PROFILE Result (ordered by duration) 

state duration (summed) in sec percentage 
Sending data 1.69029 99.96392 
freeing items 0.00015 0.00887 
statistics 0.00015 0.00887 
checking query cache for query 0.00009 0.00532 
init 0.00006 0.00355 
preparing 0.00003 0.00177 
checking permissions 0.00002 0.00118 
optimizing 0.00002 0.00118 
Opening tables 0.00002 0.00118 
System lock 0.00001 0.00059 
starting 0.00001 0.00059 
cleaning up 0.00001 0.00059 
Table lock 0.00001 0.00059 
end 0.00001 0.00059 
executing 0.00001 0.00059 
logging slow query 0.00001 0.00059 
Total 1.69090 100.00000 

Change Of STATUS VARIABLES Due To Execution Of Query 

variable value description 
Bytes_received 291 Bytes sent from the client to the server 
Bytes_sent 72 Bytes sent from the server to the client 
Com_select 1 Number of SELECT statements that have been executed 
Handler_read_key 133514 Number of requests to read a row based on a key 
Handler_read_next 133549 Number of index columns read with a range constraint or an index scan 
Key_read_requests 444695 Number of MyISAM key blocks read from cache 
Key_reads 234 Number of MyISAM key blocks that were read from disk. Indicates insufficient key cache size 
Key_write_requests 200 Number of MyISAM key blocks that were written to cache 
Key_writes 105 Number of MyISAM key blocks written to disk. Indicates insufficient key cache size 
Last_query_cost* 19845567 The total cost of this query as computed by the query optimizer 
Open_files* 1475 Number of files opened 
Qcache_free_memory* 149209104 Amount of Query cache free memory 
Qcache_hits 1520 Number of queries served directly by the Query Cache 
Qcache_inserts 190 Number of queries inserted into the Query Cache 
Qcache_not_cached* 2062788 Number of queries that were not cached by the Query Cache. They are not cacheable or was not cached due to the query_cache_type setting 
Questions 1 Number of statements executed by the server 
Table_locks_immediate 574 The number of requests for table locks that could be granted immediately 
Threads_cached 6 The number of threads in the thread cache 
Threads_running* 3 The number of threads that are not sleeping 
* Actual values after query execution (not changes due to query) 

EXPLAIN Result 

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE c1 const PRIMARY PRIMARY 4 const 1 Using index 
1 SIMPLE t ref category_id, mod mod 2 const 48 Using where 
1 SIMPLE c2 ref parent_category_id parent_category_id 5 const 18 
1 SIMPLE c3 ref parent_category_id parent_category_id 5 ucuzolur.c2.id 7 
1 SIMPLE c4 ref parent_category_id parent_category_id 5 ucuzolur.c3.id 7 
1 SIMPLE c5 ref parent_category_id parent_category_id 5 ucuzolur.c4.id 7 
1 SIMPLE c6 ref parent_category_id parent_category_id 5 ucuzolur.c5.id 7 
1 SIMPLE c7 ref parent_category_id parent_category_id 5 ucuzolur.c6.id 7 Using where 

你可以找到上面的配置文件。正如你看到的一切都很好,除了发送数据太慢。这个查询只是一个计数查询,为什么发送消耗太多时间,我该如何改进这个查询。我在类别表中有20000行。

+1

产品可以属于任何级别的类别,而不仅仅是叶级别?查询的目标是什么?要找出有多少产品属于类别15的类别结构? – 2012-04-05 07:28:35

+0

是的,除了主人以外,任何级别的产品都可以属于任何类别。查询的目标是找到类别15中的产品数量。想象一下:类别15(Master) - > subs - > subs_subs - > subs_subs_subs和产品可能位于subs或subs_subs或subs_subs_subs等等。 – 2012-04-05 12:51:37

回答

0

如果我理解正确的话你的目标,而不是创建整个品类结构,你可以尝试使用子查询向下钻取到找到属于所有产品到15类结构。

简化SQL:

SELECT COUNT(*) 
FROM 'product' 't' 
WHERE EXISTS (
    SELECT * 
    FROM 'category' 'c1' 
    WHERE 't'.'category_id' = 'c1'.'id' 
     AND ('c1'.'id' = 15 
     OR (EXISTS 
      (SELECT * 
      FROM 'category' 'c2' 
      WHERE 'c2'.'parent_category_id' = 'c1'.'id' 
       AND ('c2'.'id' = 15      
        OR (EXISTS .... 
         recursion here depending on 
         how many levels the categories can have) 
      ) 
     )) 
    ) 

这也可以表现得可怕,但它也可以更好地利用指标的可能,或减少点击次数的类别表。

尝试2

执行以下操作表现的更好吗?

SELECT COUNT(`t`.id) 
FROM `product` `t` 
    LEFT JOIN `category` `c2` ON (`c2`.`id` = t.category_id) 
    LEFT JOIN `category` `c3` ON (`c2`.`parent_category_id` = `c3`.`id`) 
    LEFT JOIN `category` `c4` ON (`c3`.`parent_category_id` = `c4`.`id`) 
    LEFT JOIN `category` `c5` ON (`c4`.`parent_category_id` = `c5`.`id`) 
    LEFT JOIN `category` `c6` ON (`c5`.`parent_category_id` = `c6`.`id`) 
    LEFT JOIN `category` `c7` ON (`c6`.`parent_category_id` = `c7`.`id`) 
WHERE (`c2`.`id` = 15 
    OR `c3`.`id` = 15 
    OR `c4`.`id` = 15 
    OR `c5`.`id` = 15 
    OR `c6`.`id` = 15 
    OR `c7`.`id` = 15) 
AND (t.mod='Accepted') 

确保parent_category具有当然的索引。

+0

'c2.id = 15'在这里是错误的,因为c1.id = 15已经存在。 t.category_id必须是c2.id.我纠正这一点,并尝试,但在第一个子查询mysql尝试使用所有行(20000),因为所有的where参数绑定到另一个表,我不能用where参数筛选行。 – 2012-04-05 12:22:59

+0

我有'c1'。'id'= 15或者EXISTS ....所以c1是15,或者它的父母是15,依此类推。但实际上缺少的是't'。'category_id'='c1'。'id'现在添加。 – 2012-04-05 12:26:51

+0

@OnurErenElibol新增了一个“尝试2”,让您检出。 – 2012-04-05 13:17:04