Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL 5亿行表在select查询中使用join_Mysql_Performance_Join_Indexing_Subquery - Fatal编程技术网

MySQL 5亿行表在select查询中使用join

MySQL 5亿行表在select查询中使用join,mysql,performance,join,indexing,subquery,Mysql,Performance,Join,Indexing,Subquery,我关心的是,一旦表被完全填充,下面的查询的性能。到目前为止,它还处于开发阶段,在虚拟数据方面表现良好 一旦完全填充,表adress_zoo将包含大约5亿条记录。adress_动物园表如下所示: CREATE TABLE `adress_zoo` ( `adress_id` int(11) NOT NULL, `zoo_id` int(11) NOT NULL, UNIQUE KEY `pk` (`adress_id`,`zoo_id`), KEY `adr

我关心的是,一旦表被完全填充,下面的查询的性能。到目前为止,它还处于开发阶段,在虚拟数据方面表现良好

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

  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;
  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
其他表每个最多包含500条记录

完整查询如下所示:

  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;
  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运行了查询,结果如下:


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

az.adress_id = 5
MySQL将表限制为只有adress_id匹配的记录,然后再将其与语句的其余部分连接,因此它将取决于您认为结果集可能有多大

顺便说一句,你有一个唯一地址id,动物园id和一个单独的索引。有什么特别的原因吗?因为MySQL也可以使用跨越键的第一部分来选择


同样重要的是使用EXPLAIN来理解MySQL将如何攻击您的查询并返回结果。另请参见:

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

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时,性能才可能提高。

离题:下次有人问起这个问题时,这个问题将是一个很好的参考资料。MySQL是否能在我巨大的100k记录表中运行良好?Hi@Jack,az.address_id=X将返回大约225条记录。好的,那么我可以删除第二个索引了,太好了!在这种情况下,innodb和myisam的情况如何?@user1441607好的,我已经更新了我的答案,添加了MySQL解释功能的链接。再次感谢!我用explain运行它,它似乎在可能的地方使用了键?在原始帖子中发布了一个屏幕截图。那么我想这可以工作了吗?我对MySQL在处理更大的表时的表现没有经验。。。最小磁盘大小和RAM是多少?也许已经问过另一个问题了?@user1441607调整MySQL服务器以处理这些数据大小完全是另一个话题;但最好随着数据的增长来处理这个问题。。。比如说,你把总数据的一半加进去,看看它是怎么回事;如果存在性能问题,您可以开始询问/查看:一旦所有数据都可用,我将测试此调整。感谢@danihp的支持。