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

这篇具有很好参考价值的文章主要介绍了使用Python内置模块加速SQL查询。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

本文将介绍如何使用sqlite3模块在Python中连接和查询SQLite数据库,同时还将讲述如何添加索引并看到它是如何提高性能的。 

在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——一个用于生成合成数据的Python软件包,可以通过pip安装:

$ 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列上创建了索引,因此如果运行涉及其他列的查询,查询的运行速度不会比没有索引时更快。

 文章来源地址https://www.toymoban.com/news/detail-669293.html

到了这里,关于使用Python内置模块加速SQL查询的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python 通过pymssql访问查询操作 SQL Server数据库

    在企业应用开发中,经常用到应用程序访问数据库的开发模式,中小企业使用的数据库中,以ms SQL Server居多。本文就以一个简单的实例模型,简单介绍一下python访问ms sql sever数据库的方法。 本文中以下面的本地SQL Server数据库为例进行数据库连接,数据表的查询、增加、删除

    2024年02月10日
    浏览(105)
  • 【数据库】日常使用PL/SQL 登录ORACLE 数据库查询数据

    一、PL/SQL 登录方式 username: ##访问数据库的账号 password: ##访问数据库的密码 Databse: ##数据库IP地址/实例名 数据库集群心跳地址/实例名 Connect as : ##Normal,如果使用sysdba账户登录选择SYSDBA 二、PL/SQL使用SQL语句查询 点击上方导航栏,New,选择SQL Window,即可再次输入要查询的

    2024年02月19日
    浏览(70)
  • clickhouse数据库 使用http 方式交付查询sql

    今天使用clickhouse 的HTTP 方式进行查询语句 clickhouse  服务  搭建在192.168.0.111 上面 那么我们如何快速的去查询呢   如下 我们可以使用curl 功能 或者直接在浏览器上输入对应的查询命令  如下: 说明: 前面的IP 是我们clickhouse所在的服务器IP底子 端口      8123     默认的H

    2024年01月25日
    浏览(44)
  • Django笔记二十一之使用原生SQL查询数据库

    本文首发于公众号:Hunter后端 原文链接:Django笔记二十一之使用原生SQL查询数据库 Django 提供了两种方式来执行原生 SQL 代码。 一种是使用 raw() 函数,一种是 使用 connection.cursor()。 但是官方还是推荐在使用原生 SQL 之前,尽量的先去探索一下 QuerySet 提供的各种 API。 目前而言

    2023年04月10日
    浏览(61)
  • 【Mysql】X-DOC:Mysql数据库大量数据查询加速(定时JOB和存储过程应用案例)

    在某中台系统中,设计了大量的基础数据(维度数据、维度映射关系等)来支撑业务功能,业务表中存在大量的维度外键关联字段,其优点是可以实现前端的选择录入,数据校验,确保录入数据的准确性;缺点是在做业务报表时,需要做大量的维度关联(join)操作。 受限于

    2024年02月12日
    浏览(43)
  • 关系数据库SQL数据查询

    1.查询仅涉及一个表,选择表中的若干列 查询全部列 选出所有属性列: 在SELECT后面列出所有列名 将目标列表达式指定为 * 查询经过计算的值 SELECT子句的目标列表达式不仅可以为表中的属性列,也可以是表达式 使用列别名改变查询结果的列标题: 2.选择表中的若干元组

    2024年02月09日
    浏览(54)
  • LLMs之Vanna:Vanna(利用自然语言查询数据库的SQL工具+底层基于RAG)的简介、安装、使用方法之详细攻略

    LLMs之Vanna:Vanna(利用自然语言查询数据库的SQL工具+底层基于RAG)的简介、安装、使用方法之详细攻略 目录 Vanna的简介 1、用户界面 2、RAG vs. Fine-Tuning 3、为什么选择Vanna? 4、扩展Vanna Vanna的安装和使用方法 1、安装 2、训练 (1)、使用DDL语句训练 (2)、使用文档训练 (3)、使用SQL训

    2024年01月20日
    浏览(71)
  • 数据库 SQL高级查询语句:聚合查询,多表查询,连接查询

    创建Students和Courses表 直接查询 设置别名查询 设置条件查询 使用COUNT(*) 和 COUNT(StudentID)是一样的效果,因为StudentID是主键,每行记录的主键都不同。另外我们在聚合查询中还是能使用WHERE子句的,比如我们要 查找年龄大于20岁的学生数量 ,可使用以下SQL语句: 函数 说明 SUM

    2024年02月09日
    浏览(127)
  • 数据库SQL查询相关练习

    1、显示所有职工的基本信息。 2、查询所有职工所属部门的部门号,不显示重复的部门号。 3、求出所有职工的人数。 4、列出最高工和最低工资。 5、列出职工的平均工资和总工资。 6、创建一个只有职工号、姓名和参加工作的新表,名为工作日期表。 8、列出所有姓刘的职工

    2024年01月25日
    浏览(49)
  • 数据库作业-sql语句查询

    建表的插入数据的表 数据库作业-sql建表和插入数据_快乐的xiao何的博客-CSDN博客 create table supplier( supplierno char(6) primary key, suppliername nvarchar(10), address nvarchar(20), number char(11) )create table category( categoryno char(5) primary key, categoryname varchar(20), descriptions text... https://blog.csdn.net/m0_539670

    2023年04月23日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包