【问题标题】:How to avoid full table scan in mysql query with large output如何避免在具有大输出的mysql查询中进行全表扫描
【发布时间】:2022-01-13 21:21:07
【问题描述】:

我有非常大的表(超过 1000 万行)和返回大量数据的查询。我需要让它跑得更快。因此,我尝试添加覆盖索引(由 where 子句和 id 的值组成),但即使在对 USE INDEX 进行索引提示之后,仍然存在全表扫描。然后我在选择中剪切值(仅留下 id)并添加覆盖索引,但仍然存在全表扫描。如何避免全表扫描? 我尝试为所有列创建覆盖索引并进行全索引扫描,但该解决方案比全表扫描更长。 还有其他优化方法吗?我尝试了索引,尝试删除不存在(更改为 id not in),这一切都让时间变得更糟。 我有 Table1.id、table1.UserId、Table2.Id 的索引。

select t.id, t.Date, t.Added , t.NewId, t.UserId, t.Lost 
from Table1 t
where t.Added=0 and t.Lost=0 
   and not exists (select 1
                    from table2 n 
                    where n.Id=t.id and n.userId=t.userId and n.Added=0 and n.Del=0); 

【问题讨论】:

  • 您在table2 上尝试过这个复合索引吗? INDEX(Del, Added, userId, Id)id the PRIMARY KEY` 在每个表中吗?

标签: mysql optimization indexing full-table-scan


【解决方案1】:

几乎不可能告诉你任何事情,因为你没有展示你的表是如何定义的,包括你使用的实际索引。

但您可能会尝试的一件事是用 LEFT OUTER JOIN 替换您的依赖子查询,MySQL 引擎可能能够做到这一点更好的优化:

select t.id, t.Date, t.Added , t.NewId, t.UserId, t.Lost 
from Table1 t
left join table2 n on n.Id=t.id and n.userId=t.userId and n.Added=0 and n.Del=0
where t.Added=0 and t.Lost=0 and n.Id is null;
  1. 在以下列上创建多列索引:Table1.id、Table1.userId、Table1.Added、Table1.Lost、Table1.NewId
  2. 如果以下列尚未建立索引,则在它们上创建索引:Table2.Id、Table2.userId、table2.Added、Table2.Del

【讨论】:

  • 我已经有 Table1.id、Table1.userId 和 Table2.Id 的索引。有了他们并使用左连接,可以将时间缩短为 2(非常感谢)。所以我不需要覆盖索引?但是索引其他列会有好处吗?
  • 如果您在您从 Table1 中选择的所有列上创建了一个多列索引,那将是一个覆盖索引并且还包括列我在列列表的第 1 项中提到,我认为只需要扫描索引而不是实际行。然后确保在我在第二个列表中提到的列上有索引。
  • 我已经更新了答案以使其更加明确。
猜你喜欢
  • 2021-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-07
  • 1970-01-01
  • 1970-01-01
  • 2017-10-22
  • 1970-01-01
相关资源
最近更新 更多