Tôi có thể thực hiện một trận đấu chữ cái đầu tiên có thể đọc được trên hai bảng không?


9
select value 
from persons p join persons2 p2 
    on left(p.lastname,1) = left(p2.lastname,1)

Máy chủ SQL. Có cách nào để làm cho SARGable / chạy nhanh hơn không? Tôi không thể tạo cột trên bảng người, nhưng tôi có thể tạo cột trên người2.


3
Bạn có biết rằng kết quả của truy vấn đó sẽ là một loại CROSS THAM GIA, thực sự?
ypercubeᵀᴹ

1
Những cái bàn to cỡ nào? Nếu mỗi cái chỉ nói một hàng 10K, kết quả sẽ có ít nhất 4 triệu hàng. Tôi tự hỏi những gì sẽ sử dụng truy vấn như vậy.
ypercubeᵀᴹ

1
@ ypercubeᵀᴹ có thể là một đầu vào ban đầu vào một số quá trình sao chép bằng cách sử dụng kết hợp mờ?
Martin Smith

Nghe có vẻ là một ý tưởng tồi. Bạn đang cố gắng đạt được điều gì ở đây?
David TOUR TOUR Markovitz

Đây chỉ là ví dụ. Có nhiều vị ngữ hơn. Martin Smith có ý tưởng đúng, đó là sự trùng lặp.
Lastchancexi

Câu trả lời:


9

Tạo một khung nhìn trên các bảng với một cột được tính toán bền vững được xác định là LEFT(lastname, 1)của mỗi bảng, sau đó so sánh các giá trị cột được tính toán bền vững.

Đây là một chiếc giường thử nghiệm cho thấy làm thế nào để làm điều đó:

CREATE TABLE dbo.Persons
(
    PersonID int NOT NULL
        CONSTRAINT PK_Persons
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , FirstName nvarchar(500) NOT NULL
    , LastName nvarchar(500) NOT NULL
);

CREATE TABLE dbo.Persons2
(
    PersonID int NOT NULL
        CONSTRAINT PK_Persons2
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , FirstName nvarchar(500) NOT NULL
    , LastName nvarchar(500) NOT NULL
);

GO
CREATE VIEW dbo.PersonsView
WITH SCHEMABINDING
AS
SELECT p1.PersonID
    , p1.FirstName
    , p1.LastName 
    , LastNameInitial = LEFT(p1.LastName, 1)
FROM dbo.Persons p1;
GO
CREATE VIEW dbo.PersonsView2
WITH SCHEMABINDING
AS
SELECT p2.PersonID
    , p2.FirstName
    , p2.LastName 
    , LastNameInitial = LEFT(p2.LastName, 1)
FROM dbo.Persons p2;
GO
CREATE UNIQUE CLUSTERED INDEX CX_PersonsView
ON dbo.PersonsView(PersonID);
CREATE NONCLUSTERED INDEX IX_PersonsView_LastNameInitial
ON dbo.PersonsView(LastNameInitial)
INCLUDE (FirstName, LastName);

CREATE UNIQUE CLUSTERED INDEX CX_PersonsView2
ON dbo.PersonsView2(PersonID);
CREATE NONCLUSTERED INDEX IX_PersonsView2_LastNameInitial
ON dbo.PersonsView2(LastNameInitial)
INCLUDE (FirstName, LastName);

CREATE STATISTICS ST_PersonsView_001
ON dbo.PersonsView(LastName);

CREATE STATISTICS ST_PersonsView2_001
ON dbo.PersonsView2(LastName);

Ở đây, chúng tôi sẽ chèn một số dữ liệu mẫu:

INSERT INTO dbo.Persons(FirstName, LastName)
VALUES ('Max', 'Vernon')
    , ('Joe', 'Black');

INSERT INTO dbo.Persons2(FirstName, LastName)
VALUES ('Max', 'Vernon')
    , ('Joe', 'Black');

Đây là SELECTtruy vấn:

SELECT *
FROM dbo.PersonsView pv1
    INNER JOIN dbo.PersonsView2 pv2 ON pv1.LastNameInitial = pv2.LastNameInitial;

Và kết quả:

+ ---------- + ----------- + ---------- + --------------- - + ---------- + ----------- + ---------- + ------------- ---- +
| Cá nhân | Tên đầu tiên | Họ | LastNameInitial | Cá nhân | Tên đầu tiên | Họ | LastNameInitial |
+ ---------- + ----------- + ---------- + --------------- - + ---------- + ----------- + ---------- + ------------- ---- +
| 2 | Joe | Đen | B | 2 | Joe | Đen | B |
| 1 | Tối đa | Vernon | V | 1 | Tối đa | Vernon | V |
+ ---------- + ----------- + ---------- + --------------- - + ---------- + ----------- + ---------- + ------------- ---- +

Kế hoạch thực hiện, chỉ có hai hàng trên mỗi bảng (phải thừa nhận là không có nhiều hàng!)

nhập mô tả hình ảnh ở đây


11

Nếu lastnamecột được lập chỉ mục trong ít nhất một trong các bảng thì bạn cũng có thể sử dụngLIKE

SELECT *
FROM   persons p
       INNER JOIN persons2 p2
               ON p2.lastname LIKE LEFT(p.lastname, 1) + '%' 

nhập mô tả hình ảnh ở đây

Kế hoạch cho việc này có thể có một tìm kiếm trên bảng được chỉ định ở bên trái của thích.

tức là ON p.lastname LIKE LEFT(p2.lastname, 1) + '%'sẽ không thể sử dụng chỉ mục trên persons2đã được sử dụng ở trên nhưng có thể tìm kiếm trên persons.

Tuy nhiên, gợi ý trong câu trả lời khác về lập chỉ mục một cột được tính toán ở cả hai bên là linh hoạt hơn. Đối với một kế hoạch các vòng lặp lồng nhau, một trong hai bảng có thể ở bên trong và nó cũng sẽ cho phép nhiều phép nối nhiều mà không yêu cầu sắp xếp.


những gì về phương pháp này ? Hãy thêm nó vào câu trả lời của bạn nếu nó có bất kỳ lợi ích nào. Nó sẽ được sử dụng các chỉ mục trên cả hai bảng - và nếu vậy, nó sẽ hiệu quả hơn?
ypercubeᵀᴹ

@ ypercubeᵀᴹ Nó có thể đưa ra một kế hoạch như thế này nếu các chỉ mục đang bao trùm i.stack.imgur.com/RSzcT.png . Tôi không thấy bất kỳ lợi thế nào so với kế hoạch trong câu trả lời của tôi. Vì cuối cùng vẫn cần phải đọc tất cả các hàng trong bảng bên ngoài, chỉ cần qua 26 lần tìm kiếm thay vì một lần quét.
Martin Smith

2

Tôi tình cờ có một bảng có 3.423 hàng và 195 giá trị riêng biệt trong Name. Tôi sẽ gọi bảng này P(người) và sao chép nó để tạo P2(person2). Có một khóa chính duy nhất, được nhóm trên một cột ID số nguyên. Tôi đang sử dụng Microsoft SQL Server 2016 (KB3194716) Phiên bản dành cho nhà phát triển (64-bit) trên Windows 10 Pro 6.3 với RAM 32GB.

Với truy vấn cơ sở

select
    p.pid
from dbo.p
inner join dbo.p2 
    on LEFT(p.name, 1) = LEFT(p2.name, 1);

Tôi nhận được 1,5 triệu hàng được trả lại trong 3200-3300ms (từ thống kê io).

nhập mô tả hình ảnh ở đây

Bằng cách viết lại như vậy -

select
    p.pid
from dbo.p
where exists
(
    select 1
    from dbo.p2 
    where LEFT(p.name, 1) = LEFT(p2.name, 1)
);

trôi qua giảm xuống 50-60ms và kế hoạch là:

nhập mô tả hình ảnh ở đây

Ít hàng hơn được trả về (3,423) vì thuật toán phù hợp. Kế hoạch và số hàng tương tự đạt được bằng cách thay đổi truy vấn cơ sở thành select distinct.

Bằng cách tạo cột được lập chỉ mục, tính toán

alter table dbo.p2
add Name1 as Left(Name, 1);

create index ix1 on dbo.p2(Name1);

Thời gian trôi qua giảm xuống 45-50ms.

nhập mô tả hình ảnh ở đây

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.