【问题标题】:MySQL simple but slow queryMySQL简单但缓慢的查询
【发布时间】:2021-12-15 03:40:13
【问题描述】:

我有一个表 TEST 有两列:

  • A varchar(250)
  • B tinyint(1)

该表有大约 400 万行。 A 包含 UTF8 字符串,B 只能是 0 或 1。

select count(1) from TEST 非常快(截至 MySQL Workbench 0,000 秒),但 select count(1) from TEST where B=1 大约需要 15 秒(在相当快的机器上,但在具有更多列的真实表上,对于这个问题应该无关紧要)。为 B 添加索引没有帮助 - 它仍然进行全表扫描。强制使用索引也无济于事。

存储引擎是 MyISAM,因为选择比插入/更新多得多,这可能是最好的选择。

如何加快查询速度?

【问题讨论】:

  • 如果性能受到这种影响,您可以考虑创建两个表:一个包含 b=1 的数据,另一个包含 b=0 的数据
  • 要试验的另一件事是您使用的引擎或索引的类型
  • 看看这里,如果索引没有帮助:stackoverflow.com/questions/1332624/…
  • InnoDB 和 MyISAM 之间也存在一些差异,后者通常更快但不太可靠。
  • 性能差异让我觉得你的表在 MyISAM 存储引擎中。是吗? MyISAM 表会保持持久的行数,因此查询 SELECT COUNT(*) 但只有在您的查询没有 WHERE 子句时才会加快速度。

标签: mysql indexing query-optimization


【解决方案1】:

很遗憾,您提出了一个令人讨厌的问题。没有什么魔法可以避免对您向我们展示的查询进行全表或全索引扫描。

编辑为什么简单地计算所有行的速度如此神奇? @BillKarwin 在他的评论中解释了这一点。您使用 MyISAM 存储引擎,它在其元数据中维护表的总行数,因此可以立即满足SELECT COUNT(*) FROM mytbl。添加 WHERE 子句后,它需要扫描所有行。

改善这种情况的建议包括使用某种汇总表。在其他一些 RDBMS SQL 中,这将被称为“物化视图”。例如,您可以创建此表:

CREATE TABLE tablecounts AS
SELECT COUNT(*) num, B
  FROM mytbl
 GROUP BY B;
ALTER TABLE tablecounts ADD UNIQUE INDEX B (B);

然后偶尔,可能来自重复出现的EVENT,您会更新它:

INSERT INTO tablecounts (num, B)
SELECT COUNT(*) num, B
  FROM mytbl
 GROUP BY B
    ON DUPLICATE KEY UPDATE SET num=VALUES(num);

然后您的应用可以通过SELECT num FROM tablecounts WHERE B=1 获取您在问题中提到的计数。

这不是一个完美的解决方案。当然,在您运行事件之前,该计数将变得陈旧,因为您的应用程序的其他部分在原始表中插入、更新或删除行。但是您很快就会得到一个大概的计数。

编辑如果您确实需要SELECT A FROM tbl WHERE B = 0 的详细结果,(B, A) 上的索引将通过仅扫描相关行来帮助您提高性能。如果您的大多数行都有B = 1,那么索引将通过为 MySql 提供一种完全忽略它们的方法来提供很大帮助。

【讨论】:

  • 谢谢。在实际应用中,我不需要计数,而是需要每个“A”的列表,其中“B”为 1(或 0,取决于情况/问题/应用程序)。 “B”的值每天变化几千行。维护两个表需要在许多应用程序中进行更改。 select A from TEST 非常快,也需要全表扫描。我清楚地知道添加where B=1 需要完整的索引扫描,但我不明白为什么这会慢得多。
【解决方案2】:

B-tree 索引对于高基数数据(即具有许多可能值的列,其中列中的数据是唯一的或几乎唯一的)最有效。 B 树索引在如此小的基数列上很糟糕。 创建位图索引。

位图索引是一种使用位图的特殊类型的数据库索引。这种技术适用于大型数据库,当列的基数较低且这些列在查询中最常使用时。

在您的情况下,B 列只有两个值,因此,低基数然后使用位图索引 用这个

CREATE BITMAP INDEX Index_Name ON TEST (B); 

【讨论】:

  • 据我所知,MySQL 不支持位图索引。
猜你喜欢
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-04
  • 1970-01-01
  • 2023-04-09
相关资源
最近更新 更多