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行。
答案 0 :(得分:0)
确保您加入的列上有索引,并尝试不使用“WHERE IN”。
@Quassnoi对他的答案提出了非常好的观点: SQL JOIN vs IN performance?
答案 1 :(得分: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当然有索引。