【问题标题】:SQL: Optimize the query on large table with indexingSQL:使用索引优化对大表的查询
【发布时间】:2019-10-01 16:17:19
【问题描述】:

例如,我有下表:

table Product
------------
id
category_id 
processed
product_name

此表在列 id category_idprocessed(category_id, proccessed) 上有索引。该表的统计数据为:

select count(*) from Product; -- 50M records
select count(*) from Product where category_id=10; -- 1M records
select count(*) from Product where processed=1; -- 30M records

我想查询的最简单的查询是:(必须选择*)。

select * from Product 
where category_id=10 and processed=1 
order by id ASC LIMIT 100  

上面的无限制查询只有大约10,000条记录。

我想多次调用上述查询。每次我出去时,我都会将字段 processed 更新为 0。(因此它不会出现在下一个查询中)。当我在真实数据上进行测试时,有时优化器会尝试使用id作为key,因此花费了很多时间。

如何优化上述查询(一般而言)

P/S:为了避免混淆,我知道最好的索引应该是(类别、已处理、id)。但我无法更改索引。我的问题只是与优化查询有关。

谢谢

【问题讨论】:

  • 这个链接对索引提示真的很有帮助:mysql.rjweb.org/doc.php/index_cookbook_mysql 和 Gordon 的回答应该会给你最好的性能
  • 试试force index (processed)
  • 为了防止 MySQL 使用前导列为 id 的索引(即使用索引来避免“使用文件排序”操作),我们将 ORDER BY 子句更改为对表达式进行操作,而不是一个光秃秃的柱子。例如,如果id 是数字类型,我们可以使用ORDER BY id + 42 ASC。如果id 数据类型为日期、日期时间等,我们可以使用ORDER BY id + INTERVAL 42 DAY ASC。如果是字符类型,我们可以ORDER BY CONCAT('42',id) ASC
  • @spencer7593 感谢您提供这些信息。你能帮我解释一下为什么吗?是否有任何消息来源提到这一点。谢谢。
  • dev.mysql.com/doc/refman/8.0/en/select-optimization.html 特别是关于使用索引来满足 ORDER BY 的部分。当一个索引不能被使用时,有一个 Using filesort 操作。这在大型设备上可能会很昂贵。如果优化器使用前导列为id 的索引,那么它必须使用该索引来满足 ORDER BY ... 优化器必须认为按顺序检查每一行会更快,并确定它是否满足 WHERE 条件,找到 100 行后停止。 MySQL 不能使用索引来满足 ORDER BY 表达式。

标签: mysql sql mariadb


【解决方案1】:

对于这个查询:

select *
from Product
where category_id = 10 and processed = 1
order by id asc
limit 100;

最佳索引位于product(category_id, processed, id)。这是一个具有三部分键的单个索引,键按此顺序排列。

【讨论】:

  • 最好的,应该是。但是这张表很大,我无法更改索引。
  • @TrầnKimDự 如果您无法更改索引,那么您希望如何提高性能?
  • 我只是猜测,有某种方式,例如,分成 2 个查询,然后再次加入。如果我的猜测不正确,我深表歉意。
  • 有时优化器猜错了。他们使用id 作为索引。 (原因显然是因为我使用select *,但我无法更改)
【解决方案2】:

鉴于您拥有INDEX(category_id, processed),因此仅拥有INDEX(category_id) 几乎没有任何优势。所以DROP后者。

可能具有将优化器推向复合INDEX(category_id, processed)的有益副作用,这至少对查询“更好”。

不接触索引,您可以使用FORCE INDEX 提及复合索引的名称。但我不推荐它。 “今天可能会有所帮助,但明天会在数据更改后造成伤害。”

为什么说“但我不能更改索引。”?较新版本的 MySQL/MariaDB 使 ADD/DROP INDEX 比旧版本快得多。另外,pt-online-schema-change 提供了一种快速的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-05
    • 1970-01-01
    • 2011-12-31
    • 2012-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-19
    相关资源
    最近更新 更多