Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.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查询优化:带计数子查询的选择速度非常慢_Mysql_Sql_Query Optimization - Fatal编程技术网

mysql查询优化:带计数子查询的选择速度非常慢

mysql查询优化:带计数子查询的选择速度非常慢,mysql,sql,query-optimization,Mysql,Sql,Query Optimization,我有以下表格: mysql> show create table rsspodcastitems \G *************************** 1. row *************************** Table: rsspodcastitems Create Table: CREATE TABLE `rsspodcastitems` ( `id` char(20) NOT NULL, `description` mediumtext,

我有以下表格:

mysql> show create table rsspodcastitems \G
*************************** 1. row ***************************
       Table: rsspodcastitems
Create Table: CREATE TABLE `rsspodcastitems` (
  `id` char(20) NOT NULL,
  `description` mediumtext,
  `duration` int(11) default NULL,
  `enclosure` mediumtext NOT NULL,
  `guid` varchar(300) NOT NULL,
  `indexed` datetime NOT NULL,
  `published` datetime default NULL,
  `subtitle` varchar(255) default NULL,
  `summary` mediumtext,
  `title` varchar(255) NOT NULL,
  `podcast_id` char(20) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `podcast_id` (`podcast_id`,`guid`),
  UNIQUE KEY `UKfb6nlyxvxf3i2ibwd8jx6k025` (`podcast_id`,`guid`),
  KEY `IDXkcqf7wi47t3epqxlh34538k7c` (`indexed`),
  KEY `IDXt2ofice5w51uun6w80g8ou7hc` (`podcast_id`,`published`),
  KEY `IDXfb6nlyxvxf3i2ibwd8jx6k025` (`podcast_id`,`guid`),
  KEY `published` (`published`),
  FULLTEXT KEY `title` (`title`),
  FULLTEXT KEY `summary` (`summary`),
  FULLTEXT KEY `subtitle` (`subtitle`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> show create table station_cache \G
*************************** 1. row ***************************
       Table: station_cache
Create Table: CREATE TABLE `station_cache` (
  `Station_id` char(36) NOT NULL,
  `item_id` char(20) NOT NULL,
  `item_type` int(11) NOT NULL,
  `podcast_id` char(20) NOT NULL,
  `published` datetime NOT NULL,
  KEY `Station_id` (`Station_id`,`published`),
  KEY `IDX12n81jv8irarbtp8h2hl6k4q3` (`Station_id`,`published`),
  KEY `item_id` (`item_id`,`item_type`),
  KEY `IDXqw9yqpavo9fcduereqqij4c80` (`item_id`,`item_type`),
  KEY `podcast_id` (`podcast_id`,`published`),
  KEY `IDXkp2ehbpmu41u1vhwt7qdl2fuf` (`podcast_id`,`published`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
第二个表的“item_id”列是指前者的“id”列(两者之间没有外键,因为关系是多态的,即第二个表可能引用的实体不在第一个表中,但在其他类似但不同的表中)

我正在尝试获取一个查询,该查询列出第一个表中最近的项,而第二个表中没有任何对应项。到目前为止,我发现性能最高的查询是:

select i.*, 
       (select count(station_id) 
         from station_cache 
          where item_id =  i.id) as stations 
 from rsspodcastitems i 
  having stations = 0 
   order by published desc
我还考虑过在不存在(…)的地方使用
子查询来执行限制,但这实际上比我上面提到的要慢。但这仍然需要相当长的时间才能完成。MySQL的查询计划似乎没有使用可用的索引:

+----+--------------------+---------------+------+---------------+------+---------+------+--------+----------------+
| id | select_type        | table         | type | possible_keys | key  | key_len | ref  | rows   | Extra          |
+----+--------------------+---------------+------+---------------+------+---------+------+--------+----------------+
|  1 | PRIMARY            | i             | ALL  | NULL          | NULL | NULL    | NULL | 106978 | Using filesort |
|  2 | DEPENDENT SUBQUERY | station_cache | ALL  | NULL          | NULL | NULL    | NULL |  44227 | Using where    |
+----+--------------------+---------------+------+---------------+------+---------+------+--------+----------------+
请注意,查询的两部分都没有使用
,而它应该能够使用主表中的
键已发布(已发布)
,以及子查询的
键项id(项id,项类型)


有什么建议可以让我在不等待几分钟的情况下获得适当的结果吗?

您可能希望检测并删除表中的冗余索引。查看这两个表的创建表信息,可以帮助您发现几个,包括
podcast\u id
guid
Station\u id
已发布的
项目id
项目类型
podcast\u id
已发布
可能还有更多。

我认为最快的查询应该是:

select i.*
from rsspodcastitems i 
where not exists (select 1
                  from station_cache sc
                  where sc.item_id = i.id
                 )
order by published desc;
这将利用
station\u缓存(item\u id)
上的索引,或许还可以利用
rsspodcastitems(published,id)

如果查询返回大量行,那么查询可能会更快。查询的措辞允许在
rsspodcastitems(published)
上建立索引,以避免文件排序。如果删除
分组依据
,则
存在
版本应更快

我应该注意到,我喜欢你使用having
子句。在过去遇到这种情况时,我使用了一个子查询:

select i.*, 
       (select count(station_id) 
         from station_cache 
          where item_id =  i.id) as stations 
from (select i.*
      from rsspodcastitems i 
      order by published desc
     ) i
where not exists (select 1
                  from station_cache sc
                  where sc.item_id = i.id
                 );
这允许一个索引进行排序

我希望您的方法有一点变化:

select i.*, 
       (exists (select 1 
                from station_cache sc
                where sc.item_id = i.id
               )
       ) as has_station 
from rsspodcastitems i 
having has_station = 0 
order by published desc;

这应该比使用
count()

的版本稍微快一点。我最终的解决方案是删除全文索引,并使用外部生成的索引表(通过迭代文本中的单词、过滤停止词和应用词干算法生成)来允许搜索。我不知道为什么全文索引会导致性能问题,但它们似乎会降低每个涉及表的查询的速度,即使它们没有被使用。

我注意到了这些问题。我还注意到,每次我重新启动web服务器时,hibernate都会重新创建它们,所以我放弃了删除它们的尝试……很有趣。“explain select…”提供的分析表明,您的查询应该更快(因为它使用子查询索引,而我的子查询不使用索引),但在实际使用中,它仍然更慢。