Tôi có nên lập chỉ mục một trường bit trong SQL Server không?


99

Tôi nhớ đã từng đọc rằng việc lập chỉ mục một trường có số lượng thấp (số lượng giá trị khác biệt thấp) không thực sự đáng làm. Tôi thừa nhận rằng tôi không biết đủ về cách các chỉ mục hoạt động để hiểu tại sao lại như vậy.

Vì vậy, điều gì sẽ xảy ra nếu tôi có một bảng với 100 triệu hàng trong đó và tôi đang chọn các bản ghi trong đó trường bit là 1? Và giả sử rằng tại bất kỳ thời điểm nào, chỉ có một số ít các bản ghi mà trường bit là 1 (trái ngược với 0). Nó có giá trị lập chỉ mục trường bit đó hay không? Tại sao?

Tất nhiên tôi chỉ có thể kiểm tra nó và kiểm tra kế hoạch thực hiện, và tôi sẽ làm điều đó, nhưng tôi cũng tò mò về lý thuyết đằng sau nó. Khi nào thì cardinality quan trọng và khi nào thì không?


Đây có phải là một truy vấn phổ biến không? Nó có thể đáng giá khi tìm kiếm "số ít" các bản ghi nhưng sẽ không giúp bạn nhiều ở các hàng khác. Có những cách nào khác để xác định dữ liệu?
jason saldo 23/10/08

4
Mặc dù tôi không nghĩ rằng tôi sẽ chỉ mục JUST một cột bit của chính nó, nhưng rất phổ biến là bao gồm các cột bit như một phần của chỉ mục ghép. Một ví dụ đơn giản sẽ là chỉ mục trên ACTIVE, LASTNAME thay vì chỉ họ, khi ứng dụng của bạn hầu như luôn tìm kiếm khách hàng tích cực.
BradC 23/10/08

"Tôi nhớ đã đọc tại một thời điểm rằng việc lập chỉ mục một trường có bản số thấp (số lượng giá trị riêng biệt thấp) không thực sự đáng làm" Điều đó bởi vì SQL Server hầu như sẽ luôn thấy hiệu quả hơn khi chỉ thực hiện quét bảng hơn là đọc mục lục. Vì vậy, về cơ bản chỉ mục của bạn sẽ không bao giờ được sử dụng và thật lãng phí để duy trì nó. Như những người khác đã nói nó có thể ổn trong một chỉ số phức hợp.
DJ.

5
Tôi sẽ không đồng ý. Nếu phân phối của bạn là 50/50, thì bạn sẽ không bao giờ sử dụng chỉ mục, vì việc quét bảng sẽ nhanh hơn. Tuy nhiên, nếu bạn chỉ có 5, 1 giá trị, và 1 triệu 0 giá trị, nó sẽ rất có khả năng sử dụng các chỉ số khi tìm kiếm 1.
Kibbee

1
Trong ví dụ mà bạn đưa ra, tôi sẽ nghiêng về việc đặt LastName trước. Nó phụ thuộc vào khối lượng công việc truy vấn cụ thể, nhưng nói chung có cột chọn lọc hơn trước, có nghĩa là chỉ mục có nhiều khả năng được sử dụng hơn.
Mitch Wheat

Câu trả lời:


72

Hãy xem xét chỉ mục là gì trong SQL - và chỉ mục thực sự là một phần bộ nhớ trỏ đến các phần bộ nhớ khác (tức là con trỏ đến các hàng). Chỉ mục được chia thành các trang để các phần của chỉ mục có thể được tải và tải xuống từ bộ nhớ tùy thuộc vào cách sử dụng.

Khi bạn yêu cầu một tập hợp các hàng, SQL sử dụng chỉ mục để tìm các hàng nhanh hơn so với việc quét bảng (xem mọi hàng).

SQL có các chỉ mục được phân cụm và không phân cụm. Hiểu biết của tôi về các chỉ mục được phân nhóm là chúng nhóm các giá trị chỉ mục tương tự vào cùng một trang. Bằng cách này khi bạn yêu cầu tất cả các hàng khớp với một giá trị chỉ mục, SQL có thể trả về các hàng đó từ một trang bộ nhớ được phân nhóm. Đây là lý do tại sao cố gắng phân cụm chỉ mục một cột GUID là một ý tưởng tồi - bạn không cố gắng phân cụm các giá trị ngẫu nhiên.

Khi bạn lập chỉ mục một cột số nguyên, chỉ mục của SQL chứa một tập hợp các hàng cho mỗi giá trị chỉ mục. Nếu bạn có phạm vi từ 1 đến 10, thì bạn sẽ có 10 con trỏ chỉ mục. Tùy thuộc vào số lượng hàng có, điều này có thể được phân trang khác nhau. Nếu truy vấn của bạn tìm kiếm chỉ mục khớp với "1" và sau đó trong đó Tên chứa "Fred" (giả sử cột Tên không được lập chỉ mục), SQL sẽ lấy tập hợp các hàng khớp với "1" rất nhanh, sau đó quét bảng để tìm phần còn lại.

Vì vậy, những gì SQL thực sự đang làm là cố gắng giảm tập hợp làm việc (số hàng) mà nó phải lặp lại.

Khi bạn lập chỉ mục một trường bit (hoặc một số phạm vi hẹp), bạn chỉ giảm tập hợp làm việc theo số hàng phù hợp với giá trị đó. Nếu bạn có một số lượng nhỏ các hàng phù hợp, nó sẽ làm giảm tập hợp làm việc của bạn rất nhiều. Đối với một số lượng lớn các hàng có phân phối 50/50, nó có thể giúp bạn tăng hiệu suất rất ít so với việc giữ cho chỉ mục được cập nhật.

Lý do mà mọi người đều nói là kiểm tra là vì SQL chứa một trình tối ưu hóa rất thông minh và phức tạp có thể bỏ qua một chỉ mục nếu nó quyết định việc quét bảng nhanh hơn hoặc có thể sử dụng sắp xếp, hoặc có thể sắp xếp các trang bộ nhớ, tuy nhiên nó rất thích.


Vì vậy, có vẻ như nếu tôi chỉ có một số ít hàng trong đó trường bit là 1 (ví dụ: theo dõi "IsProcessed"), thì một chỉ mục sẽ tốt vì nó sẽ sắp xếp chúng theo giá trị và sau đó có thể chọn nhỏ làm việc thiết lập rất nhanh chóng. Nếu bạn đồng ý, hãy thêm vào và tôi sẽ chấp nhận nó.
jeremcc 23/10/08

2
Ý tôi muốn nói trong nhận xét trước đây của tôi là tuyên bố này: "Khi bạn lập chỉ mục một trường bit (hoặc một số phạm vi hẹp), bạn chỉ giảm một nửa tập hợp làm việc" là không đúng nếu phân phối có trọng số lớn về một giá trị. Nhưng tôi thích phần còn lại của câu trả lời của bạn, vì vậy nếu bạn sửa điều đó, tôi sẽ chấp nhận nó.
jeremcc 23/10/08

1
Làm xong. Tôi đã nghĩ rằng đối với một triệu hàng, một trường bit sẽ có phân phối 50%, nhưng bạn nói đúng rằng đối với một không gian vấn đề cụ thể, nó có thể làm giảm tập hợp làm việc rất nhiều.
Geoff Cox

Bạn nên xem xét các kế hoạch thực thi có và không có chỉ mục và xem liệu chỉ mục có đang được sử dụng hay không và liệu nó có thực sự làm giảm chi phí cho các truy vấn của bạn hay không. Dễ dàng và khoa học!
onupdatecascade

Điều gì về lập chỉ mục một trường bit + một trường khác? Ví dụ. trong nhật ký hoạt động web, một chỉ mục sẽ lập chỉ mục dấu thời gian, nhưng một chỉ mục hữu ích khác có thể nằm trên trường bit "IsHTTPS" + dấu thời gian, để xem nhanh tất cả các hành động https. Điều đó cũng sẽ không hiệu quả?
ingredient_15939

19

Tôi chỉ gặp câu hỏi này bằng cách khác. Giả sử rằng tuyên bố của bạn rằng chỉ một số ít bản ghi giả định giá trị 1 (và đó là những bản ghi bạn quan tâm), thì một chỉ mục được lọc có thể là một lựa chọn tốt. Cái gì đó như:

create index [IX_foobar] on dbo.Foobar (FooID) where yourBitColumn = 1

Điều này sẽ tạo ra một chỉ mục nhỏ hơn đáng kể mà trình tối ưu hóa đủ thông minh để sử dụng khi đó là một vị từ trong truy vấn của bạn.


1
Cần lưu ý rằng vị từ trong truy vấn phải được mã hóa cứng thành giá trị trong chỉ mục được lọc. Nếu bạn chuyển giá trị vào một tham số yourBitColumn = @value, thì trình tối ưu hóa không thể xác định liệu chỉ mục đã lọc có thể sử dụng được hay không.
geofftnz

2
Có nhiều cách để giải quyết vấn đề này, nhưng bạn đúng; trình tối ưu hóa cần đảm bảo tại thời điểm biên dịch rằng các giá trị cho bất kỳ vị từ nào khớp với vị từ chỉ mục đã lọc là tĩnh / bất biến vì công việc của trình tối ưu hóa là tạo một kế hoạch chung sẽ hoạt động cho bất kỳ tập hợp thông số nào.
Ben Thul

9

100 triệu bản ghi chỉ với một số ít có trường bit được đặt thành 1? Có, tôi nghĩ việc lập chỉ mục trường bit chắc chắn sẽ tăng tốc độ truy vấn các bản ghi bit = 1. Bạn sẽ nhận được thời gian tìm kiếm logarit từ chỉ mục và sau đó chỉ chạm vào vài trang có bản ghi bit = 1. Nếu không, bạn phải chạm vào tất cả các trang của bảng kỷ lục 100 triệu.

Sau đó, một lần nữa, tôi chắc chắn không phải là một chuyên gia cơ sở dữ liệu và có thể thiếu một cái gì đó quan trọng.


8

Nếu phân phối của bạn khá nổi tiếng và không cân bằng, chẳng hạn như 99% các hàng là bit = 1 và 1% là bit = 0, khi bạn thực hiện mệnh đề WHERE với bit = 1, quá trình quét toàn bộ bảng sẽ diễn ra cùng lúc với quét chỉ mục. Nếu bạn muốn truy vấn nhanh trong đó bit = 0, cách tốt nhất mà tôi biết là tạo chỉ mục đã lọc, thêm mệnh đề WHERE bit = 0. Bằng cách đó, chỉ mục đó sẽ chỉ lưu trữ hàng 1%. Sau đó, thực hiện WHERE bit = 0 sẽ chỉ đơn giản là để trình tối ưu hóa truy vấn chọn chỉ mục đó và tất cả các hàng từ nó sẽ là bit = 0. Bạn cũng có lợi khi có một lượng rất nhỏ không gian đĩa cần thiết để so sánh một chỉ mục đầy đủ trên bit .


2
Nếu 99% các hàng là bit = 1, trình tối ưu hóa nên bỏ qua chỉ mục và thực hiện quét bảng. Việc sử dụng chỉ mục sẽ thực sự tệ hơn quét bảng, ít nhất là trên ổ đĩa quay, nhiều I / O hơn và các lần đọc không liên tiếp từ đĩa. Chỉ mục được lọc (tương đương Postgres: chỉ mục một phần) là cách để thực hiện. Tôi đoán vì đã nhiều năm sau câu hỏi, câu trả lời này không nhận được số phiếu bầu xứng đáng.
Andrew Lazarus,

7

Mặc dù tôi không nghĩ rằng tôi sẽ chỉ mục JUST một cột bit của chính nó, nhưng rất phổ biến là bao gồm các cột bit như một phần của chỉ mục ghép.

Một ví dụ đơn giản sẽ là chỉ mục trên ACTIVE, LASTNAME thay vì chỉ họ, khi ứng dụng của bạn hầu như luôn tìm kiếm khách hàng tích cực.


7
Trong ví dụ mà bạn đưa ra, tôi sẽ nghiêng về việc đặt LastName trước. Nó phụ thuộc vào khối lượng công việc truy vấn cụ thể, nhưng nói chung có cột chọn lọc hơn trước, có nghĩa là chỉ mục có nhiều khả năng được sử dụng hơn.
Mitch Wheat

7

Trong trường hợp bạn chưa đọc nó, gần đây Jason Massie đã viết một bài báo thảo luận về chủ đề này.

http://st Statisticsio.com/Home/tabid/36/articleType/ArticleView/articleId/302/Never-Index-a-BIT.aspx

Chỉnh sửa: Vị trí bài viết mới - http://sqlserverpedia.com/blog/sql-server-bloggers/ooter-index-a-bit

Máy quay lui cho vị trí bài viết "Mới" trước đây: http://web.archive.org/web/20120201122503/http://sqlserverpedia.com/blog/sql-server-bloggers/ooter-index-a-bit/

Vị trí SQL Server Pedia mới là Toadworld, có một bài viết mới từ Kenneth Fisher thảo luận về chủ đề này:

http://www.toadworld.com/platforms/sql-server/b/weblog/archive/2014/02/17/dba-myths-an-index-on-a-bit-column-will-ctures-be- used.aspx

máy quay lui: http://web.archive.org/web/20150508115802/http://www.toadworld.com/platforms/sql-server/b/weblog/archive/2014/02/17/dba-myths-an -index-on-a-bit-column-will-never-be-used.aspx


bài viết này không còn hiển thị nữa
Homer 6

@ Homer6 Tôi đã thêm một liên kết đến ngôi nhà mới trông như thế nào cho bài viết này.
Jeff

Liên kết mới đến trang chủ Toad World.
N West

Tìm thấy bài viết bằng cách sử dụng máy Wayback và tìm thấy một bài viết mới có liên quan. Hi vọng điêu nay co ich.
Jeff

2

Tất nhiên nó có giá trị, đặc biệt nếu bạn cần truy xuất dữ liệu theo giá trị đó. Nó sẽ tương tự như sử dụng ma trận thưa thay vì sử dụng ma trận bình thường.

Bây giờ với SQL 2008, bạn có thể sử dụng các hàm phân vùng và bạn có thể lọc dữ liệu đi trong một chỉ mục. Điểm bất lợi đối với các phiên bản trước đó là chỉ mục sẽ được tạo cho tất cả dữ liệu, nhưng điều này có thể được tối ưu hóa bằng cách lưu trữ các giá trị thú vị trong một nhóm tệp riêng biệt.


2

Như những người khác đã nói, bạn sẽ muốn đo lường điều này. Tôi không nhớ mình đã đọc cái này ở đâu, nhưng một cột cần phải có số lượng rất cao (khoảng 95%) để một chỉ mục có hiệu quả. Thử nghiệm tốt nhất của bạn cho điều này sẽ là xây dựng chỉ mục và kiểm tra các kế hoạch thực thi cho các giá trị 0 và 1 của trường BIT. Nếu bạn thấy một hoạt động tìm kiếm chỉ mục trong kế hoạch thực thi thì bạn biết rằng chỉ mục của mình sẽ được sử dụng.

Hành động tốt nhất của bạn là kiểm tra với bảng SELECT * FROM cơ bản WHERE BitField = 1; truy vấn và từ từ xây dựng chức năng từ đó từng bước một cho đến khi bạn có một truy vấn thực tế cho ứng dụng của mình, kiểm tra kế hoạch thực thi với từng bước để đảm bảo rằng tìm kiếm chỉ mục vẫn đang được sử dụng. Phải thừa nhận rằng không có gì đảm bảo rằng kế hoạch thực hiện này sẽ được sử dụng trong quá trình sản xuất, nhưng có nhiều khả năng là nó sẽ như vậy.

Một số thông tin có thể được tìm thấy trên các diễn đàn sql-server-performance.com và trong bài viết tham khảo


Vấn đề không quan trọng lắm về số lượng của toàn bộ cột. Đó là tính chọn lọc của mệnh đề WHERE. Vì vậy, nếu có ít cột có giá trị 1, vẫn có thể tốt để lập chỉ mục. Nếu nó là 50/50 (ví dụ: nam / nữ) thì không đáng như vậy.
WW.

2

"Tôi nhớ đã đọc ở một thời điểm rằng việc lập chỉ mục một trường có bản số thấp (số lượng giá trị khác biệt thấp) không thực sự đáng làm"

Điều đó bởi vì SQL Server hầu như sẽ luôn thấy hiệu quả hơn khi chỉ thực hiện quét bảng hơn là đọc chỉ mục. Vì vậy, về cơ bản chỉ mục của bạn sẽ không bao giờ được sử dụng và thật lãng phí để duy trì nó. Như những người khác đã nói nó có thể ổn trong một chỉ số phức hợp.


2

Nếu mục tiêu của bạn là thực hiện truy vấn các bản ghi trong đó giá trị trường bit bằng '1' nhanh hơn, bạn có thể thử chế độ xem được lập chỉ mục của bảng cơ sở chỉ chứa các bản ghi trong đó trường bit của bạn bằng '1'. Trong ấn bản doanh nghiệp nếu một truy vấn có thể sử dụng dạng xem được lập chỉ mục thay vì một bảng được chỉ định để cải thiện hiệu suất truy vấn thì nó sẽ sử dụng dạng xem. Về lý thuyết, điều này sẽ làm tăng tốc độ của các truy vấn chọn lọc chỉ tìm kiếm các bản ghi có giá trị trường bit là '1'.

http://www.microsoft.com/technet/prodtechnol/sql/2005/impprfiv.mspx

Tất cả điều này giả định bạn là Microsoft SQL Server 2005 Enterprise. Điều tương tự có thể áp dụng cho năm 2008, tôi không quen với phiên bản đó.


2

Nếu bạn muốn biết liệu một chỉ mục có những tác dụng mà bạn mong muốn hay không: hãy kiểm tra và thử nghiệm lại.

Nói chung, bạn không muốn một chỉ mục không đủ thu hẹp bảng của bạn, vì chi phí duy trì một chỉ mục. (chi phí> lợi nhuận). Nhưng nếu chỉ số trong trường hợp của bạn giảm một nửa bảng, bạn có thể đạt được thứ gì đó ngoài việc đặt nó lên bàn. Tất cả phụ thuộc vào kích thước / cấu trúc chính xác của bảng của bạn và cách bạn đang sử dụng nó (số lần đọc / ghi).


1

Tự nó, không vì nó dẫn đến rất ít tính chọn lọc. Là một phần của chỉ số hợp chất. hoàn toàn có thể nhưng chỉ sau các cột bình đẳng khác.


1

Bạn không thể lập chỉ mục một trường bit trong SQL Server 2000, như được chỉ ra trong Sách trực tuyến vào thời điểm đó:

bit

Kiểu dữ liệu số nguyên 1, 0 hoặc NULL.

Nhận xét

Các cột kiểu bit không thể có chỉ mục trên chúng.

Có, nếu bạn chỉ có một số ít hàng, trong số hàng triệu, một chỉ mục sẽ hữu ích. Nhưng nếu bạn muốn làm điều đó trong trường hợp này bạn cần phải làm cột a tinyint.

Lưu ý : Trình quản lý doanh nghiệp sẽ không cho phép bạn tạo chỉ mục trên cột bit. Nếu bạn muốn, bạn vẫn có thể tạo chỉ mục theo cách thủ công trên một cột bit:

CREATE INDEX IX_Users_IsActiveUsername ON Users
(
   IsActive,
   Username
)

Nhưng SQL Server 2000 sẽ không thực sự sử dụng một chỉ mục như vậy - chạy một truy vấn mà chỉ mục sẽ là một ứng cử viên hoàn hảo, ví dụ:

SELECT TOP 1 Username 
FROM Users
WHERE IsActive = 0

Thay vào đó, SQL Server 2000 sẽ thực hiện quét bảng, hoạt động như thể chỉ mục thậm chí không tồn tại. Nếu bạn thay đổi cột thành tinyint SQL Server 2000 sẽ thực hiện tìm kiếm chỉ mục. Ngoài ra, truy vấn không được đề cập sau:

SELECT TOP 1 * 
FROM Users
WHERE IsActive = 0

Nó sẽ thực hiện tìm kiếm chỉ mục, sau đó là tra cứu dấu trang.


SQL Server 2005 không hỗ trợ giới hạn cho các chỉ mục trên cột bit. Ví dụ:

SELECT TOP 1 Username 
FROM Users
WHERE IsActive = 0

sẽ gây ra một tìm kiếm chỉ mục thông qua chỉ mục bao trùm. Nhưng trường hợp không được bảo hiểm:

SELECT TOP 1 * 
FROM Users
WHERE IsActive = 0

sẽ không thực hiện tìm kiếm chỉ mục theo sau là tra cứu dấu trang, nó sẽ thực hiện quét bảng (hoặc quét chỉ mục theo cụm), thay vì thực hiện tìm kiếm chỉ mục sau đó là tra cứu dấu trang.

Được kiểm chứng bằng thực nghiệm và quan sát trực tiếp.


FYI - SQL Server 2005 Management Studio cho phép bạn làm điều đó.
jeremcc 23/10/08

Bản sao SQL Server 2000 của tôi cho phép tôi đặt chỉ mục trên một cột bit.
Kibbee 23/10/08

Bản sao SQL Server 2000 của tôi không cho phép tôi đặt chỉ mục trên một cột bit.
Ian Boyd

1

câu trả lời rất muộn ...

Có, nó có thể hữu ích theo nhóm SQL CAT (đã cập nhật, đã được hợp nhất)


1
Liên kết dường như đã chết. Tuy nhiên, bài đăng đó dường như đã được hợp nhất cùng với một số bài khác trong một cuốn sách điện tử . Phần được tham chiếu bắt đầu từ trang 86. Sách điện tử có thể được tải xuống từ SQLCAT.com eBooks theo liên kết "Hướng dẫn của SQLCAT về Công cụ quan hệ".
mwolfe02

0

Đây có phải là một truy vấn phổ biến không? Nó có thể đáng giá khi tìm kiếm "số ít" các bản ghi nhưng sẽ không giúp bạn nhiều ở các hàng khác. Có những cách nào khác để xác định dữ liệu?


0

Cardinality là một yếu tố, yếu tố khác là chỉ số phân chia dữ liệu của bạn tốt như thế nào. Nếu bạn có khoảng nửa 0s và nửa 0s, thì nó sẽ hữu ích. (Giả sử rằng chỉ mục đó là một con đường tốt hơn để lựa chọn so với một số chỉ mục khác). Tuy nhiên, bạn có thường xuyên chèn và cập nhật không? Việc thêm chỉ mục cho hiệu suất CHỌN cũng ảnh hưởng đến hiệu suất CHÈN, CẬP NHẬT và XÓA, vì vậy hãy ghi nhớ điều đó.

Tôi sẽ nói, nếu 1 đến 0 (hoặc ngược lại) không tốt hơn 75% đến 25%, đừng bận tâm.


1
Tôi sẽ không đồng ý. Nếu phân phối của bạn là 50/50, thì bạn sẽ không bao giờ sử dụng chỉ mục, vì việc quét bảng sẽ nhanh hơn. Tuy nhiên, nếu bạn chỉ có 5, 1 giá trị, và 1 triệu 0 giá trị, nó sẽ rất có khả năng sử dụng các chỉ số khi tìm kiếm 1.
Kibbee

0

đo thời gian phản hồi trước và sau đó và xem nó có đáng giá không; về mặt lý thuyết, nó sẽ cải thiện hiệu suất cho các truy vấn bằng cách sử dụng các trường được lập chỉ mục nhưng nó thực sự phụ thuộc vào việc phân phối các giá trị true / false và các trường khác liên quan đến các truy vấn mà bạn lo ngại


0

Ian Boyd đã đúng khi anh ấy nói rằng bạn không thể làm điều đó thông qua Enterprise Manager cho SQL 2000 (xem ghi chú của anh ấy về việc tạo nó thông qua T-SQL.


0

Bạn cần phải thông minh ở đây để truy vấn, bạn phải biết giá trị tải trên cột của bạn nếu tải đúng là nhiều hơn trong hệ thống của bạn và bạn muốn kiểm tra tất cả các giá trị đúng, hãy ghi truy vấn của bạn để kiểm tra không sai .. nó sẽ giúp ích rất nhiều , nó chỉ lừa.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.