首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用join的select查询中的MySQL 500万行表

使用join的select查询中的MySQL 500万行表
EN

Stack Overflow用户
提问于 2012-06-07 16:33:58
回答 2查看 4.5K关注 0票数 4

我关心的是,一旦表被完全填充,下面的查询的性能。到目前为止,它还在开发中,并且在使用虚拟数据时表现良好。

一旦完全填充,表"adress_zoo“将包含大约5亿条记录。"adress_zoo“表如下所示:

代码语言:javascript
复制
  CREATE TABLE `adress_zoo` 
     ( `adress_id` int(11) NOT NULL, `zoo_id` int(11) NOT NULL, 
     UNIQUE KEY `pk` (`adress_id`,`zoo_id`), 
     KEY `adress_id` (`adress_id`) ) 
     ENGINE=InnoDB DEFAULT CHARSET=latin1;

其他表中每个表最多包含500条记录。

完整的查询如下所示:

代码语言:javascript
复制
  SELECT a.* FROM jos_zoo_item AS a 
  JOIN jos_zoo_search_index AS zsi2 ON zsi2.item_id = a.id 
  WHERE a.id IN (   

     SELECT r.id FROM ( 

        SELECT zi.id AS id, Max(zi.priority) as prio 
        FROM jos_zoo_item AS zi 
        JOIN jos_zoo_search_index AS zsi ON zsi.item_id = zi.id 
        LEFT JOIN jos_zoo_tag AS zt ON zt.item_id = zi.id 
        JOIN jos_zoo_category_item AS zci ON zci.item_id = zi.id 
        **JOIN adress_zoo AS az ON az.zoo_id = zi.id** 

        WHERE 1=1 
        AND ( (zci.category_id != 0 AND ( zt.name != 'prolong' OR zt.name is NULL)) 
        OR (zci.category_id = 0 AND zt.name = 'prolong') ) 
        AND zi.type = 'telefoni' 
        AND zsi.element_id = '44d3b1fd-40f6-4fd7-9444-7e11643e2cef' 
        AND zsi.value = 'Small' 
        AND zci.category_id > 15 
        **AND az.adress_id = 5** 

        GROUP BY zci.category_id ) AS r 
  ) 

  AND a.application_id = 6 
  AND a.access IN (1,1) 
  AND a.state = 1 
  AND (a.publish_up = '0000-00-00 00:00:00' OR a.publish_up <= '2012-06-07 07:51:26') 
  AND (a.publish_down = '0000-00-00 00:00:00' OR a.publish_down >= '2012-06-07 07:51:26') 
  AND zsi2.element_id = '1c3cd26e-666d-4f8f-a465-b74fffb4cb14' 

  GROUP BY a.id 
  ORDER BY zsi2.value ASC

查询通常会返回大约25条记录。

根据您的经验,此查询的性能是否可接受(例如在3秒内响应)?我能做些什么来优化这一点?

根据@Jack的建议,我用EXPLAIN运行了查询,得到了如下结果:

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-07 16:41:31

这部分是一个重要的限制因素:

代码语言:javascript
复制
az.adress_id = 5

在将表与语句的其余部分连接之前,MySQL会将表限制为adress_id匹配的那些记录,因此这将取决于您认为结果集可能有多大。

顺便说一句,你有一个UNIQUE(adress_id, zoo_id)和一个单独的INDEX。有什么特别的原因吗?因为生成键的第一部分也可以被MySQL用来进行选择。

同样重要的是,使用EXPLAIN来理解MySQL将如何“攻击”您的查询并返回结果。另请参阅:http://dev.mysql.com/doc/refman/5.5/en/execution-plan-information.html

票数 2
EN

Stack Overflow用户

发布于 2012-06-07 16:51:43

为了避免子查询,您可以尝试将查询重写为:

代码语言:javascript
复制
SELECT a.* FROM jos_zoo_item AS a 
  JOIN jos_zoo_search_index AS zsi2 ON zsi2.item_id = a.id 
  INNER JOIN 
  (   
     SELECT ** distinct ** r.id FROM ( 

        SELECT zi.id AS id, Max(zi.priority) as prio 
        FROM jos_zoo_item AS zi 
        JOIN jos_zoo_search_index AS zsi ON zsi.item_id = zi.id 
        LEFT JOIN jos_zoo_tag AS zt ON zt.item_id = zi.id 
        JOIN jos_zoo_category_item AS zci ON zci.item_id = zi.id 
        **JOIN adress_zoo AS az ON az.zoo_id = zi.id** 

        WHERE 1=1 
        AND ( (zci.category_id != 0 AND ( zt.name != 'prolong' OR zt.name is NULL)) 
        OR (zci.category_id = 0 AND zt.name = 'prolong') ) 
        AND zi.type = 'telefoni' 
        AND zsi.element_id = '44d3b1fd-40f6-4fd7-9444-7e11643e2cef' 
        AND zsi.value = 'Small' 
        AND zci.category_id > 15 
        **AND az.adress_id = 5** 

        GROUP BY zci.category_id ) AS r 
  ) T
    on a.id = T.id
  where 
  AND a.application_id = 6 
  AND a.access IN (1,1) 
  AND a.state = 1 
  AND (a.publish_up = '0000-00-00 00:00:00' OR a.publish_up <= '2012-06-07 07:51:26') 
  AND (a.publish_down = '0000-00-00 00:00:00' OR a.publish_down >= '2012-06-07 07:51:26') 
  AND zsi2.element_id = '1c3cd26e-666d-4f8f-a465-b74fffb4cb14' 

  GROUP BY a.id 
  ORDER BY zsi2.value ASC

这种方法不会对每个候选行都执行子查询。只有在几毫秒内计算出T时,才能提高性能。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10928346

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档