Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
拉威尔';s";软删除;需要MySQL上的索引吗?_Mysql_Laravel_Optimization_Indexing_Eloquent - Fatal编程技术网

拉威尔';s";软删除;需要MySQL上的索引吗?

拉威尔';s";软删除;需要MySQL上的索引吗?,mysql,laravel,optimization,indexing,eloquent,Mysql,Laravel,Optimization,Indexing,Eloquent,如果我在Laravel4.2中使用软删除(数据库是mysql),那么每个有说服力的查询都有其中deleted\u at为NULL。在处的已删除\u上没有索引 在大桌子上会慢吗?(或者可能为空在不需要索引的情况下进行了优化) 我是否应该在列的deleted\u上添加索引 那么,Laravel的“soft_delete”列中的deleted_是否需要MySQL中的索引 澄清:Laravel在的deleted\u列中存储一个时间戳,以指示记录何时被软删除,而不是布尔值。位于的deleted\u列不

如果我在Laravel4.2中使用软删除(数据库是mysql),那么每个有说服力的查询都有
其中deleted\u at为NULL
。在处的
已删除\u上没有索引

  • 在大桌子上会慢吗?(或者可能
    为空
    在不需要索引的情况下进行了优化)
  • 我是否应该在
列的
deleted\u上添加索引

那么,Laravel的“soft_delete”
列中的
deleted_是否需要MySQL中的索引


澄清:Laravel在
deleted\u列中存储一个时间戳,以指示记录何时被软删除,而不是布尔值。

位于
deleted\u列不是一个好的索引候选。与注释相比,我将尝试更好地解释:索引只有在基数相对较高时才有用。基数是描述数据集中索引唯一性的数字。这意味着它是总记录数除以总唯一记录数

例如,主键的基数是1。每个记录都包含主键的唯一值。1也是最高的数字。你可以把它看作是“100%”。 但是,诸如deleted_at之类的列没有这样的值。Laravel对deleted_at所做的是检查它是否为空。这意味着它有两个可能的值。包含两个值的列具有极低的基数,随着记录数的增加而减少

您可以为这样的列编制索引,但它没有任何帮助。将会发生的是,它可能会减慢速度并占用空间


TL;DR:不,您不必为该列编制索引,索引将不会对性能产生有益影响。

我不知道@N.B.的上述内容为什么有这么多的上升票,在我的上下文中,我发现这完全不正确

我在一些keys表的时间戳处向deleted_添加了索引,并享受了一些从32秒下降到5.4毫秒以下的查询。这实际上取决于应用程序的性质

在我的场景中,我有3个带有软删除的表,一些简单的连接(都带有索引),但由于Laravel处理软删除的默认性质,我的查询受到了影响

我强烈建议为这些列编制索引,这样当记录数字上升时,你的应用程序就不会阻塞

简短的回答:也许吧

长答覆:

如果
deleted\u at
中几乎没有不同的值,MySQL将不会使用
索引(deleted\u at)

如果在
deleted\u at
中有不同的非空日期,MySQL将使用
索引(deleted\u at)

到目前为止,大多数讨论都没有考虑到这个单列索引的基数

注意:这与2值标志不同,例如
已删除
。在这样的数据库上使用单列索引是没有用的

更多讨论(从MySQL的角度)

现在,当您在模型上调用delete方法时,deleted_at列将设置为当前日期和时间。并且,当查询使用软删除的模型时,软删除的模型将自动从所有查询结果中排除

因此,我假设这发生在表定义中:

deleted_at  DATETIME  NULL  -- (or TIMESTAMP NULL)
并且该值被初始化(显式或隐式)为
NULL

案例1:大量新行,尚未“删除”:所有
deleted\u at
值均为
NULL
。在这种情况下,优化器将避开
索引(已删除)
,认为这没有帮助。事实上,使用索引会带来伤害,因为遍历整个索引和数据的成本会更高。忽略索引并简单地假设所有行都是
选中的候选行
,这样会更便宜

案例2:删除了几行(很多行中的几行):现在
deleted\u at
有多个值。尽管Laravel只关心
是否为空
vs
是否为非空
,但MySQL将其视为一个多值列。但是,由于测试的
为NULL
,并且大多数行仍然是
NULL
,因此优化器的反应与案例1相同

案例3:软删除的行比仍处于活动状态的行多得多:现在索引突然变得有用,因为表
中只有一小部分为NULL

案例2和案例3之间没有确切的界限。20%是一个方便的经验法则

现在,从执行的角度来看。

用于
删除位置的索引(已删除位置)
为空

  • 使用
    NULL
    向下钻取第一行的索引BTree
  • 扫描直到
    为空
    失败
  • 对于每个匹配的行,进入数据树以获取该行
  • 索引(已删除)
    未使用:

  • 扫描数据树(或使用其他索引)
  • 对于每个数据行,检查
    deleted\u at是否为NULL
    ,否则过滤掉该行
  • 综合指数:

    处有一个以
    deleted\u开头的“复合”(多列)索引可能非常有益。例如:

    INDEX(deleted_at, foo)
    
    WHERE deleted_at IS NULL
      AND foo BETWEEN 111 AND 222
    
    这很可能有效地使用索引,而不管表中已删除的
    百分比是多少\u at为NULL

  • 使用
    NULL
    foo>=111
    向下钻取第一行的索引BTree

  • 扫描直到
    为空
    foo它不需要索引。如果为空,则不会删除它。如果它有一个值,它将被删除。这意味着它有两个可能的值才能工作。具有两个可用值的列不是很好的索引候选列-它们的基数正在收敛到0。因此,删除的_at不需要索引。好的,谢谢。我认为几乎每个
    where
    子句都需要索引。如果您愿意,可以将您的评论作为答案发布。这是否意味着没有理由为布尔列编制索引,或者我误解了吗?@Cabloo-您没有