deleted_at 系统默认允许为 null 是否会有性能问题?

传说mysql里允许null的字段会忽略索引,那么也就不会去建索引。
那么问题来了,laravel里的deleted_at字段默认nullable(),查询的时候where xxx is null来查询的,如果数据量大了,会否有性能问题呢?
现实场景:一般系统deleted_at is not null的命中率不会高,估计低于5%

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 17

是这样的,deleted_at 字段本身没必要加索引的,按照优化规则,他只存在两种可能,所以没有加索引的必要,

关于sql优化中的允许为空的这一块(各种优化原则,不建议允许字段为空),其实说的不够全面,确实允许会对优化有影响,但是说的是索引的时候的影响,对于不考虑索引的字段,设置为允许为空是没什么影响的,

举个例子:对于 用户的生日 有的人没设置,有的人设置了,假如你的业务类型几乎都是以生日来排序的,这时候可能你需要加一个索引来提高查询效率,但是呢,你又想标记是否设置,所以你用了 null 来代表没设置否则有日期则为设置,那么这样即允许为空,又有索引,是会影响一些效率的,但是官方也说了,这个不作为主要优化手段,仅作为一个额外考虑的优化手段;

回过头来可以发现,其实delete_at 允许为空是不会影响什么的,本身也不会去为这个字段加索引

6年前 评论

deleted_at字段一般是自己设置的吧,created_at和updated_at才是laravel自动生成的吧

8年前 评论
Summer

嗯,听起来会有问题

8年前 评论

@程事不足 deleted_at是软删除的预设字段呀

8年前 评论

NUll并不影响索引使用的,请阅读http://dev.mysql.com/doc/refman/5.5/en/problems-with-null.html

 You can add an index on a column that can have NULL values if you are using the MyISAM, InnoDB, or MEMORY storage engine. Otherwise, you must declare an indexed column NOT NULL, and you cannot insert NULL into the column.
8年前 评论

The column deleted_at is not a good index candidate. I'll try to explain better compared to the comment: indexes are useful only when their cardinality is relatively high. Cardinality is a number that describes index uniqueness in the data-set. That means it's total number of records divided by total unique records.

For example, the cardinality of primary key is 1. Every record contains unique value for primary key. 1 is also, the highest number. You can consider it as a "100%".

But, a column such as deleted_at doesn't have such a value. What Laravel does with deleted_at is check whether it is or isn't null. That means it has two possible values. Columns that contain two values have extremely low cardinality which decreases as number of records goes up.

You can index such a column, but it won't be of any help. What will happen is that it could slow things down and take up space.

TL;DR: no, you don't have to index that column, index will have no beneficial impact on performance.

引自:http://stackoverflow.com/questions/2652506...

8年前 评论

自己写 trait SoftDelete

    public static function onlyTranshed()
    {
        $instance = new static;
        $column = $instance->getQualifiedDeletedAtColumn();

        return $instance->newQueryWithoutScope(new SoftDeleteScope())->where($column, '>', 0);
    }
7年前 评论

@12 null column 是不影响索引的使用,但是在null column 字段增加索引后的效果是什么样的,索引会发挥作用吗?

MySQL难以优化引用了可空列的查询,它会使索引、索引统计和值更加复杂。可空列需要更多的储存空间,还需要在MySQL内部进行特殊处理。当可空列被索引的时候,每条记录都需要一个额外的字节,还可能导致 MyISAM 中固定大小的索引(例如一个整数列上的索引)变成可变大小的索引。

7年前 评论

碰到了, 表示问题慢...

7年前 评论
nff93

这帖一年了,所以。。。结论到底是啥:joy:

7年前 评论

@nff93 按照大家给的资料, mysql 5.5+ 没影响

7年前 评论

是这样的,deleted_at 字段本身没必要加索引的,按照优化规则,他只存在两种可能,所以没有加索引的必要,

关于sql优化中的允许为空的这一块(各种优化原则,不建议允许字段为空),其实说的不够全面,确实允许会对优化有影响,但是说的是索引的时候的影响,对于不考虑索引的字段,设置为允许为空是没什么影响的,

举个例子:对于 用户的生日 有的人没设置,有的人设置了,假如你的业务类型几乎都是以生日来排序的,这时候可能你需要加一个索引来提高查询效率,但是呢,你又想标记是否设置,所以你用了 null 来代表没设置否则有日期则为设置,那么这样即允许为空,又有索引,是会影响一些效率的,但是官方也说了,这个不作为主要优化手段,仅作为一个额外考虑的优化手段;

回过头来可以发现,其实delete_at 允许为空是不会影响什么的,本身也不会去为这个字段加索引

6年前 评论

@dingdejing『只是针对索引字段』 很精辟呀

6年前 评论

@Summer @dingdejing
在这里延伸问一个问题:
deleted_at 默认值为null,这一点在给表创建唯一约束的时候有冲突,MySQLPgSQL(其他数据库暂不了解)中唯一约束允许多个null值存在。

使用软删除可能碰到的问题:如果表中有唯一约束的字段,比如User表的username,一行记录被软删除后,username已经被占用了,新的数据不能使用该username
而如果将deleted_at加入唯一约束,由于deleted_at默认值是nullMySQLPgSQL下唯一值是不校验NULL的,即唯一值列出现多个NULL值都不会报错。

这就有点尴尬了,如果一张表想加入唯一约束,就不能使用软删除功能,要不然就重写软删除逻辑,给deleted_at 设置一个默认值,但这应该有违Laravel设计的本意,Laravel内是不是提供其他解决方式?我不是很熟悉,所以在此请教 :pray:

5年前 评论
chenliq 4年前

@Herjew 你这种情况就是在校验username的时候也要包含deleted_at not null

5年前 评论

@5J 不是校验逻辑问题,是数据库的唯一约束功能 与 deleted_at 设定之间的冲突,我转而提了个问题 在这里

5年前 评论

@Herjew 如果不是业务上必要用唯一索引来做数据限制,性能上普通索引效率更好。

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!