[英]What is the difference clustered vs non-clustered index when we calculate number of accesses pages?
Employee (Ssn, FirstName, LastName, Gender, Age, Salary, DepartmentID) 假設: • 沒有索引。 • 總共有8,000,000 行。 • 250,000 行在 2,500 到 3,000 的薪水范圍內。 • 每頁有100 行。 • 400 個索引行適合一個非聚集索引葉頁。 在給定假設的情況下,下列查詢的頁面訪問次數是多少? 分別考慮每種情況。 a) Select Ssn From Employee Where Salary>2500 and Salary<3000 and DepartmentID=1; b) 在 Employee (Salary) 上創建聚簇索引 ixEmpSal; Select Ssn From Employee Where Salary>2500 and Salary<3000 and Gender='M';
我有一個員工表,我想知道任何查詢的頁面訪問次數。我不明白以下問題的某些部分
1-) 我如何使用這部分“適合非聚集索引葉頁的 400 個索引行”。 如果我將問題的“非聚集索引”部分變成“聚集索引”會發生什么
2-) 在問題的一部分中數據庫是否分別搜索每個和部分?我的意思是例如 satabase 搜索 Salary>2500 然后開始搜索 Salary<3000 然后搜索 DepartmenId
ps:我不太了解理論解釋你能用例子解釋嗎
首先,讓我為查詢推薦最佳索引:
a) Select Ssn From Employee Where Salary>2500 and Salary<3000 and DepartmentID=1;
INDEX(DepartmentID, Salary) -- in this order
(這么寫,2500和3000都不算了,真的要嗎?)
b) 在 Employee (Salary) 上創建聚簇索引 ixEmpSal; Select Ssn From Employee Where Salary>2500 and Salary<3000 and Gender='M';
在 MySQL 中,唯一的聚集索引是PRIMARY KEY
。 並且,PK必須是唯一的。 (這使您的問題 1 無效)因此,該索引可能不可行。 相反,經常使用代理人。
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
INDEX(gender, salary)
(我稍后會提出另一種選擇。)
MySQL 對數據(按 PK 排序)和每個輔助(非集群) INDEX
使用 B+樹。 二級索引行有一個 PK 的副本來查找該行的 rest。
如果沒有好的索引,MySQL 將掃描整個表(“表掃描”)。 因為它是 B+Tree,而不僅僅是 BTree,所以它將只讀取葉節點(在通過向下鑽取樹一次找到“第一”行之后)。 所以閱讀的頁數大約是 8,000,000/100 + 4-1。
log-base-100 (8M) = 4,因此 B+Tree 的數據深度約為 4 層。 對於每個二級索引,log-base-400 (8M) ~= 3 級。
INDEX(Salary)
:250,000 / 400 ~= 625 個索引塊加上 4 * 250,000 個數據塊來檢查部門或性別,以及獲取所需的任何其他列(SSN,如前所述)。 數據塊(在這種情況下)將被大量緩存,尤其是非葉節點。Select b假設一家平等主義的公司,50% 的性別=M。 現在我們正在查看 250,000 * 50% / 400 ~= 313 個索引塊。 如果需要,還有一半的數據塊。
InnoDB 使用 16KB 塊。 因此乘以它得到磁盤上和/或 buffer_pool 中的字節數(假設它都可以被緩存)。 為非葉節點添加大約 1%。
但是......一旦它在索引中找到“行”,它就需要進入數據 B+Tree 以獲得所需的任何其他列。 這將涉及向下鑽取數據的 B+ 樹( +
在這里無關緊要)以獲取每一行。 現在我們正在查看每個獲取的數據行 4 頁——但大部分都被緩存了。
一種不同的技術
PRIMARY KEY(Salary, id), -- cluster on Salary
INDEX(id) -- to keep AUTO_INCREMENT happy
-- and neither of my indexes
現在您的兩個查詢只需要查看數據 B+Tree。 Select b 是 250,000 / 100 ~= 2500 個塊並且使用 B_Tree 的+
並且不使用任何二級索引。 它將掃描所有 250K 行以查看哪些與 Dept 或 Gender 匹配,然后 SSN 立即可用。
請注意,將id
添加到Salary
可提供 PK 所需的唯一性。 所以這更接近你問的問題。
節點很少滿InnoDB 的塊通常在 1/2 到 15/16 之間滿,平均約為 70%。 這是因為來自更新/刪除/插入的塊拆分等。 這可能會混淆您的“100”和“400”,但不會混淆我提出的結論。
(你的問題 2)MySQL沒有在單個INDEXes
中使用兩個索引。(極少數例外。)我建議的復合(多列)索引甚至比嘗試使用兩個索引更好。
(如果 SSN 位於您的數據庫中,安全性就更為重要。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.