論索引影響性能的一面④ 索引失蹤之謎【上】

梁敬彬梁敬弘兄弟出品

往期回顧
論索引影響性能的一面①索引的各種開銷
論索引影響性能的一面②索引的使用失效
論索引影響性能的一面③ 索引開銷與經典案例

開篇:DBA的深夜“尋人啟事”

作為數據庫的守護者,我們最信賴的伙伴莫過于“索引”。它如同一位效率超群的圖書管理員,能于浩如煙海的數據中,精準地為我們取出所需的那一頁。但你是否也曾遇到過這樣的“靈異事件”:明明為它精心創建了索引,性能卻依舊慘不忍睹?執行計劃里,那個熟悉的身影消失不見,取而代之的是令人絕望的“全表掃描”(TABLE ACCESS FULL)。

索引失蹤了,到底去哪兒了?

這并非靈異故事,而是一系列潛藏在日常操作中的“性能懸案”。今天,我們將化身偵探,深入四個經典的“案發現場”,揭開索引失蹤的秘密。

在這里插入圖片描述

懸案一:like與 %間一波三折的故事

案情簡介:
江湖傳言,“LIKE一出,索引必廢”。這個說法流傳甚廣,讓許多開發者談%色變。但這究竟是真相,還是誤解?讓我們用證據說話。

現場勘查與證據收集:
首先,我們準備“案發現場”——一張T表,并在OBJECT_NAME列上建立索引。

drop table t purge;
create table t as select * from dba_objects where object_id is not null;
set autotrace off
update t set object_id=rownum;
update t set object_name='AAALJB' where object_id=8;
update t set object_name='LJBAAA' where object_id=10;
commit;
create index idx_object_name on t(object_name);
SET AUTOTRACE ON
SET LINESIZE 1000

1. 場景一:前綴匹配查詢 (‘LJB%’)

select object_name,object_id from t where object_name like 'LJB%';OBJECT_NAME OBJECT_ID
-------------------------------------------------------------------------------------
LJBAAA 10
LJB_TMP_SESSION 72521
LJB_TMP_SESSION 72910
LJB_TMP_TRANSACTION 72522
LJB_TMP_TRANSACTION 72911
已選擇5行。執行計劃
--------------------------------------------------------------------------------------
| Id |Operation | Name |Rows | Bytes | Cost (%CPU)| Time |
| 0 |SELECT STATEMENT | | 5| 395 | 6 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 5| 395 | 6 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IDX_OBJECT_NAME | 5| | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
統計信息
----------------------------------------------------------0  recursive calls0  db block gets9  consistent gets0  physical reads0  redo size602  bytes sent via SQL*Net to client415  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)5  rows processed

破案分析:
索引健在,且表現優異! INDEX RANGE SCAN(索引范圍掃描)赫然在列。like 'LJB%'這種前綴匹配,Oracle可以精準定位到索引樹中“LJB”的位置開始掃描,當然能用到索引。

2. 場景二:模糊匹配查詢 (‘%LJB%’)

select object_name,object_id from t where object_name like '%LJB%';執行計劃
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 12 | 948 | 292 (1)| 00:00:04 |
|* 1 | TABLE ACCESS FULL| T | 12 | 948 | 292 (1)| 00:00:04 |
--------------------------------------------------------------------------------------統計信息
----------------------------------------------------------0  recursive calls0  db block gets1049  consistent gets0  physical reads0  redo size653  bytes sent via SQL*Net to client415  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)6  rows processed

破案分析:
索引“人間蒸發”! TABLE ACCESS FULL出現了。因為前導%的存在,Oracle不知道檢索何時能停下來,只能放棄索引,選擇全表掃描。

3. 場景三:后綴匹配的“曲線救國” (‘%LJB’)

正常情況下,后綴匹配與模糊匹配原理相似,無法使用常規索引。但我們可以通過reverse函數和函數索引,巧妙破局。

create index idx_reverse_objname on t(reverse(object_name));
set autotrace on
select object_name,object_id from t where reverse(object_name) like reverse('%LJB');OBJECT_NAME OBJECT_ID
-------------------------------------------------------------------------------------
AAALJB 8執行計劃
--------------------------------------------------------------------------------------
|Id |Operation |Name |Rows |Bytes |Cost (%CPU)| Time |
| 0|SELECT STATEMENT | | 3596| 509K| 290 (0)| 00:00:04 |
| 1| TABLE ACCESS BY INDEX ROWID|T | 3596| 509K| 290 (0)| 00:00:04 |
|* 2| INDEX RANGE SCAN |IDX_REVERSE_OBJNAME| 647| | 6 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
統計信息
----------------------------------------------------------0  recursive calls0  db block gets5  consistent gets0  physical reads0  redo size496  bytes sent via SQL*Net to client415  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed

在這里插入圖片描述

懸案二:move命令引發的“血案”

案情簡介:
這是一起發生在某大型制造業系統的真實“血案”。一個看似無害的ALTER TABLE … MOVE操作,竟導致系統核心查詢性能驟降,業務近乎癱瘓。

現場勘查與證據收集:

drop table t_p cascade constraints purge;
drop table t_c cascade constraints purge;
CREATE TABLE T_P (ID NUMBER, NAME VARCHAR2(30));
ALTER TABLE T_P ADD CONSTRAINT T_P_ID_PK PRIMARY KEY (ID);
CREATE TABLE T_C (ID NUMBER, FID NUMBER, NAME VARCHAR2(30));
ALTER TABLE T_C ADD CONSTRAINT FK_T_C FOREIGN KEY (FID) REFERENCES T_P (ID);
INSERT INTO T_P SELECT ROWNUM, TABLE_NAME FROM ALL_TABLES;
INSERT INTO T_C SELECT ROWNUM, MOD(ROWNUM, 1000) + 1, OBJECT_NAME FROM ALL_OBJECTS;
COMMIT;
CREATE INDEX IND_T_C_FID ON T_C (FID);-- 檢查索引初始狀態
SELECT TABLE_NAME,INDEX_NAME,STATUS FROM USER_INDEXES WHERE INDEX_NAME='IND_T_C_FID';
TABLE_NAME           INDEX_NAME           STATUS
-------------------- -------------------- --------
T_C                  IND_T_C_FID          VALID-- 執行一個“不小心”的操作
ALTER TABLE T_C MOVE;-- 再次檢查索引狀態
SELECT TABLE_NAME,INDEX_NAME,STATUS FROM USER_INDEXES WHERE INDEX_NAME='IND_T_C_FID';
TABLE_NAME           INDEX_NAME           STATUS
-------------------- -------------------- --------
T_C                  IND_T_C_FID          UNUSABLE

破案分析:
兇手正是MOVE命令! MOVE操作改變了表中所有行的ROWID,而索引中存儲的恰恰是舊的ROWID。Oracle為了避免數據錯亂,將該索引標記為UNUSABLE。這個“暗殺”是無聲的,操作本身不報錯,但索引已悄然“死亡”。

受害者(索引失效后的查詢):

SET LINESIZE 1000
SET AUTOTRACE TRACEONLY
SELECT A.ID, A.NAME, B.NAME FROM T_P A, T_C B WHERE A.ID = B.FID AND A.ID = 880;執行計劃
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 25 | 1500 | 111 (1)| 00:00:02 |
| 1 | NESTED LOOPS | | 25 | 1500 | 111 (1)| 00:00:02 |
| 2 | TABLE ACCESS BY INDEX ROWID| T_P | 1 | 30 | 0 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN | T_P_ID_PK | 1 | | 0 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL | T_C | 25 | 750 | 111 (1)| 00:00:02 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------3 - access("A"."ID"=880)4 - filter("B"."FID"=880)統計信息
----------------------------------------------------------0  recursive calls0  db block gets394  consistent gets0  physical reads0  redo size3602  bytes sent via SQL*Net to client459  bytes received via SQL*Net from client6  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)72  rows processed

對T_C表執行了TABLE ACCESS FULL,邏輯讀高達394。

“救治”方案與效果:

ALTER INDEX IND_T_C_FID REBUILD;-- 再次執行查詢
SELECT A.ID, A.NAME, B.NAME FROM T_P A, T_C B WHERE A.ID = B.FID AND A.ID = 880;執行計劃
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 72 | 4320 | 87 (0)| 00:00:02 |
| 1 | NESTED LOOPS | | 72 | 4320 | 87 (0)| 00:00:02 |
| 2 | TABLE ACCESS BY INDEX ROWID| T_P | 1 | 30 | 0 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN | T_P_ID_PK | 1 | | 0 (0)| 00:00:01 |
| 4 | TABLE ACCESS BY INDEX ROWID| T_C | 72 | 2160 | 87 (0)| 00:00:02 |
|* 5 | INDEX RANGE SCAN | IND_T_C_FID | 72 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------3 - access("A"."ID"=880)5 - access("B"."FID"=880)統計信息
----------------------------------------------------------0  recursive calls0  db block gets81  consistent gets0  physical reads0  redo size3602  bytes sent via SQL*Net to client459  bytes received via SQL*Net from client6  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)72  rows processed

偵探筆記:
ALTER TABLE … MOVE是一個極其危險的操作。操作規范:在執行MOVE后,必須立即REBUILD該表上的所有索引。
在這里插入圖片描述

懸案三:外鍵索引失效引發的“幽靈鎖”

案情簡介:
如果說上一個案例是MOVE命令造成的直接性能傷害,那么這個案例,則是它更隱蔽、更陰險的“并發癥”——鎖等待。
現場勘查與證據收集:

-- 準備環境
drop table t_p cascade constraints purge;
drop table t_c cascade constraints purge;
CREATE TABLE T_P (ID NUMBER, NAME VARCHAR2(30));
ALTER TABLE T_P ADD CONSTRAINT T_P_ID_PK PRIMARY KEY (ID);
CREATE TABLE T_C (ID NUMBER, FID NUMBER, NAME VARCHAR2(30));
ALTER TABLE T_C ADD CONSTRAINT FK_T_C FOREIGN KEY (FID) REFERENCES T_P (ID);
INSERT INTO T_P SELECT ROWNUM, TABLE_NAME FROM ALL_TABLES;
INSERT INTO T_C SELECT ROWNUM, MOD(ROWNUM, 1000) + 1, OBJECT_NAME FROM ALL_OBJECTS;
COMMIT;
-- 注意,這里沒有給外鍵列T_C(FID)創建索引-- 以下操作導致外鍵相關的索引失效(此處原文為move,但實際場景是未創建索引)
-- ALTER TABLE T_C MOVE;

并發測試:

-- 首先開啟會話1
select sid from v$mystat where rownum=1;
DELETE T_C WHERE ID = 2;-- 接下來開啟會話2,也就是開啟一個新的連接
select sid from v$mystat where rownum=1;
DELETE T_P WHERE ID = 2000;
-- 居然發現卡住半天不動了!

破案分析:
這起“幽靈鎖”的根源,在于外鍵約束的底層工作機制。當你操作主表(如DELETE T_P)時,Oracle必須確保子表中沒有任何記錄引用你將要刪除的主表記錄。

索引有效時: Oracle會通過外鍵列上的索引,快速檢查子表T_C中是否存在FID = 2000的記錄。
索引失效(或不存在)時: Oracle無法快速檢查,只能在子表T_C上施加一個全表鎖,然后慢慢地進行全表掃描。當會話1持有T_C的行級鎖時,會話2想要獲取全表鎖自然會被阻塞。
偵探筆記:
外鍵列上必須建立索引,并保證其永遠有效! 這不僅是查詢性能的需要,更是保證高并發環境下系統穩定性的“生命線”。

懸案四:shrink操作后的“偽裝者”

案情簡介:
既然MOVE如此危險,那我們用更現代的SHRINK命令來收縮表空間,總該安全了吧?它確實能避免索引失效,但新的問題又來了:索引明明VALID,優化器為何依然棄之不用?

現場勘查與證據收集:

drop table t purge;
create table t as select * from dba_objects where object_id is not null;
alter table t modify object_id not null;
set autotrace off
insert into t select * from t;
insert into t select * from t;
commit;
create index idx_object_id on t(object_id);
set linesize 1000
set autotrace on
select count(*) from t;
set autotrace off
delete from t where rownum<=292000;
commit;
set autotrace on
alter table t enable row movement;
alter table t shrink space;
select count(*) from t;執行計劃
------------------------------------------------------------------------------------
Plan hash value: 2966233522
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 5 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T | 740 | 5 (0)| 00:00:01 |
------------------------------------------------------------------------------------統計信息
----------------------------------------------------------0  recursive calls0  db block gets15  consistent gets0  physical reads0  redo size424  bytes sent via SQL*Net to client415  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed

破案分析:
索引再次“失蹤”!它明明狀態VALID,為何被優化器無情拋棄?我們強制讓它走索引(使用hint)看看。

select /*+index(t)*/ count(*) from t;執行計劃
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 675 (1)| 00:00:09 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | INDEX FULL SCAN| IDX_OBJECT_ID | 740 | 675 (1)| 00:00:09 |
--------------------------------------------------------------------------------------
統計信息
----------------------------------------------------------0  recursive calls0  db block gets649  consistent gets0  physical reads0  redo size424  bytes sent via SQL*Net to client415  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed

真相大白!強制走索引的成本(Cost=675,邏輯讀=649)遠高于走全表掃描(Cost=5,邏輯讀=15)。原因在于:SHRINK操作雖然收縮了表,但并未有效地收縮索引段的空間。 大量DELETE操作在索引中留下了許多“空洞”,導致索引變得稀疏而“臃腫”,掃描它反而得不償失。

偵探筆記:
索引的VALID狀態,僅僅是它的“準入證”,并不代表它的“健康證”。一個因大量刪除而變得臃腫的索引,即便有效,也可能成為性能的拖累。在這種情況下,ALTER INDEX … REBUILD 才是整理索引碎片、恢復其緊湊結構和高性能的“特效藥”。

總結

今天的調查到此告一段落。我們揭開了四個導致索引“失蹤”或“失效”的經典懸案:

偽裝者LIKE: 被前導通配符%所迷惑。
刺客MOVE: 無聲地讓索引狀態變為UNUSABLE。
幫兇“無索引外鍵”: 在并發操作中制造“幽靈鎖”。
“亞健康”的SHRINK后遺癥: 索引雖在,卻因臃腫而被優化器嫌棄。
然而,索引失蹤之謎遠未結束。在下一集中,我們將繼續追蹤另外四位“嫌疑人”,它們同樣狡猾,同樣致命。敬請期待《索引失蹤之謎(下)》。

未完待續…
論索引影響性能的一面⑤:索引失蹤之謎(下)

系列回顧

“大白話人工智能” 系列
“數據庫拍案驚奇” 系列
“世事洞明皆學問” 系列

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/909346.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/909346.shtml
英文地址,請注明出處:http://en.pswp.cn/news/909346.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java集合(九) ---- Stack 類

目錄 九、Stack 類 9.1 位置 9.2 特點 9.3 棧 9.4 構造方法 9.5 常用方法 9.6 注意點&#xff1a;循環遍歷 Stack 類 九、Stack 類 9.1 位置 Stack 類位于 java.util 包下 9.2 特點 Stack 類是 Vector 類的子類Stack 類對標于數據結構中的棧結構 9.3 棧 定義&…

ARXML可視化轉換工具使用說明

ARXML可視化轉換工具 | 詳細使用指南與說明 &#x1f4dd; 前言 自上篇文章《聊聊ARXML解析工具&#xff1a;我們是如何擺脫昂貴商業軟件的》發布以來&#xff0c;收到了眾多朋友的關注和咨詢&#xff0c;這讓我倍感榮幸&#xff01; 新朋友請注意&#xff1a;如果您還沒有閱…

松勝與奧佳華按摩椅:普惠科技與醫療級體驗的碰撞

在智能健康設備快速普及的今天&#xff0c;按摩椅已從奢侈品轉變為家庭健康管理的重要工具。面對市場上琳瑯滿目的品牌&#xff0c;松勝與奧佳華憑借截然不同的發展路徑&#xff0c;各自開辟出特色鮮明的賽道&#xff1a;前者以“技術普惠”理念打破高端按摩椅的價格壁壘&#…

一起學習Web 后端——PHP(二):深入理解字符與函數的使用

一、前言 在上一講中&#xff0c;我們主要講PHP的相關知識。本節我們將繼續深入&#xff0c;學習&#xff1a; PHP 中各種語法字符、符號的含義與用法&#xff1b; PHP 中常用函數的種類、定義方式與實際應用。 這些知識是構建 Web 后端邏輯的基礎&#xff0c;對于后期編寫…

【Bluedroid】藍牙啟動之 GAP_Init 流程源碼解析

藍牙 GAP(通用訪問配置文件)模塊是藍牙協議棧的核心組件,負責設備發現、連接管理及基礎屬性暴露等關鍵功能。本文圍繞 Android藍牙協議棧 GAP 模塊的初始化流程與連接管理實現展開,結合代碼解析其核心函數(GAP_Init、gap_conn_init、gap_attr_db_init)的功能邏輯,以及關…

最新四六級寫作好詞好句錦囊(持續更新中)

完整版四六級備考攻略可見另一篇博客~~&#xff08;喜歡的留個點贊收藏再走唄~~&#xff09; ??????四六級備考攻略-CSDN博客 一、通用 1、詞組 2、單詞 3、句型 二、老齡化、老年人 三、學習、社交、社會實踐 四、文化、習俗 五、數字素養、數字技能 六、資…

Java 通用實體驗證框架:從業務需求到工程化實踐【生產級 - 適用于訂單合并前置校驗】

Java 通用實體驗證框架&#xff1a;從業務需求到工程化實踐【適用于訂單合并前置校驗】 一、業務驗證痛點與需求背景 1. 傳統驗證方式的困境 傳統驗證方式存在代碼冗余、維護成本高和擴展性差等問題。相同的驗證邏輯在不同模塊重復編寫&#xff0c;修改驗證規則時需要同步修…

PyArk飄云閣出品的ARK工具

PyArk是由飄云閣&#xff08;PiaoYunGe&#xff09;開發的一款功能強大的系統安全分析工具&#xff0c;主要用于Windows環境下的內核級檢測與分析。該工具集成了進程管理、驅動模塊掃描、內核及應用層鉤子檢測、進程注入等核心功能&#xff0c;旨在幫助安全研究人員深入識別潛在…

【高中數學之復數】已知復數z的幅角為60°,且|z-1|是|z|和|z-2|的等比中項,求|z|?(2003高考數學全國卷,解答題首題,總第17題)

【問題】 已知復數z的幅角為60&#xff0c;且|z-1|是|z|和|z-2|的等比中項&#xff0c;求|z|? 【來源】 2003高考數學全國卷&#xff0c;解答題首題&#xff0c;總第17題。 【解答】 解&#xff1a; 由復數輻長輻角定義有 zr*(Cos60iSin60) 據等比中項定義有&#xff1…

觀點 | 科技企業到了品牌建設的歷史性窗口期

隨著全球科技產業的飛速發展&#xff0c;科技型企業作為推動技術創新和經濟發展的重要力量&#xff0c;正面臨著前所未有的機遇與挑戰。近年來&#xff0c;中國科技行業保持了快速增長的態勢。根據國家統計局的數據&#xff0c;2023年全國研究與試驗發展&#xff08;R&D&am…

影像組學5:Radiomics Score的計算

Rad-score&#xff08;全稱 Radiomics score&#xff0c;影像組學評分&#xff09;是通過數學模型將影像組學提取的多個特征整合為一個綜合性指標&#xff0c;從而簡化臨床分析與決策。 前文已介紹影像組學的病灶分割、特征提取及篩選流程&#xff0c;本節將重點闡述 Rad-scor…

使用Appium在iOS上實現自動化

安裝 Appium npm install -g appium檢測 Appium 是否安裝成功 appium --version安裝 Appium Doctor npm install appium-doctor -g安裝 ios 測試驅動 appium driver install xcuitest檢測 iOS 環境是否正常 appium-doctor --ios安裝 ideviceinstaller brew install idevi…

JPA全面指南:使用步驟、語法詳解與實戰案例

一、JPA概述與核心概念 1.1 什么是JPA&#xff1f; Java Persistence API&#xff08;JPA&#xff09;是Java EE和Java SE平臺上的ORM&#xff08;對象關系映射&#xff09;標準規范&#xff0c;它簡化了Java應用程序與數據庫的交互過程。JPA不是具體的實現&#xff0c;而是一…

Django框架認證系統默認在登錄成功后嘗試重定向到/accounts/profile/

這個404錯誤是因為Django的認證系統默認在登錄成功后嘗試重定向到/accounts/profile/,但你的項目中沒有配置這個URL。以下是完整解決方案: 方法一:設置登錄重定向路徑(推薦) 在settings.py中添加以下配置: # settings.py LOGIN_REDIRECT_URL = /dashboard/ # 替換為你…

QT實現右鍵菜單欄

1.所需頭文件 #include <QPoint> // QPoint 類型 #include <QWidget> // mapFromGlobal() 的父類 #include <QEvent> // event->globalPos() 的來源&#xff08;如 QMouseEvent&#xff09; #include <QContextMenuEvent> // 用于 QContex…

華為云Flexus+DeepSeek征文|華為云CCE容器高可用部署Dify LLM應用后的資源釋放指南

目錄 前言 1 高可用部署帶來的資源特性 1.1 涉及的核心資源組件 1.2 高可用部署的代價 2 正確釋放資源的重要性 3 使用資源編排釋放資源 3.1 進入資源編排頁面 3.2 兩種刪除方式解析 3.3 推薦操作流程 4 手動刪除各類云資源 4.1 使用資源頁面集中管理 4.2 分服務刪…

yum查看歷史操作

在 Red Hat/CentOS 系統中&#xff0c;可以使用 yum history 命令查看和管理 YUM/DNF 的歷史操作記錄。以下是詳細使用方法&#xff1a; 1. 查看完整歷史記錄 sudo yum history list # 或簡寫 sudo yum history輸出示例&#xff1a; ID | 命令行 | 日期與時間…

Python-Flask實現登錄

Python-Flask實現登錄 Python-Flask實現登錄項目結構Flask藍圖路由項目代碼 Python-Flask實現登錄 項目結構 Flask藍圖路由 from flask import Blueprint, render_template, request, sessionac Blueprint(account, __name__)ac.route(/login, methods[GET, POST]) def logi…

libcuckoo 介紹和使用指南

文章目錄 libcuckoo 介紹和使用指南什么是 libcuckoo&#xff1f;主要特點安裝方法從源碼安裝 基本使用方法創建哈希表并發操作示例 高級功能自定義哈希函數和比較函數更新操作大小和統計信息 性能考慮適用場景注意事項 libcuckoo 介紹和使用指南 libcuckoo 是一個高性能、并發…

TIA Portal V20HMI仿真時數值無法寫入虛擬plc解決教程

在博圖 V20 中使用 S7-PLCSIM Advanced 仿真 S7-1500 Advanced V5.0 PLC&#xff0c;同時使用 WinCC Runtime Advanced 仿真 HMI 時出現“連接中斷”且無法寫入數值&#xff0c;而單獨使用 S7-PLCSIM (Classic) 仿真 PLC 正常&#xff0c;這是一個非常典型且令人困擾的問題。問…