【问题标题】:In MySQL 8, is there an index I can create to speed up LIKE searches?在 MySQL 8 中,我可以创建一个索引来加速 LIKE 搜索吗?
【发布时间】:2020-12-04 09:19:29
【问题描述】:

我正在使用 Django 3、Python 3.8 和 MySql 8。我有以下 Django 模型,我在其中创建基于部分名称的搜索...

class Coop(models.Model):
    objects = CoopManager()
    name = models.CharField(max_length=250, null=False)
    types = models.ManyToManyField(CoopType, blank=False)
    addresses = models.ManyToManyField(Address)
    enabled = models.BooleanField(default=True, null=False)
    phone = models.ForeignKey(ContactMethod, on_delete=models.CASCADE, null=True, related_name='contact_phone')
    email = models.ForeignKey(ContactMethod, on_delete=models.CASCADE, null=True, related_name='contact_email')
    web_site = models.TextField()

...

# Look up coops by a partial name (case insensitive)
def find_by_name(self, partial_name):
    queryset = Coop.objects.filter(name__icontains=partial_name, enabled=True)
    print(queryset.query)
    return queryset

上面的代码产生了这个查询...

SELECT `directory_coop`.`id`, `directory_coop`.`name`, `directory_coop`.`enabled`, `directory_coop`.`phone_id`, `directory_coop`.`email_id`, `directory_coop`.`web_site` FROM `directory_coop` WHERE (`directory_coop`.`enabled` = True AND `directory_coop`.`name` LIKE %Credit%)

下面是 Django 迁移生成的表。我可以进行任何类型的索引或其他调整来加快这些查询 - 具体来说,“name LIKE %Credit%”部分?

CREATE TABLE `directory_coop` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(250) COLLATE utf8mb4_unicode_ci NOT NULL,
  `enabled` tinyint(1) NOT NULL,
  `phone_id` int DEFAULT NULL,
  `email_id` int DEFAULT NULL,
  `web_site` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`id`),
  KEY `directory_coop_email_id_c20abcd2` (`email_id`),
  KEY `directory_coop_phone_id_4c7e2178` (`phone_id`),
  CONSTRAINT `directory_coop_email_id_c20abcd2_fk_directory_contactmethod_id` FOREIGN KEY (`email_id`) REFERENCES `directory_contactmethod` (`id`),
  CONSTRAINT `directory_coop_phone_id_4c7e2178_fk_directory_contactmethod_id` FOREIGN KEY (`phone_id`) REFERENCES `directory_contactmethod` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=993 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

【问题讨论】:

  • 您可以通过在特定字段中添加pk=True 来设置模型中的主键。你也可以设置db_index(在这里阅读docs.djangoproject.com/en/3.1/ref/models/fields/#db-index),但总的来说,如果你知道自己在做什么并且ORM不能满足你的需求,我建议跳过ORM并编写原始查询......跨度>
  • @ArakkalAbu,接受的答案是“全文搜索可用于 MySQL 5.6+ 的 InnoDB 表。”但它并没有提供很多其他细节。你说的是这个吗?
  • 在这方面,我想指出两点,1)。新的 MySQL 版本支持full-text search,可以在您的情况下使用custom database function。 2.) 索引不会加速 LIKE 查询,它解决了您提出的确切问题。
  • 那么你是说即使我将列类型更改为“FULLTEXTSEARCH”,也不会加快 LIKE 查询的速度?

标签: python-3.x django indexing sql-like mysql-8.0


【解决方案1】:

使用like 运算符的常规索引不会加速 SQL 查询,但您可以在 FULLTEXT indexed column 上使用 MySQL's full-text search functions

为此,您需要索引 namemanually using SQL query,因为 Django 还没有该功能。

name列启用FULLTEXT索引后,您可以使用the search lookupDjango Func(...)表达式查询数据。


参考文献

  1. Creating FULLTEXT Indexes for Full-Text Search
  2. MySQL 8.0 Full-Text Search Functions
  3. Django MySQL full text search
  4. What is Full Text Search vs LIKE
  5. How to speed up SELECT .. LIKE queries in MySQL on multiple columns?

【讨论】:

  • 您引用的 Django Func 链接列出了 'field_lower=Lower('field')',但这只会匹配精确的字符串,对吗?它不会像以前的 LIKE '%str%' 那样匹配部分?
  • @Dave Func(...) 用于调用任何有效的数据库函数,Django 不提供该函数。我不明白这里的“部分”是什么意思?
猜你喜欢
  • 2015-07-22
  • 2013-07-27
  • 1970-01-01
  • 2021-08-17
  • 2021-01-20
  • 2011-07-12
  • 1970-01-01
  • 1970-01-01
  • 2015-01-11
相关资源
最近更新 更多