我将 Django 与 PostgreSQL 数据库结合使用,并且我有一个模型将文件路径(特别是 S3 文件路径)存储在 CharField 中,如下所示:
class File(models.Model):
file_path = models.CharField(max_length=255)
我经常使用 Django 的 get() 方法检索单个文件记录,并且与 S3 文件路径完全匹配:
file = File.objects.get(file_path='/bucket/path/to/file.txt')
这将转换为以下 SQL 查询:
SELECT * FROM my_table WHERE file_path = '/bucket/path/to/file.txt' LIMIT 1;
我想了解 PostgreSQL 处理这个查询时幕后发生了什么。具体来说:
1. How does PostgreSQL handle the comparison of strings when using the = operator on a CharField with an S3 file path?
2. Does PostgreSQL behave differently if there’s an index on the file_path column, and how does it decide between using an index or performing a sequential scan?
3. Is it beneficial to create an index on the file_path field for better performance,
如果您知道 Django 中的查询集如何工作,您会发现它只是将 ORM 表示法转换为纯文本
SQL
例如:
File.objects.get(file_path='/bucket/path/to/file.txt')
它将转变为如下所示:
SELECT * FROM "appname_file" WHERE "file_path" = '/bucket/path/to/file.txt' LIMIT 1;
在这种情况下,如果
file_path
不是索引,那么 SQL 引擎执行 Execution Plan
它将执行一个名为:FULL SCAN
的操作,这意味着它肯定会扫描表中不是索引的所有行。就性能而言确实非常高效。
如果您决定创建索引
file_path
,它将做一些非常不同的事情,因为它存储了名为 Data pages or Leaf nodes
的内容,其中包含记录子集分配位置的映射,因此它将查询 data_pages
并从那里开始它将获取该行的唯一标识符,并且不会执行 FULL SCAN
。
注意事项:
EXPLAIN
关键字评估生成计划的性能,并可以分析结果。EXPLAIN ANALYZE
,它不仅会给你执行计划,还会给你执行时间。from django.db import connection
sql = 'EXPLAIN SELECT * FROM appname_file WHERE file_path=%s LIMIT 1;'
params = ['/bucket/path/to/file.txt']
with connection.cursor() as cursor:
cursor.execute(sql, params):
plan = cursor.fetchall()
print(plan)
我鼓励您进行自己的性能评估,看看索引是否适合您的用例,我想如果
appname_file
对于每一行都是唯一的,它会特别有效。