【问题标题】:Optimize mysql with inner joins and where使用内部连接优化 mysql 和 where
【发布时间】:2016-04-27 19:48:59
【问题描述】:

我有疑问:

SELECT DISTINCT h.id,
                h.host
FROM pozycje p
INNER JOIN hosty h ON p.host_id = h.id
INNER JOIN keywordy k ON k.id=p.key_id
AND k.bing=0
WHERE h.archive_data_checked IS NULL LIMIT 20

存在某些行时速度很快,但如果不存在结果,则需要 2,3 sek 才能执行。我希望不到 1 秒。解释如下:

http://tinyurl.com/gogx42n

表 pozycje 有 30 000 000 行,hosty 有 4 000 000 行,keywordy 有 40 000 行。引擎 InnoDB,32GB RAM 服务器

当不存在结果时,我可以做哪些索引或改进来加快查询速度?

编辑:

显示表格关键字;

 CREATE TABLE `keywordy` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `main_kw` varchar(255) CHARACTER SET utf8 NOT NULL,
 `keyword` varchar(255) CHARACTER SET utf8 NOT NULL,
 `lang` varchar(10) CHARACTER SET utf8 NOT NULL,
 `searches` int(11) NOT NULL,
 `cpc` float NOT NULL,
 `competition` float NOT NULL,
 `currency` varchar(10) CHARACTER SET utf8 NOT NULL,
 `data` date DEFAULT NULL,
 `adwords` int(11) NOT NULL,
 `monitoring` tinyint(1) NOT NULL DEFAULT '0',
 `bing` tinyint(1) NOT NULL DEFAULT '0',
 PRIMARY KEY (`id`),
 UNIQUE KEY `keyword` (`keyword`,`lang`),
 KEY `id_bing` (`id`,`bing`)
) ENGINE=InnoDB AUTO_INCREMENT=38362 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

【问题讨论】:

  • 您最近是否对这些表中的每一个进行了分析表...。索引看起来不错,但是在 hosty 上的 archive_data_checked 上添加了一个索引,我希望它可以在加入 pozcyje 之前大大减少加入的行数然后到 keywordy
  • 显示创建表关键字;
  • 分析表从未完成。 SHOW CREATE TABLE 添加了关键字
  • 在安静时运行 ANALYZE TABLE 可能是值得的,因为它可能不会使用最新的统计数据来决定要使用哪些索引。并确保在 hosty 上的 archive_data_checked 上有一个索引

标签: mysql query-optimization mariadb


【解决方案1】:

请测试一下:

SELECT DISTINCT h.id,
                h.host              
FROM hosty h
WHERE
    EXISTS ( SELECT 1 FROM keywordy WHERE id=p.key_id AND bing=0)
  AND
    EXISTS ( SELECT 1 FROM pozycje WHERE host_id = h.id)
  AND h.archive_data_checked IS NULL LIMIT 20

【讨论】:

  • “where 子句”中的未知列“p.key_id”
  • @ekapek - 我删除了一个 EXISTS:SELECT DISTINCT h.id, h.host FROM hosty h INNER JOIN pozycje p ON p.host_id = h.id WHERE EXISTS (SELECT 1 FROM keywordy WHERE id= p.key_id AND bing=0) AND h.archive_data_checked IS NULL LIMIT 20
  • 时间和以前差不多 >2 sek
【解决方案2】:

我将首先提出以下问题。如果您在

上进行查询,哪个会具有较小的“集合”
select count(*) from KeyWordy where bing = 0
vs
select count(*) from hosty where archive_date_checked IS NULL

然后,我会尝试在知道较小集合的情况下优化查询,并将其作为索引的主要标准。如果 KeyWordy 更可能是较小的集合,我会为您的表提供以下索引

table       index
keywordy    (bing, id)   specifically NOT (id, bing) as bing FIRST is optimized for where or JOIN clause
pozycje     (key_id, host_id )
hosty       (archive_data_checked, id, host)

SELECT DISTINCT 
      h.id,
      h.host
   FROM 
      Keywordy k
         JOIN pozycje p
            ON k.id = p.key_id
            JOIN hosty h
               on archive_data_checked IS NULL
              AND p.host_id = h.id
   WHERE
      k.bing = 0
   LIMIT 
      20

如果 HOSTY 表基于 archive_data_checked IS NULL 会更小,我提供以下

table       index
pozycje     (host_id, key_id )    reversed of other option

SELECT DISTINCT 
      h.id,
      h.host
   FROM 
      hosty h 
         JOIN pozycje p
            ON h.id = p.host_id
            JOIN Keywordy k
               on k.bing = 0
              AND p.key_id = k.id
   WHERE 
      h.archive_data_checked IS NULL 
   LIMIT 
      20

一个 FINAL 选项,可能是添加关键字“STRAIGHT_JOIN”,例如

select STRAIGHT_JOIN DISTINCT ... rest of query

如果它对您有用,它会提供哪些时间改进。

【讨论】:

  • 经过测试的解决方案 1,最佳时间是 2,1 sek MySQL 不使用 archive_data_checked_id_host 索引 - 强制使用此索引查询需要 10sek+
猜你喜欢
  • 2011-12-02
  • 2017-06-24
  • 2012-03-16
  • 1970-01-01
  • 1970-01-01
  • 2016-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多