Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Chỉ mục đã lọc và Cột BAO GỒM

Các chỉ mục được lọc có sức mạnh đáng kinh ngạc, nhưng tôi vẫn thấy có một số nhầm lẫn về chúng - đặc biệt là về các cột được sử dụng trong các bộ lọc và điều gì sẽ xảy ra khi bạn muốn thắt chặt các bộ lọc.

Một câu hỏi gần đây trên dba.stackexchange đã yêu cầu trợ giúp về lý do tại sao các cột được sử dụng trong bộ lọc của chỉ mục đã lọc nên được đưa vào các cột 'được bao gồm' của chỉ mục. Câu hỏi tuyệt vời - ngoại trừ việc tôi cảm thấy như nó bắt đầu trên một tiền đề kém, bởi vì những cột đó không nên được đưa vào chỉ mục . Có, họ giúp, nhưng không phải theo cách mà câu hỏi dường như gợi ý.

Để giúp bạn xem xét chính câu hỏi, đây là bản tóm tắt nhanh:

Để đáp ứng truy vấn này…

 CHỌN Id, Tên hiển thị TỪ Người dùng Ở ĐÂU Danh tiếng > 400000; 

… Chỉ mục được lọc sau đây là khá tốt:

 TẠO CHỈ SỐ KHÔNG ĐƯỢC ĐIỀU CHỈNH DUY NHẤT Người dùng_400k_ClubON dbo.Users (Tên hiển thị, Id) BAO GỒM (Danh tiếng) Ở đâu Danh tiếng > 400000; 

Nhưng mặc dù đã có chỉ mục này, Trình tối ưu hóa Truy vấn đề xuất chỉ mục sau nếu giá trị được lọc được thắt chặt, chẳng hạn như 450000.

 TẠO CHỈ SỐ CHỈ SỐ KHÔNG ĐƯỢC ĐIỀU CHỈNH 

Tôi đang diễn giải câu hỏi một chút ở đây, bắt đầu bằng cách đề cập đến tình huống này và sau đó xây dựng một ví dụ khác, nhưng ý tưởng thì giống nhau. Tôi chỉ không muốn làm mọi thứ phức tạp hơn bằng cách liên quan đến một bảng riêng biệt.

Điểm là - chỉ số do QO đề xuất là chỉ số ban đầu nhưng đã bật lên. Chỉ mục ban đầu có Danh tiếng trong danh sách BAO GỒM và Tên hiển thị và Id là các cột chính, trong khi chỉ mục được đề xuất mới thì ngược lại với Danh tiếng là cột chính và Tên hiển thị &ID trong BAO GỒM. Hãy xem tại sao.

Câu hỏi đề cập đến một bài đăng của Erik Darling, nơi anh ấy giải thích rằng anh ấy đã điều chỉnh truy vấn '450.000' ở trên bằng cách đặt Danh tiếng vào cột BAO GỒM. Erik cho thấy rằng không có Danh tiếng trong danh sách BAO GỒM, một truy vấn lọc đến giá trị cao hơn của Danh tiếng cần phải thực hiện Tra cứu (xấu!), Hoặc thậm chí có thể từ bỏ hoàn toàn chỉ mục đã lọc (thậm chí có thể tệ hơn). Ông kết luận rằng việc có cột Danh tiếng trong danh sách BAO GỒM cho phép SQL có số liệu thống kê, để nó có thể đưa ra lựa chọn tốt hơn và cho thấy rằng với Danh tiếng trong BAO GỒM, nhiều truy vấn lọc dựa trên các giá trị Danh tiếng cao hơn đều quét chỉ mục đã lọc của anh ta.

Trong một câu trả lời cho câu hỏi dba.stackexchange, Brent Ozar chỉ ra rằng những cải tiến của Erik không đặc biệt tuyệt vời vì chúng gây ra Quét. Tôi sẽ quay lại vấn đề đó, vì bản thân nó là một điểm thú vị và hơi không chính xác.

Trước tiên, hãy nghĩ một chút về các chỉ mục nói chung.

Một chỉ mục cung cấp một cấu trúc có thứ tự cho một tập dữ liệu. (Tôi có thể hiểu sai và chỉ ra rằng việc đọc qua dữ liệu trong một chỉ mục từ đầu đến cuối có thể chuyển bạn từ trang này sang trang khác theo một cách có vẻ lộn xộn, nhưng vẫn khi bạn đang đọc qua các trang, theo dõi các con trỏ từ một trang đến tiếp theo, bạn có thể tự tin rằng dữ liệu được sắp xếp theo thứ tự. Trong mỗi trang, bạn thậm chí có thể nhảy xung quanh để đọc dữ liệu theo thứ tự, nhưng có một danh sách hiển thị cho bạn những phần (vị trí) của trang nên được đọc theo thứ tự nào. Thực sự không có ích lợi gì đối với tôi ngoại trừ việc trả lời những người có nội dung ngang ngược, những người sẽ nhận xét nếu tôi không làm như vậy.)

Và thứ tự này là theo các cột chính - đó là điều dễ dàng mà mọi người đều nhận được. Nó hữu ích không chỉ để có thể tránh sắp xếp lại dữ liệu sau này, mà còn để có thể nhanh chóng xác định vị trí bất kỳ hàng hoặc phạm vi hàng cụ thể nào theo các cột đó.

Các cấp độ lá của chỉ mục chứa các giá trị trong bất kỳ cột nào trong danh sách INCLUDE hoặc trong trường hợp Chỉ mục được phân nhóm, các giá trị trên tất cả các cột trong bảng (ngoại trừ các cột được tính không liên tục). Các cấp độ khác trong chỉ mục chỉ chứa các cột khóa và (nếu chỉ mục không phải là duy nhất) địa chỉ duy nhất của hàng - đó là các khóa của chỉ mục được phân nhóm (với trình thống nhất của hàng nếu chỉ mục được phân nhóm cũng không phải là duy nhất ) hoặc giá trị RowID cho một đống, đủ để cho phép dễ dàng truy cập vào tất cả các giá trị cột khác cho hàng. Các cấp độ lá cũng bao gồm tất cả thông tin "địa chỉ".

Nhưng đó không phải là một chút thú vị cho bài đăng này. Một chút thú vị cho bài đăng này là ý tôi muốn nói đến "một tập hợp dữ liệu". Hãy nhớ rằng tôi đã nói "Chỉ mục cung cấp cấu trúc có thứ tự cho một tập dữ liệu ".

Trong một chỉ mục được phân nhóm, tập hợp dữ liệu đó là toàn bộ bảng, nhưng nó có thể là một cái gì đó khác. Bạn có thể đã hình dung ra cách hầu hết các chỉ mục không phân cụm không liên quan đến tất cả các cột của bảng. Đây là một trong những điều làm cho các chỉ mục không phân cụm trở nên hữu ích, bởi vì chúng thường nhỏ hơn rất nhiều so với bảng bên dưới.

Trong trường hợp chế độ xem được lập chỉ mục, tập dữ liệu của chúng tôi có thể là kết quả của toàn bộ truy vấn, bao gồm các phép nối trên nhiều bảng! Đó là cho một bài đăng khác.

Nhưng trong một chỉ mục được lọc, nó không chỉ là bản sao của một tập hợp con các cột mà còn là một tập hợp con các hàng. Vì vậy, trong ví dụ ở đây, chỉ số này chỉ dựa trên những người dùng có hơn 400 nghìn danh tiếng.

 TẠO CHỈ SỐ DUY NHẤT KHÔNG CHỈNH SỬA Người dùng_400k_Club_NoIncludeON dbo.Users (Tên hiển thị, Id) TẠI ĐÂU Danh tiếng > 400000; 

Chỉ số này lấy những người dùng có hơn 400 nghìn danh tiếng và sắp xếp họ theo Tên và Tên hiển thị. Nó có thể là duy nhất vì (giả sử) cột Id đã là duy nhất. Nếu bạn thử thứ gì đó tương tự trên bàn của mình, bạn có thể cần phải cẩn thận với điều đó.

Nhưng tại thời điểm này, chỉ mục không quan tâm Danh tiếng là gì đối với mỗi người dùng - nó chỉ quan tâm liệu Danh tiếng có đủ cao để có trong chỉ mục hay không. Nếu danh tiếng của người dùng được cập nhật và nó vượt quá ngưỡng mà Tên và Id hiển thị của người dùng sẽ được chèn vào chỉ mục. Nếu nó giảm xuống dưới, nó sẽ bị xóa khỏi chỉ mục. Nó giống như việc có một bảng riêng cho những người có trình độ cao, ngoại trừ việc chúng tôi đưa mọi người vào bảng đó bằng cách tăng giá trị Danh tiếng của họ trên ngưỡng 400 nghìn trong bảng bên dưới. Nó có thể làm điều này mà không cần phải thực sự lưu trữ giá trị Danh tiếng.

Vì vậy, bây giờ nếu chúng tôi muốn tìm những người có ngưỡng trên 450 nghìn, chỉ số đó đang thiếu một số thông tin.

Chắc chắn, chúng tôi có thể tự tin nói rằng tất cả những người mà chúng tôi sẽ tìm thấy đều có trong chỉ mục đó - nhưng bản thân chỉ mục này không chứa đủ thông tin để lọc thêm về Danh tiếng. Nếu tôi nói với bạn, tôi đã có một danh sách theo thứ tự bảng chữ cái gồm các phim đoạt giải Oscar Phim hay nhất từ ​​những năm 1990 (American Beauty, Braveheart, Dances With Wolves, English Patient, Forrest Gump, Schindler's List, Shakespeare in Love, Silence of the Lambs, Titanic, Unforgiven) , thì tôi có thể đảm bảo với bạn rằng những người chiến thắng cho năm 1994-1996 sẽ là một tập hợp con của những người đó, nhưng tôi không thể trả lời câu hỏi nếu không tìm hiểu thêm một số thông tin trước.

Rõ ràng là chỉ mục đã lọc của tôi sẽ hữu ích hơn nếu tôi bao gồm năm và thậm chí có khả năng cao hơn nếu năm là một cột quan trọng, vì truy vấn mới của tôi muốn tìm các chỉ số cho năm 1994-1996. Nhưng có lẽ tôi đã thiết kế chỉ mục này xung quanh một truy vấn để liệt kê tất cả các bộ phim từ những năm 1990 theo thứ tự bảng chữ cái. Truy vấn đó không quan tâm đến năm thực tế là bao nhiêu, chỉ quan tâm đến năm 1990 hay không, và tôi thậm chí không cần trả lại năm - chỉ tiêu đề - vì vậy tôi có thể quét chỉ mục đã lọc của mình để lấy kết quả. Đối với truy vấn đó, tôi thậm chí không cần sắp xếp lại kết quả hoặc tìm điểm bắt đầu - chỉ mục của tôi thực sự hoàn hảo.

Một ví dụ thực tế hơn về việc không quan tâm đến giá trị của cột trong bộ lọc đang ở trạng thái, chẳng hạn như:

 WHERE IsActive =1 

Tôi thường xuyên thấy mã di chuyển dữ liệu từ bảng này sang bảng khác khi các hàng ngừng 'hoạt động'. Mọi người không muốn các hàng cũ lộn xộn trong bảng của họ và họ nhận ra rằng dữ liệu 'nóng' của họ chỉ là một tập hợp con nhỏ của tất cả dữ liệu của họ. Vì vậy, họ chuyển dữ liệu làm mát của mình vào bảng Lưu trữ, giữ cho bảng Hoạt động của họ nhỏ.

Một chỉ mục được lọc có thể làm điều này cho bạn. Đằng sau hậu trường. Ngay sau khi bạn cập nhật hàng và thay đổi cột IsActive đó thành một cái gì đó khác với 1. Nếu bạn chỉ quan tâm đến việc có dữ liệu hoạt động trong hầu hết các chỉ mục của mình, thì các chỉ mục được lọc là lý tưởng. Nó thậm chí sẽ đưa các hàng trở lại chỉ mục nếu giá trị IsActive thay đổi trở lại 1.

Nhưng bạn không cần phải đặt IsActive trong danh sách BAO GỒM để đạt được điều này. Tại sao bạn muốn lưu trữ giá trị - bạn đã biết giá trị là gì - nó là 1! Trừ khi bạn đang yêu cầu trả lại giá trị mà bạn không cần nó. Và tại sao bạn lại trả về giá trị khi bạn đã biết rằng câu trả lời là 1, phải không ?! Ngoại trừ điều đó một cách bực bội, các số liệu thống kê mà Erik đề cập đến trong bài đăng của anh ấy sẽ có lợi khi nằm trong danh sách BAO GỒM. Bạn không cần nó cho truy vấn, nhưng bạn nên bao gồm nó để thống kê.

Hãy cùng suy nghĩ về những gì Trình tối ưu hóa truy vấn cần làm để tìm ra tính hữu ích của chỉ mục.

Trước khi nó có thể làm được nhiều điều, nó cần phải xem xét liệu chỉ số có phải là một ứng cử viên hay không. Việc sử dụng một chỉ mục sẽ chẳng ích gì nếu nó không có tất cả các hàng có thể cần thiết - trừ khi chúng ta có một cách hiệu quả để lấy phần còn lại. Nếu tôi muốn những bộ phim từ năm 1985-1995, thì chỉ số về những bộ phim những năm 1990 của tôi là khá vô nghĩa. Nhưng đối với những năm 1994-1996, có lẽ nó không tệ.

Tại thời điểm này, cũng giống như bất kỳ việc xem xét chỉ mục nào, tôi cần suy nghĩ về việc liệu nó có đủ giúp ích cho việc tìm kiếm dữ liệu và đưa nó vào thứ tự giúp thực hiện phần còn lại của truy vấn hay không (có thể là đối với Kết hợp hợp nhất, Tổng hợp luồng, đáp ứng ĐẶT HÀNG BẰNG hoặc nhiều lý do khác). Nếu bộ lọc truy vấn của tôi khớp chính xác với bộ lọc chỉ mục, thì tôi không cần phải lọc thêm - chỉ cần sử dụng chỉ mục là đủ. Điều này nghe có vẻ tuyệt vời, nhưng nếu nó không khớp chính xác, nếu bộ lọc truy vấn của tôi chặt chẽ hơn bộ lọc chỉ mục (như ví dụ năm 1994-1996 của tôi hoặc 450.000 của Erik), tôi sẽ cần có các giá trị Năm hoặc giá trị Danh tiếng để kiểm tra - hy vọng nhận được chúng từ INCLUDEd ở cấp độ lá hoặc một nơi nào đó trong các cột chính của tôi. Nếu chúng không có trong chỉ mục, tôi sẽ phải thực hiện Tra cứu cho mọi hàng trong chỉ mục đã lọc của mình (và lý tưởng nhất là có ý tưởng về số lần Tra cứu của tôi sẽ được gọi, đó là số liệu thống kê mà Erik muốn cột được bao gồm cho).

Lý tưởng nhất là bất kỳ chỉ mục nào tôi định sử dụng đều được sắp xếp đúng thứ tự (thông qua các phím), BAO GỒM tất cả các cột tôi cần trả về và được lọc trước để chỉ những hàng tôi cần. Đó sẽ là chỉ mục hoàn hảo và kế hoạch thực hiện của tôi sẽ là Quét.

Đúng vậy, một QUÉT. Không phải Tìm kiếm, mà là Quét. Nó sẽ bắt đầu trên trang đầu tiên của chỉ mục của tôi và tiếp tục cung cấp cho tôi các hàng cho đến khi tôi có đủ số lượng tôi cần hoặc cho đến khi không còn hàng nào để trả lại. Không bỏ qua bất kỳ, không sắp xếp chúng - chỉ cho tôi các hàng theo thứ tự.

A Seek sẽ gợi ý rằng tôi không cần toàn bộ chỉ mục, có nghĩa là tôi đang lãng phí tài nguyên trong việc duy trì phần đó của chỉ mục và để truy vấn nó, tôi phải tìm điểm bắt đầu và tiếp tục kiểm tra các hàng để xem liệu tôi có kết thúc hay không. Nếu bản Quét của tôi có Vị trí thì chắc chắn, tôi đang phải xem qua (và kiểm tra) nhiều dữ liệu hơn mức tôi cần, nhưng nếu bộ lọc chỉ mục của tôi hoàn hảo, thì Trình tối ưu hóa truy vấn sẽ nhận ra điều đó và không phải thực hiện các kiểm tra đó .

Lời kết

INCLUDE không quan trọng đối với các chỉ mục được lọc. Chúng hữu ích để cung cấp quyền truy cập dễ dàng vào các cột có thể hữu ích cho truy vấn của bạn và nếu bạn tình cờ thắt chặt những gì trong chỉ mục được lọc của mình theo bất kỳ cột nào, cho dù nó có được đề cập trong bộ lọc hay không, bạn nên cân nhắc việc đưa cột đó vào hỗn hợp. Nhưng tại thời điểm đó, bạn nên hỏi liệu bộ lọc chỉ mục của bạn có phải là bộ lọc phù hợp hay không, bạn nên có những gì khác trong danh sách INCLUDE của mình và thậm chí (các) cột chính nên là gì. Các truy vấn của Erik không hoạt động tốt vì anh ấy cần thông tin không có trong chỉ mục, mặc dù anh ấy đã đề cập đến cột trong bộ lọc. Anh ấy cũng thấy cách sử dụng tốt cho số liệu thống kê và tôi vẫn khuyến khích bạn bao gồm các cột bộ lọc vì lý do đó. Nhưng việc đặt chúng vào BAO GỒM không cho phép chúng đột ngột bắt đầu thực hiện Tìm kiếm, bởi vì đó không phải là cách bất kỳ chỉ mục nào hoạt động, cho dù có lọc hay không.

Tôi muốn bạn, độc giả, hiểu rõ các chỉ mục đã lọc. Chúng cực kỳ hữu ích và khi bạn bắt đầu hình dung chúng giống như các bảng theo quyền riêng của chúng, có thể trở thành một phần của thiết kế cơ sở dữ liệu tổng thể của bạn. Chúng cũng là lý do để luôn sử dụng cài đặt ANSI_NULLs và QUOTED_IDENTIFIER, vì bạn sẽ gặp lỗi từ chỉ mục được lọc trừ khi các cài đặt đó được BẬT, nhưng hy vọng bạn đã đảm bảo rằng chúng luôn bật.

Ồ, và những bộ phim đó là Forrest Gump, Braveheart và The English Patient.

@rob_farley


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Thả so với Cắt ngắn trong SQL

  2. Các thay đổi đối với phân vùng từ thiện có thể không thành công

  3. Xem các ngày lễ bằng con mắt của Người lập mô hình dữ liệu

  4. Cách tránh chèn các bản ghi trùng lặp trong truy vấn SQL INSERT (5 cách dễ dàng)

  5. Khởi tạo tệp tức thì:Tác động trong quá trình thiết lập