假设我有以下模型
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/