连接上的mysql索引用法

643ylb08  于 2021-06-21  发布在  Mysql
关注(0)|答案(1)|浏览(416)

我知道有几个问题与此类似,但我发现这些问题与我的问题没有直接关系。
一些初步的背景:我有一个事实表,称为ft\u booking,有大约10毫米的记录。我有一个称为dm_date的维度,有大约11k条记录,即日期。这些表通常通过外键进行关联。表中有3个日期外键,一个用于登机,一个用于预订,另一个用于取消。所有列都有非常相同的定义,并且每个列的不同记录的数量是相似的(每个列中的不同值从2.5k到3k不等)。
我来了:

EXPLAIN SELECT

* 

FROM dw.ft_booking b
LEFT JOIN dw.dm_date db ON db.sk_date = b.fk_date_booking
WHERE date (db.date) = '2018-05-05'


如您所见,索引正在表booking中使用,查询运行得非常快,尽管在我的过滤器中,我使用的是date()函数。为简洁起见,我将使用fk\u date\u boarding列声明同样的情况。但是,看看这个:

EXPLAIN SELECT

* 

FROM dw.ft_booking b
LEFT JOIN dw.dm_date db ON db.sk_date = b.fk_date_cancellation
WHERE date (db.date) = '2018-05-05';


出于某种神秘的原因,计划者选择不使用索引。现在,我了解到在列上使用某些函数会迫使数据库执行完整的表扫描,以便能够在列上应用该函数,从而绕过索引。但是,在这种情况下,函数不在实际的外键列上,这是booking表中应该进行查找的地方。
如果我删除date()函数,索引将按预期用于这些列中的任何一列。有人可能会说,“那么,为什么不去掉date()函数呢?”——我使用metabase,一个允许用户使用图形界面来构建查询的界面,而不需要知道mysql,该工具当前的一个限制是,在构建非直接用mysql编写的查询时,它总是使用date()函数—因此,我无法删除正在运行的查询中的函数。
实际问题:为什么mysql在前两种情况下使用index,而在后两种情况下不使用index,因为所有列的不同值的数量几乎相同,而且除了名称之外,它们都有确切的smae定义?我是不是漏了什么?
编辑:这里是每个表的create语句。还有一些,但是我们只需要这里的表ft\u booking和dm\u date(文件的前两个表)。

zlwx9yxi

zlwx9yxi1#

你在“隐藏” date 在函数调用中”。如果 db.date 被宣布为 DATE ,那么

date (db.date) = '2018-05-05'

可以很简单

db.date = '2018-05-05'

如果 db.date 被宣布为 DATETIME ,然后更改为

db.date >= '2018-05-05'
    AND db.date  < '2018-05-05' + INTERVAL 1 DAY

无论是哪种情况,都要确保 db.date .
如果说“我有一个称为dm\u date的维度”,您的意思是您构建了一个只包含日期的维度表,那么您就是 JOINing 在主桌上放一些 id , ... 说白了,别那么做!不要规范化“连续”的事物,例如 DATE , DATETIME , FLOAT ,或其他数值。
如果您需要进一步讨论,请提供 SHOW CREATE TABLE 有关表格(请使用文本,而不是屏幕截图。)
为什么?
简单的答案是,优化器不知道如何分解任何函数。也许可以;也许应该。但事实并非如此。也许答案包括不想看到函数结果将如何被使用。。。与…相比 DATE ? 反对 DATETIME ? 被用作字符串?其他的?
不过,我认为真正的性能杀手是 dm_date 而不是索引和使用主表中的日期。
此外,主表比它需要的大! fk_date_booking 是4字节 INT SIGNED 而不是3字节 DATE .

相关问题