【问题标题】:aggregation queries in mysql with indexing and partitonmysql中带有索引和分区的聚合查询
【发布时间】:2020-12-27 18:59:29
【问题描述】:

到目前为止,我有一个大约有 200 万行的表。该表将继续增长,因为每个月将添加大约 0.5-06 百万行。

例如,我有如下查询:

select `importer_name`, ROUND(SUM(total_value_usd_exchange), 2) AS top15_usd
from   `importer_bills`
WHERE  year(bill_of_entry_date)=2020
AND 
Month(bill_of_entry_date)=3
group  by `importer_name`
order  by ROUND(SUM(total_value_usd_exchange), 2) desc limit 15 offset 0;

此查询当前需要9.98 秒才能执行。

跟随explain的输出:

1   SIMPLE  importer_bills  p0  ref idx_importer_bills_upwork_09,idx_importer_bills_year_month  idx_importer_bills_year_month   5   const,const 1106762 100.00  Using index condition; Using temporary; Using filesort
  1. idx_importer_bills_upwork_09 是importer_name 列上的索引。

  2. idx_importer_bills_year_month 是 bill_of_entry_yearbill_of_entry_month 的索引

我还添加了bill_of_entry_year的分区。

我尝试将上述查询替换为:

select `importer_name`, ROUND(SUM(total_value_usd_exchange), 2) AS top15_usd
from   `importer_bills`
WHERE  
bill_of_entry_year=2020
AND
bill_of_entry_month = 3
group  by `importer_name`
order  by ROUND(SUM(total_value_usd_exchange), 2) desc limit 15 offset 0;

这花费了9.01 秒。

explain的输出:

1   SIMPLE  importer_bills  p0  ref idx_importer_bills_upwork_09,idx_importer_bills_year_month  idx_importer_bills_year_month   5   const,const 1106762 100.00  Using index condition; Using temporary; Using filesort

如何有一堆这样的查询基于比仅年份和月份更多的过滤器?有时只使用一年过滤器。仅 2M 行 10 秒是不可接受的。我该如何优化呢?

where 子句中使用的列总是会根据用户对过滤器的选择而改变,但可以考虑强制使用 YEAR 过滤器。也可能是一个月(但最好不要这样做)

【问题讨论】:

    标签: mysql indexing relational-database partitioning database-partitioning


    【解决方案1】:

    我首先将where 子句中的日期过滤器重写为 SARGable 表达式:

    where bill_of_entry_date >= '2020-03-01' and bill_of_entry_date < '2020-04-01'
    

    这不会在日期列上使用日期函数,因此它可能会利用索引。然后,我会推荐以下索引:

    importer_bills(bill_of_entry_year, importer_name, total_value_usd_exchange)
    

    第一个索引列匹配where 谓词;以下列匹配group by 列,第三列是聚合列。不能保证 MySQL 会使用索引中的所有列,但是,如果 where 谓词具有足够的选择性,您应该仍然会看到性能优势。

    【讨论】:

    • where 子句中使用的列总是会根据用户选择的过滤器而改变,但可以考虑强制使用 YEAR 过滤器。也可能是一个月(但最好不要这样做)
    • @Simrankaur:您想要生成与用户输入相对应的文字日期,而不是在表格列上使用日期函数 - 如示例所示。否则查询效率低。
    • 对。我确实在桌子上有 b​​ill_of_entry_year , bill_of_entry_month 列以及我尝试使用并在问题中添加结果
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-21
    • 1970-01-01
    • 2018-04-09
    • 2011-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多