mysql - Django startswith vs endswith 在 MySQL 上的性能

标签 mysql django indexing django-models django-queryset

假设我有以下模型

class Person(models.Model):
    name = models.CharField(max_length=20, primary_key=True)

所以我会在数据库中有像这样的对象

Person.objects.create(name='alex white')
Person.objects.create(name='alex chen')
Person.objects.create(name='tony white')

然后我可以查询所有名字为 alex 的用户或者姓氏是 white通过执行以下操作

all_alex = Person.objects.filter(name__startswith='alex')
all_white = Person.objects.filter(name__endswith='white')

我不知道 Django 如何在幕后实现它,但我猜它是用 SQL LIKE 'alex%' 实现的。或 LIKE '%white'

但是,由于根据 MySQL index documentation ,因为只有在 % 时才能使用主键索引(例如,与全表扫描相反)出现在 LIKE 的末尾查询。

这是否意味着,随着数据库的增长,startswith将是可行的 - 而 endswith不会,因为它会求助于全表扫描?

我是正确的还是哪里出错了?请记住,这些不是事实,而只是我根据一般假设做出的推论 - 因此我要求确认。

最佳答案

假设您想要 AND - 那只是 Alex White 而不是 Alex Chen托尼·怀特, ...

更好的(假设有一个以 name 开头的索引)是

SELECT ...
    WHERE name LIKE 'Alex%White'

如果 Django 不能生成它,那么它就会妨碍 MySQL 的高效使用。

此构造将扫描所有以 alex 开头的名称,进一步过滤表达式的其余部分。

如果您确实想要OR(和 3 个名称),那么您将陷入困境

SELECT ...
    WHERE ( name LIKE 'Alex%'
         OR name LIKE '%White' )

除了扫描所有的名字别无选择。

在某些情况下,也许这个 FULLTEXT 会更好:

FULLTEXT(name)  -- This index is needed for the following:

SELECT ...
    WHERE MATCH(name) AGAINST('Alex White' IN BOOLEAN MODE)  -- for OR

SELECT ...
    WHERE MATCH(name) AGAINST('+Alex +White' IN BOOLEAN MODE)  -- for AND

(同样,我不知道 Django 的功能。)

关于mysql - Django startswith vs endswith 在 MySQL 上的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40827780/

相关文章:

textarea标签内的Django模板换行符

django - 如何正确安装 django-nose?

php - 调整 "NOW()"时区

mysql - 将表字段 1 更新为字段 2,其中字段 1 等于字段 3

使用属性过滤 Django-sphinx 结果?

Mysql多重索引对单个查询不起作用(Group By + RangeWhere条件)

python - 根据 Pandas 中另一列的索引从一列获取数据

performance - 高效查询PostgreSQL中包含数组列的条件表

PHP 表单不向 MySQL 发送数据

php - 非常高 'Waiting (TTFB)' 时间 - Opencart 3.0.2.0