您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Python

使用Python内置模块加速SQL查询

时间:2023-08-22 20:12:15  来源:  作者:

假设你正在查阅一本书的页面,你想要更快地找到你正在寻找的信息。你会怎么做呢?那么你可能会查找术语索引,然后跳转到引用特定术语的页面。SQL中的索引与书籍中的索引工作原理类似。

在大多数实际系统中,都将对包含大量行的数据库表运行查询(想象一下数百万行)。需要通过扫描所有行来检索结果的查询将非常慢。如果你知道经常需要根据某些列查询信息,可以在这些列上创建数据库索引。这将大大加快查询速度。

图片

那么今天跟随本文将学到什么呢?将学习如何使用sqlite3模块在Python/ target=_blank class=infotextkey>Python中连接和查询SQLite数据库。同时还将学习如何添加索引并看到它是如何提高性能的。

要按照本教程进行编码,确保工作环境中安装了Python 3.7+和SQLite。

注意:本教程中的示例和样本输出适用于Ubuntu LTS 22.04上的Python 3.10和SQLite3(版本3.37.2)。

在Python中连接到数据库

本文将使用内置的sqlite3模块。在开始运行查询之前,需要做到以下步骤:

【sqlite3】:https://docs.python.org/3/library/sqlite3.html

  • 连接到数据库

  • 创建一个数据库游标以运行查询

要连接到数据库,本文将使用sqlite3模块中的connect()函数。一旦建立了连接,就可以在连接对象上调用cursor()来创建一个数据库游标,如下所示:

import sqlite3

# 连接到数据库
db_conn = sqlite3.connect('people_db.db')
db_cursor = db_conn.cursor()

在这里,尝试连接到名为people_db的数据库。如果数据库不存在,运行上述代码片段将为我们创建SQLite数据库。

创建表格并插入记录

现在,本文将在数据库中创建一个表,并向其中添加记录。

people_db数据库中创建一个名为people的表,其中包含以下字段:

  • name

  • emAIl

  • job

# main.py
...
# 创建表格
db_cursor.execute('''CREATE TABLE people (
                  id INTEGER PRIMARY KEY,
                  name TEXT,
                  email TEXT,
                  job TEXT)''')


...

# 提交事务,关闭游标和数据库连接
db_conn.commit()
db_cursor.close()
db_conn.close()

使用Faker生成合成数据

现在,需要在表中插入记录。为此将使用Faker——一个用于生成合成数据的Python软件包,可以通过pip安装:

【Faker】:https://faker.readthedocs.io/en/master/

$ pip install faker

安装Faker后,就可以将Faker类导入到Python脚本中:

# main.py
...
from faker import Faker
...

下一步是生成并插入people表中的记录。为了演示索引如何加快查询速度,本文将插入大量记录。在这里将插入10万条记录;将num_records变量设置为100000

然后执行以下操作:

  • 实例化一个Faker对象fake并设置种子以获得可复现性。

  • 使用first_name()last_name()fake对象上调用,获取一个名字字符串。

  • 通过调用domain_name()生成一个虚假域名。

  • 使用名字和域名生成电子邮件字段。

  • 使用job()为每个个体记录获取一个职位。

使用如下代码生成并插入people表中的记录:

# 创建并插入记录
fake = Faker() # 确保导入:from faker import Faker 
Faker.seed(42)

num_records = 100000

for _ in range(num_records):
    first = fake.first_name()
    last = fake.last_name()
    name = f"{first} {last}"
    domain = fake.domain_name()
    email = f"{first}.{last}@{domain}"
    job = fake.job()
    db_cursor.execute('INSERT INTO people (name, email, job) VALUES (?,?,?)', (name,email,job))

# 提交事务并关闭游标和数据库连接
db_conn.commit()
db_cursor.close()
db_conn.close()

现在,main.py文件的包含代码如下:

# main.py
# 导入
import sqlite3
from faker import Faker

# 连接到数据库
db_conn = sqlite3.connect('people_db.db')
db_cursor = db_conn.cursor()

# 创建表格
db_cursor.execute('''CREATE TABLE people (
                  id INTEGER PRIMARY KEY,
                  name TEXT,
                  email TEXT,
                  job TEXT)''')


# 创建并插入记录
fake = Faker()
Faker.seed(42)

num_records = 100000

for _ in range(num_records):
    first = fake.first_name()
    last = fake.last_name()
    name = f"{first} {last}"
    domain = fake.domain_name()
    email = f"{first}.{last}@{domain}"
    job = fake.job()
    db_cursor.execute('INSERT INTO people (name, email, job) VALUES (?,?,?)', (name,email,job))

# 提交事务并关闭游标和数据库连接
db_conn.commit()
db_cursor.close()
db_conn.close()

运行此脚本一次,在表中填入记录数num_records

查询数据库

现在本文有了包含10万条记录的表格,接下来在people表格上运行一个示例查询。

通过运行一个查询来:

  • 获取职位为“产品经理”的记录的姓名和电子邮件,并将查询结果限制为10条记录。

本文将使用time模块的默认计时器来获取查询的大致执行时间。

# sample_query.py

import sqlite3
import time

db_conn = sqlite3.connect("people_db.db")
db_cursor = db_conn.cursor()

t1 = time.perf_counter_ns()

db_cursor.execute("SELECT name, email FROM people WHERE job='Product manager' LIMIT 10;")

res = db_cursor.fetchall()
t2 = time.perf_counter_ns()

print(res)
print(f"Query time without index: {(t2-t1)/1000} us")

以下是输出结果:

Output >>
[
    ("Tina Woods", "Tina.Woods@smith.com"),
    ("Toni Jackson", "Toni.Jackson@underwood.com"),
    ("Lisa Miller", "Lisa.Miller@solis-west.info"),
    ("Katherine Guerrero", "Katherine.Guerrero@schmidt-price.org"),
    ("Michelle Lane", "Michelle.Lane@carr-hardy.com"),
    ("Jane Johnson", "Jane.Johnson@graham.com"),
    ("Matthew Odom", "Matthew.Odom@willis.biz"),
    ("Isaac Daniel", "Isaac.Daniel@peck.com"),
    ("Jay Byrd", "Jay.Byrd@bailey.info"),
    ("Thomas Kirby", "Thomas.Kirby@west.com"),
]

Query time without index: 448.275 us

还可以通过在命令行中运行sqlite3 db_name来调用SQLite命令行客户端:

$ sqlite3 people_db.db
SQLite version 3.37.2 2022-01-06 13:25:41
Enter ".help" for usage hints.

要获取索引列表,可以运行.index

sqlite> .index

由于当前没有索引,因此不会列出任何索引。

还可以像这样检查查询计划:

sqlite> EXPLAIN QUERY PLAN SELECT name, email FROM people WHERE job='Product Manager' LIMIT 10;
QUERY PLAN
`--SCAN people

这里的查询计划是扫描所有行,效率不高。

在特定列上创建索引

要在特定列上创建数据库索引,可以使用以下语法:

CREATE INDEX index-name on table (column(s))

假设需要经常查找具有特定职位的个人记录。在职位列上创建一个名为people_job_index的索引有助于提高效率:

# create_index.py

import time
import sqlite3

db_conn = sqlite3.connect('people_db.db')

db_cursor =db_conn.cursor()

t1 = time.perf_counter_ns()

db_cursor.execute("CREATE INDEX people_job_index ON people (job)")

t2 = time.perf_counter_ns()

db_conn.commit()

print(f"Time to create index: {(t2 - t1)/1000} us")


Output >>
Time to create index: 338298.6 us

尽管创建索引需要这么长时间,但这是一次性的操作。在运行多个查询时,仍然会获得相当大的加速。

现在如果在SQLite命令行客户端运行.index,将获得:

sqlite> .index
people_job_index

使用索引查询数据库

如果现在查看查询计划,应该能够看到现在使用名为people_job_index的索引在job列上搜索people表:

sqlite> EXPLAIN QUERY PLAN SELECT name, email FROM people WHERE job='Product manager' LIMIT 10;
QUERY PLAN
`--SEARCH people USING INDEX people_job_index (job=?)

可以重新运行sample_query.py。仅修改print()语句,然后看看现在运行查询需要多长时间:

# sample_query.py

import sqlite3
import time

db_conn = sqlite3.connect("people_db.db")
db_cursor = db_conn.cursor()

t1 = time.perf_counter_ns()

db_cursor.execute("SELECT name, email FROM people WHERE job='Product manager' LIMIT 10;")

res = db_cursor.fetchall()
t2 = time.perf_counter_ns()

print(res)
print(f"Query time with index: {(t2-t1)/1000} us")

以下是输出结果:

Output >>
[
    ("Tina Woods", "Tina.Woods@smith.com"),
    ("Toni Jackson", "Toni.Jackson@underwood.com"),
    ("Lisa Miller", "Lisa.Miller@solis-west.info"),
    ("Katherine Guerrero", "Katherine.Guerrero@schmidt-price.org"),
    ("Michelle Lane", "Michelle.Lane@carr-hardy.com"),
    ("Jane Johnson", "Jane.Johnson@graham.com"),
    ("Matthew Odom", "Matthew.Odom@willis.biz"),
    ("Isaac Daniel", "Isaac.Daniel@peck.com"),
    ("Jay Byrd", "Jay.Byrd@bailey.info"),
    ("Thomas Kirby", "Thomas.Kirby@west.com"),
]

Query time with index: 167.179 us

可以看到查询现在大约需要167.179微秒来执行。

性能改进

对于本文的示例查询,使用索引的查询速度大约快2.68倍。在执行时间方面获得了62.71%的速度提升。

还可以尝试运行更多的查询:涉及筛选job列的查询,并查看性能的改进情况。

另请注意:由于只在job列上创建了索引,因此如果运行涉及其他列的查询,查询的运行速度不会比没有索引时更快。

结语

希望本指南帮助你了解如何通过创建数据库索引(在频繁查询的列上)显著加快查询速度。这是数据库索引的介绍。你还可以创建多列索引、同一列的多个索引等等。

可以在此Github存储库中找到本教程中使用的所有代码。

【GitHub】:https://github.com/balapriyac/sql-index-intro



Tags:Python   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Python 可视化:Plotly 库使用基础
当使用 Plotly 进行数据可视化时,我们可以通过以下示例展示多种绘图方法,每个示例都会有详细的注释和说明。1.创建折线图import plotly.graph_objects as go# 示例1: 创建简单...【详细内容】
2024-04-01  Search: Python  点击:(8)  评论:(0)  加入收藏
Python 办公神器:教你使用 Python 批量制作 PPT
介绍本文将介绍如何使用openpyxl和pptx库来批量制作PPT奖状。本文假设你已经安装了python和这两个库。本文的场景是:一名基层人员,要给一次比赛活动获奖的500名选手制作奖状,并...【详细内容】
2024-03-26  Search: Python  点击:(16)  评论:(0)  加入收藏
Python实现工厂模式、抽象工厂,单例模式
工厂模式是一种常见的设计模式,它可以帮助我们创建对象的过程更加灵活和可扩展。在Python中,我们可以使用函数和类来实现工厂模式。一、Python中实现工厂模式工厂模式是一种常...【详细内容】
2024-03-07  Search: Python  点击:(31)  评论:(0)  加入收藏
不可不学的Python技巧:字典推导式使用全攻略
Python的字典推导式是一种优雅而强大的工具,用于创建字典(dict)。这种方法不仅代码更加简洁,而且执行效率高。无论你是Python新手还是有经验的开发者,掌握字典推导式都将是你技能...【详细内容】
2024-02-22  Search: Python  点击:(32)  评论:(0)  加入收藏
如何进行Python代码的代码重构和优化?
Python是一种高级编程语言,它具有简洁、易于理解和易于维护的特点。然而,代码重构和优化对于保持代码质量和性能至关重要。什么是代码重构?代码重构是指在不改变代码外部行为的...【详细内容】
2024-02-22  Search: Python  点击:(33)  评论:(0)  加入收藏
Python开发者必备的八个PyCharm插件
在编写代码的过程中,括号几乎无处不在,以至于有时我们会拼命辨别哪个闭合括号与哪个开头的括号相匹配。这款插件能帮助解决这个众所周知的问题。前言在PyCharm中浏览插件列表...【详细内容】
2024-01-26  Search: Python  点击:(85)  评论:(0)  加入收藏
Python的Graphlib库,再也不用手敲图结构了
Python中的graphlib库是一个功能强大且易于使用的工具。graphlib提供了许多功能,可以帮助您创建、操作和分析图形对象。本文将介绍graphlib库的主要用法,并提供一些示例代码和...【详细内容】
2024-01-26  Search: Python  点击:(86)  评论:(0)  加入收藏
大语言模型插件功能在携程的Python实践
作者简介成学,携程高级安全研发工程师,关注Python/Golang后端开发、大语言模型等领域。一、背景2023年初,科技圈最火爆的话题莫过于大语言模型了,它是一种全新的聊天机器人模型,...【详细内容】
2024-01-26  Search: Python  点击:(73)  评论:(0)  加入收藏
如何使用Python、Apache Kafka和云平台构建健壮的实时数据管道
译者 | 李睿审校 | 重楼在当今竞争激烈的市场环境中,为了生存和发展,企业必须能够实时收集、处理和响应数据。无论是检测欺诈、个性化用户体验还是监控系统,现在都需要接近即时...【详细内容】
2024-01-26  Search: Python  点击:(46)  评论:(0)  加入收藏
Python分布式爬虫打造搜索引擎
简单分布式爬虫结构主从模式是指由一台主机作为控制节点负责所有运行网络爬虫的主机进行管理,爬虫只需要从控制节点那里接收任务,并把新生成任务提交给控制节点就可以了,在这个...【详细内容】
2024-01-25  Search: Python  点击:(58)  评论:(0)  加入收藏
▌简易百科推荐
Python 可视化:Plotly 库使用基础
当使用 Plotly 进行数据可视化时,我们可以通过以下示例展示多种绘图方法,每个示例都会有详细的注释和说明。1.创建折线图import plotly.graph_objects as go# 示例1: 创建简单...【详细内容】
2024-04-01  Python技术    Tags:Python   点击:(8)  评论:(0)  加入收藏
Python 办公神器:教你使用 Python 批量制作 PPT
介绍本文将介绍如何使用openpyxl和pptx库来批量制作PPT奖状。本文假设你已经安装了python和这两个库。本文的场景是:一名基层人员,要给一次比赛活动获奖的500名选手制作奖状,并...【详细内容】
2024-03-26  Python技术  微信公众号  Tags:Python   点击:(16)  评论:(0)  加入收藏
Python实现工厂模式、抽象工厂,单例模式
工厂模式是一种常见的设计模式,它可以帮助我们创建对象的过程更加灵活和可扩展。在Python中,我们可以使用函数和类来实现工厂模式。一、Python中实现工厂模式工厂模式是一种常...【详细内容】
2024-03-07  Python都知道  微信公众号  Tags:Python   点击:(31)  评论:(0)  加入收藏
不可不学的Python技巧:字典推导式使用全攻略
Python的字典推导式是一种优雅而强大的工具,用于创建字典(dict)。这种方法不仅代码更加简洁,而且执行效率高。无论你是Python新手还是有经验的开发者,掌握字典推导式都将是你技能...【详细内容】
2024-02-22  子午Python  微信公众号  Tags:Python技巧   点击:(32)  评论:(0)  加入收藏
如何进行Python代码的代码重构和优化?
Python是一种高级编程语言,它具有简洁、易于理解和易于维护的特点。然而,代码重构和优化对于保持代码质量和性能至关重要。什么是代码重构?代码重构是指在不改变代码外部行为的...【详细内容】
2024-02-22  编程技术汇    Tags:Python代码   点击:(33)  评论:(0)  加入收藏
Python开发者必备的八个PyCharm插件
在编写代码的过程中,括号几乎无处不在,以至于有时我们会拼命辨别哪个闭合括号与哪个开头的括号相匹配。这款插件能帮助解决这个众所周知的问题。前言在PyCharm中浏览插件列表...【详细内容】
2024-01-26  Python学研大本营  微信公众号  Tags:PyCharm插件   点击:(85)  评论:(0)  加入收藏
Python的Graphlib库,再也不用手敲图结构了
Python中的graphlib库是一个功能强大且易于使用的工具。graphlib提供了许多功能,可以帮助您创建、操作和分析图形对象。本文将介绍graphlib库的主要用法,并提供一些示例代码和...【详细内容】
2024-01-26  科学随想录  微信公众号  Tags:Graphlib库   点击:(86)  评论:(0)  加入收藏
Python分布式爬虫打造搜索引擎
简单分布式爬虫结构主从模式是指由一台主机作为控制节点负责所有运行网络爬虫的主机进行管理,爬虫只需要从控制节点那里接收任务,并把新生成任务提交给控制节点就可以了,在这个...【详细内容】
2024-01-25  大雷家吃饭    Tags:Python   点击:(58)  评论:(0)  加入收藏
使用Python进行数据分析,需要哪些步骤?
Python是一门动态的、面向对象的脚本语言,同时也是一门简约,通俗易懂的编程语言。Python入门简单,代码可读性强,一段好的Python代码,阅读起来像是在读一篇外语文章。Python这种特...【详细内容】
2024-01-15  程序员不二    Tags:Python   点击:(162)  评论:(0)  加入收藏
Python语言的特点及应用场景, 同其它语言对比优势
Python语言作为一种高级编程语言,具有许多独特的特点和优势,这使得它在众多编程语言中脱颖而出。在本文中,我们将探讨Python语言的特点、应用场景以及与其他语言的对比优势。一...【详细内容】
2024-01-09    今日头条  Tags:Python语言   点击:(253)  评论:(0)  加入收藏
站内最新
站内热门
站内头条