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

Theo dõi số 1 về các tìm kiếm ký tự đại diện hàng đầu

Trong bài đăng cuối cùng của tôi, "Một cách để lấy chỉ mục tìm kiếm ký tự đại diện đứng đầu", tôi đã đề cập rằng bạn sẽ cần các trình kích hoạt để giải quyết việc duy trì các phân đoạn mà tôi đã đề xuất. Một vài người đã liên hệ với tôi để hỏi liệu tôi có thể chứng minh những yếu tố kích hoạt đó không.

Để đơn giản hóa từ bài viết trước, hãy giả sử chúng ta có các bảng sau - một tập hợp các Công ty và sau đó là bảng CompanyNameFragment cho phép tìm kiếm ký tự đại diện giả dựa trên bất kỳ chuỗi con nào của tên công ty:

CREATE TABLE dbo.Companies
(
  CompanyID  int CONSTRAINT PK_Companies PRIMARY KEY,
  Name       nvarchar(100) NOT NULL
);
GO
 
CREATE TABLE dbo.CompanyNameFragments
(
  CompanyID int NOT NULL,
  Fragment  nvarchar(100) NOT NULL
);
 
CREATE CLUSTERED INDEX CIX_CNF ON dbo.CompanyNameFragments(Fragment, CompanyID);

Cung cấp chức năng này để tạo các đoạn (thay đổi duy nhất so với bài viết gốc là tôi đã tăng @input hỗ trợ 100 ký tự):

CREATE FUNCTION dbo.CreateStringFragments( @input nvarchar(100) )
RETURNS TABLE WITH SCHEMABINDING
AS
  RETURN 
  (
    WITH x(x) AS 
    (
      SELECT 1 UNION ALL SELECT x+1 FROM x WHERE x < (LEN(@input))
    )
    SELECT Fragment = SUBSTRING(@input, x, LEN(@input)) FROM x
  );
GO

Chúng tôi có thể tạo một trình kích hoạt duy nhất có thể xử lý cả ba hoạt động:

CREATE TRIGGER dbo.Company_MaintainFragments
ON dbo.Companies
FOR INSERT, UPDATE, DELETE
AS
BEGIN
  SET NOCOUNT ON;
 
  DELETE f FROM dbo.CompanyNameFragments AS f
    INNER JOIN deleted AS d 
    ON f.CompanyID = d.CompanyID;
 
  INSERT dbo.CompanyNameFragments(CompanyID, Fragment)
    SELECT i.CompanyID, fn.Fragment
    FROM inserted AS i 
    CROSS APPLY dbo.CreateStringFragments(i.Name) AS fn;
END
GO

Điều này hoạt động mà không cần kiểm tra xem loại hoạt động nào đã xảy ra vì:

  • Đối với CẬP NHẬT hoặc XÓA, XÓA sẽ xảy ra - đối với CẬP NHẬT, chúng tôi sẽ không bận tâm đến việc khớp các đoạn mà vẫn giữ nguyên; chúng tôi sẽ thổi bay tất cả chúng đi, vì vậy chúng có thể được thay thế hàng loạt. Đối với INSERT, câu lệnh DELETE sẽ không có hiệu lực, vì sẽ không có hàng nào trong deleted .
  • Đối với INSERT hoặc UPDATE, INSERT sẽ xảy ra. Đối với một DELETE, câu lệnh INSERT sẽ không có hiệu lực, vì sẽ không có hàng nào trong inserted .

Bây giờ, chỉ để đảm bảo nó hoạt động, hãy thực hiện một số thay đổi đối với Companies bảng và sau đó kiểm tra hai bảng của chúng tôi.

-- First, let's insert two companies 
-- (table contents after insert shown in figure 1 below)
 
INSERT dbo.Companies(Name) VALUES(N'Banana'), (N'Acme Corp');
 
-- Now, let's update company 2 to 'Orange' 
-- (table contents after update shown in figure 2 below):
 
UPDATE dbo.Companies SET Name = N'Orange' WHERE CompanyID = 2;
 
-- Finally, delete company #1 
-- (table contents after delete shown in figure 3 below):
 
DELETE dbo.Companies WHERE CompanyID = 1;
Hình 1: Nội dung bảng ban đầu Hình 2: Nội dung bảng sau khi cập nhật Hình 3: Nội dung bảng sau khi xóa

Lưu ý (dành cho những người toàn vẹn tham chiếu)

Lưu ý rằng nếu bạn thiết lập khóa ngoại thích hợp giữa hai bảng này, bạn sẽ phải sử dụng trình kích hoạt thay vì trình kích hoạt để xử lý việc xóa, nếu không bạn sẽ gặp vấn đề về gà và trứng - bạn không thể đợi cho đến khi * sau khi * cha mẹ hàng bị xóa để loại bỏ các hàng con. Vì vậy, bạn sẽ phải thiết lập ON DELETE CASCADE (mà cá nhân tôi không có xu hướng thích), hoặc hai trình kích hoạt của bạn sẽ trông giống như thế này (trình kích hoạt sau vẫn phải thực hiện cặp DELETE / INSERT trong trường hợp CẬP NHẬT):

CREATE TRIGGER dbo.Company_DeleteFragments
ON dbo.Companies
INSTEAD OF DELETE
AS
BEGIN
  SET NOCOUNT ON;
 
  DELETE f FROM dbo.CompanyNameFragments AS f
    INNER JOIN deleted AS d
    ON f.CompanyID = d.CompanyID;
 
  DELETE c FROM dbo.Companies AS c
    INNER JOIN deleted AS d
    ON c.CompanyID = d.CompanyID;
END
GO
 
CREATE TRIGGER dbo.Company_MaintainFragments
ON dbo.Companies
FOR INSERT, UPDATE
AS
BEGIN
  SET NOCOUNT ON;
 
  DELETE f FROM dbo.CompanyNameFragments AS f
    INNER JOIN deleted AS d
    ON f.CompanyID = d.CompanyID;
 
  INSERT dbo.CompanyNameFragments(CompanyID, Fragment)
    SELECT i.CompanyID, fn.Fragment
    FROM inserted AS i
    CROSS APPLY dbo.CreateStringFragments(i.Name) AS fn;
END
GO

Tóm tắt

Bài đăng này nhằm mục đích cho thấy việc thiết lập trình kích hoạt sẽ dễ dàng như thế nào sẽ duy trì tính năng có thể tìm kiếm các đoạn chuỗi để cải thiện các tìm kiếm theo ký tự đại diện, ít nhất là đối với các chuỗi có kích thước vừa phải. Bây giờ, tôi vẫn biết rằng loại này xuất hiện như một ý tưởng kỳ quặc, nhưng tôi vẫn tiếp tục nói về nó bởi vì tôi tin rằng có những trường hợp sử dụng tốt ngoài kia.

Trong bài đăng tiếp theo của tôi, tôi sẽ chỉ ra cách xem tác động của lựa chọn này:Bạn có thể dễ dàng thiết lập khối lượng công việc đại diện để so sánh chi phí tài nguyên của việc duy trì các phân đoạn với hiệu suất tiết kiệm tại thời điểm truy vấn. Tôi sẽ xem xét các độ dài chuỗi khác nhau cũng như các cân bằng khối lượng công việc khác nhau (chủ yếu là đọc so với chủ yếu là viết) và cố gắng tìm ra các điểm ngọt ngào và khu vực nguy hiểm.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sai lầm về hiệu suất:Các biến bảng luôn ở trong bộ nhớ

  2. Tầm quan trọng của việc chọn kích thước máy ảo Azure thích hợp

  3. Cải thiện hiệu suất của UDF với NULL ON NULL INPUT

  4. Cách các kế hoạch song song bắt đầu - Phần 4

  5. Các tính năng không dùng nữa để đưa ra khỏi hộp công cụ của bạn - Phần 1