国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

如何使用索引加速 SQL 查詢 [Python 版]

這篇具有很好參考價(jià)值的文章主要介紹了如何使用索引加速 SQL 查詢 [Python 版]。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

推薦:使用 NSDT場(chǎng)景編輯器助你快速搭建可二次編輯器的3D應(yīng)用場(chǎng)景

假設(shè)您正在篩選一本書的頁面。而且您希望更快地找到所需的信息。你是怎么做到的?好吧,您可能會(huì)查找術(shù)語索引,然后跳轉(zhuǎn)到引用特定術(shù)語的頁面。SQL 中的索引的工作方式與書籍中的索引類似。

在大多數(shù)實(shí)際系統(tǒng)中,您將針對(duì)具有大量行(例如數(shù)百萬行)的數(shù)據(jù)庫表運(yùn)行查詢。需要全表掃描所有行以檢索結(jié)果的查詢將非常慢。如果您知道必須經(jīng)?;谀承┝胁樵冃畔ⅲ瑒t可以在這些列上創(chuàng)建數(shù)據(jù)庫索引。這將大大加快查詢速度。

那么我們今天會(huì)學(xué)到什么呢?我們將學(xué)習(xí)使用 sqlite3 模塊在 Python 中連接和查詢 SQLite 數(shù)據(jù)庫。我們還將學(xué)習(xí)如何添加索引,并了解它如何提高性能。

要按照本教程編寫代碼,您應(yīng)該在工作環(huán)境中安裝 Python 3.7+ 和 SQLite。

注意:本教程中的示例和示例輸出適用于 Ubuntu LTS 3.10 上的 Python 3.3 和 SQLite37(版本 2.22.04)。

在 Python 中連接到數(shù)據(jù)庫

我們將使用內(nèi)置的 sqlite3 模塊。在開始運(yùn)行查詢之前,我們需要:

  • 連接到數(shù)據(jù)庫
  • 創(chuàng)建數(shù)據(jù)庫游標(biāo)以運(yùn)行查詢

若要連接到數(shù)據(jù)庫,我們將使用

來自 sqlite3 模塊的 connect() 函數(shù)。建立連接后,我們可以調(diào)用連接對(duì)象來創(chuàng)建數(shù)據(jù)庫游標(biāo),如下所示:cursor()

import sqlite3

# connect to the db
db_conn = sqlite3.connect('people_db.db')
db_cursor = db_conn.cursor()

在這里,我們嘗試連接到數(shù)據(jù)庫

people_db.如果數(shù)據(jù)庫不存在,運(yùn)行上面的代碼片段將為我們創(chuàng)建 sqlite 數(shù)據(jù)庫。

創(chuàng)建表并插入記錄

現(xiàn)在,我們將在數(shù)據(jù)庫中創(chuàng)建一個(gè)表,并用記錄填充它。

讓我們?cè)跀?shù)據(jù)庫中創(chuàng)建一個(gè)名為?people?的表,其中包含以下字段:people_db

  • 名字
  • 電子郵件
  • 工作
# main.py
...
# create table
db_cursor.execute('''CREATE TABLE people (
                  id INTEGER PRIMARY KEY,
                  name TEXT,
                  email TEXT,
                  job TEXT)''')


...

# commit the transaction and close the cursor and db connection
db_conn.commit()
db_cursor.close()
db_conn.close()

使用偽造器生成合成數(shù)據(jù)

我們現(xiàn)在必須在表中插入記錄。為此,我們將使用?Faker——一個(gè)用于合成數(shù)據(jù)生成的 Python 包——可通過?pip?安裝:

$ pip install faker

安裝faker后,可以將類導(dǎo)入到Python腳本中:Faker

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

下一步是生成記錄并將其插入人員表。為了讓我們知道索引如何加快查詢速度,讓我們插入大量記錄。在這里,我們將插入 100K 條記錄;將變量設(shè)置為 100000。num_records

然后,我們執(zhí)行以下操作:

  • 實(shí)例化一個(gè)對(duì)象并設(shè)置種子,以便我們獲得可重現(xiàn)性。Fakerfake
  • 使用名字和姓氏獲取名稱字符串 - 通過調(diào)用對(duì)象和對(duì)象。first_name()last_name()fake
  • 通過調(diào)用生成假域。domain_name()
  • 使用名字和姓氏以及域生成電子郵件字段。
  • 使用 獲取每個(gè)單獨(dú)記錄的作業(yè)。job()

我們生成記錄并將其插入到表中:people

# create and insert records
fake = Faker() # be sure to import: 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))

# commit the transaction and close the cursor and db connection
db_conn.commit()
db_cursor.close()
db_conn.close()

現(xiàn)在,main.py 文件具有以下代碼:

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

# connect to the db
db_conn = sqlite3.connect('people_db.db')
db_cursor = db_conn.cursor()

# create table
db_cursor.execute('''CREATE TABLE people (
                  id INTEGER PRIMARY KEY,
                  name TEXT,
                  email TEXT,
                  job TEXT)''')


# create and insert records
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))

# commit the transaction and close the cursor and db connection
db_conn.commit()
db_cursor.close()
db_conn.close()

運(yùn)行此腳本一次,以使用記錄數(shù)填充表。num_records

查詢數(shù)據(jù)庫

現(xiàn)在我們有了包含 100K 條記錄的表,讓我們對(duì)表運(yùn)行一個(gè)示例查詢。people

讓我們運(yùn)行一個(gè)查詢來:

  • 獲取職位名稱為“產(chǎn)品經(jīng)理”的記錄的名稱和電子郵件,以及
  • 將查詢結(jié)果限制為 10 條記錄。

我們將使用 time 模塊中的默認(rèn)計(jì)時(shí)器來獲取查詢的大致執(zhí)行時(shí)間。

# 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

您還可以通過在命令行運(yùn)行來調(diào)用 SQLite 命令行客戶端:sqlite3 db_name

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

要獲取索引列表,您可以運(yùn)行:.index

sqlite> .index

由于當(dāng)前沒有索引,因此不會(huì)列出任何索引。

您還可以像這樣檢查查詢計(jì)劃:

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

這里的查詢計(jì)劃是掃描所有效率低下的行。

在特定列上創(chuàng)建索引

若要在特定列上創(chuàng)建數(shù)據(jù)庫索引,可以使用以下語法:

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

假設(shè)我們需要經(jīng)常查找具有特定職位的個(gè)人的記錄。在作業(yè)列上創(chuàng)建索引會(huì)有所幫助: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

盡管創(chuàng)建索引需要這么長時(shí)間,但這是一次性操作。運(yùn)行多個(gè)查詢時(shí),您仍將獲得顯著的加速。

現(xiàn)在,如果您在 SQLite 命令行客戶端上運(yùn)行,您將獲得:.index

sqlite> .index
people_job_index

使用索引查詢數(shù)據(jù)庫

如果您現(xiàn)在查看查詢計(jì)劃,您應(yīng)該能夠看到我們現(xiàn)在使用作業(yè)列上的索引搜索表:peoplepeople_job_index

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=?)

您可以重新運(yùn)行sample_query.py。僅修改語句并查看查詢現(xiàn)在運(yùn)行需要多長時(shí)間: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

我們看到查詢現(xiàn)在大約需要 167.179 微秒來執(zhí)行。

性能改進(jìn)

對(duì)于我們的示例查詢,使用 index 進(jìn)行查詢的速度大約快 2.68 倍。我們?cè)趫?zhí)行時(shí)間中獲得了 62.71% 的百分比加速。

您還可以嘗試運(yùn)行更多查詢:涉及對(duì)作業(yè)列進(jìn)行篩選并查看性能改進(jìn)的查詢。

另請(qǐng)注意:由于我們僅在作業(yè)列上創(chuàng)建了索引,因此,如果您運(yùn)行的查詢涉及其他列,則查詢的運(yùn)行速度不會(huì)比沒有索引時(shí)快。

總結(jié)和后續(xù)步驟

我希望本指南能幫助您了解在頻繁查詢的列上創(chuàng)建數(shù)據(jù)庫索引如何顯著加快查詢速度。這是對(duì)數(shù)據(jù)庫索引的介紹。您還可以創(chuàng)建多列索引、同一列的多個(gè)索引等等。

原文鏈接:如何使用索引加速 SQL 查詢 [Python 版] (mvrlink.com)文章來源地址http://www.zghlxwxcb.cn/news/detail-649284.html

到了這里,關(guān)于如何使用索引加速 SQL 查詢 [Python 版]的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包