Django MySQL - 在文本字段上设置索引
Django MySQL - Setting an index on a Textfield
我有一个要搜索的文章数据库。我一直在使用普通的 Django ORM 进行搜索,速度越来越慢,然后我对 Django 中的 Indexes
有了一些了解。我正在使用 MySQL
,我现在知道使用 MYSQL 我无法将索引字段放入 TextField
中,正如我所面对的 here in this stack question 所描述的那样。但是就我而言,我无法将其更改为 CharField
.
我正在阅读 MyQSL 文档,其中说明
MySQL cannot index LONGTEXT columns specified without a prefix length
on the key part, and prefix lengths are not permitted in functional
key parts.
因此我的理解是,由于 Django 中的 TextField
是 MYSQL 的 LONGTEXT
,我遇到了这个 Django-MySQL
package here 并认为如果我可以使用此包将 LONGTEXT
更改为 MEDIUMTEXT
,则可以使用它,这可能会得到解决。所以我更新的模型是这样做的
class MyModel(Model):
........
document = SizedTextField(size_class=3)
但是,我在应用 python manage.py makemigrations
时仍然看到同样的错误
django.db.utils.OperationalError: (1170, "BLOB/TEXT column 'document'
used in key specification without a key length")
我该如何解决这个问题?
所有这些相关类型 TEXT
、MEDIUMTEXT
和 LONGTEXT
都太大而无法在不指定前缀的情况下进行索引。索引前缀意味着只有字符串的前 N 个字符包含在索引中。像这样:
create table mytable (
t text,
index myidx (t(200))
);
本例中的前缀长度为200个字符。因此只有前 200 个字符包含在索引中。通常这足以提高性能,除非您有大量前 200 个字符相同的字符串。
MySQL 支持的最长前缀取决于存储引擎和行格式。 MySQL 的旧版本支持最多 768 字节的索引前缀,这意味着较少的字符数,具体取决于您是否使用 multi-byte 字符集,如 utf8 或 utf8mb4。 MySQL 的最新版本默认为更现代的行格式,支持最多 3072 字节的索引,同样减少了每个字符 3 或 4 个字节。
我不是 Django 的普通用户,所以我试图浏览 documentation 关于在模型 类 上定义索引的内容。但是经过几秒钟的阅读,我没有看到为长字符串列上的索引声明前缀的选项。
我认为您的选择是以下之一:
- 将该列更改为可以索引的较短的字符串列
- 使用 MySQL 客户端创建索引,不使用 Django 迁移
returning all the articles that contain a given word passed by the client. So would be something SELECT * from articles WHERE text CONTAINS searchword
添加
FULLTEXT(text)
并使用
WHERE MATCH(text) AGAINST("searchword")
或者
WHERE MATCH(text) AGAINST("+searchword" IN BOOLEAN MODE)
它将 运行 非常快。有一些注意事项——短词和“停止”词(如“the”)将被忽略。
(如果 DJango 无法做到这一点,那么您必须使用“原始 SQL”来完成。)
我有一个要搜索的文章数据库。我一直在使用普通的 Django ORM 进行搜索,速度越来越慢,然后我对 Django 中的 Indexes
有了一些了解。我正在使用 MySQL
,我现在知道使用 MYSQL 我无法将索引字段放入 TextField
中,正如我所面对的 here in this stack question 所描述的那样。但是就我而言,我无法将其更改为 CharField
.
我正在阅读 MyQSL 文档,其中说明
MySQL cannot index LONGTEXT columns specified without a prefix length on the key part, and prefix lengths are not permitted in functional key parts.
因此我的理解是,由于 Django 中的 TextField
是 MYSQL 的 LONGTEXT
,我遇到了这个 Django-MySQL
package here 并认为如果我可以使用此包将 LONGTEXT
更改为 MEDIUMTEXT
,则可以使用它,这可能会得到解决。所以我更新的模型是这样做的
class MyModel(Model):
........
document = SizedTextField(size_class=3)
但是,我在应用 python manage.py makemigrations
django.db.utils.OperationalError: (1170, "BLOB/TEXT column 'document' used in key specification without a key length")
我该如何解决这个问题?
所有这些相关类型 TEXT
、MEDIUMTEXT
和 LONGTEXT
都太大而无法在不指定前缀的情况下进行索引。索引前缀意味着只有字符串的前 N 个字符包含在索引中。像这样:
create table mytable (
t text,
index myidx (t(200))
);
本例中的前缀长度为200个字符。因此只有前 200 个字符包含在索引中。通常这足以提高性能,除非您有大量前 200 个字符相同的字符串。
MySQL 支持的最长前缀取决于存储引擎和行格式。 MySQL 的旧版本支持最多 768 字节的索引前缀,这意味着较少的字符数,具体取决于您是否使用 multi-byte 字符集,如 utf8 或 utf8mb4。 MySQL 的最新版本默认为更现代的行格式,支持最多 3072 字节的索引,同样减少了每个字符 3 或 4 个字节。
我不是 Django 的普通用户,所以我试图浏览 documentation 关于在模型 类 上定义索引的内容。但是经过几秒钟的阅读,我没有看到为长字符串列上的索引声明前缀的选项。
我认为您的选择是以下之一:
- 将该列更改为可以索引的较短的字符串列
- 使用 MySQL 客户端创建索引,不使用 Django 迁移
returning all the articles that contain a given word passed by the client. So would be something SELECT * from articles WHERE text CONTAINS searchword
添加
FULLTEXT(text)
并使用
WHERE MATCH(text) AGAINST("searchword")
或者
WHERE MATCH(text) AGAINST("+searchword" IN BOOLEAN MODE)
它将 运行 非常快。有一些注意事项——短词和“停止”词(如“the”)将被忽略。
(如果 DJango 无法做到这一点,那么您必须使用“原始 SQL”来完成。)