THAM GIA chậm trên bàn với hàng triệu hàng


8

Trong ứng dụng của mình, tôi phải tham gia các bảng với hàng triệu hàng. Tôi có một truy vấn như thế này:

SELECT DISTINCT "f"."id" AS "FileId"  
, "f"."name" AS "FileName"  
, "f"."year" AS "FileYear"  
, "vt"."value" AS "value"  
FROM files "f"  
JOIN "clients" "cl" ON("f"."cid" = "cl"."id" AND "cl"."id" = 10)  
LEFT JOIN "value_text" "vt" ON ("f"."id" = "vt"."id_file" AND "vt"."id_field" = 65739)  
GROUP BY "f"."id", "f"."name", "f"."year", "vt"."value"  

Bảng "tệp" có 10 triệu hàng và bảng "value lòng" có 40 triệu hàng.

Truy vấn này quá chậm, phải mất từ ​​40 giây (15000 kết quả) - 3 phút (65000 kết quả) để được thực thi.

Tôi đã nghĩ về việc chia hai truy vấn, nhưng tôi không thể vì đôi khi tôi cần đặt hàng theo cột (giá trị) đã tham gia ...

Tôi có thể làm gì? Tôi sử dụng SQL Server với Azure. Cụ thể, Cơ sở dữ liệu Azure SQL với giá / mô hình lớp "PRS1 PremiumRS (125 DTU)" .

Tôi đang nhận được rất nhiều dữ liệu nhưng tôi nghĩ rằng kết nối internet không phải là nút cổ chai, bởi vì trong các truy vấn khác tôi cũng nhận được rất nhiều dữ liệu và chúng nhanh hơn.

Tôi đã thử sử dụng bảng khách như một truy vấn con và loại bỏ DISTINCTvới cùng kết quả.

Tôi có 1428 hàng trong bảng khách hàng.

thông tin bổ sung

clients bàn:

CREATE TABLE [dbo].[clients](
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [code] [nvarchar](70) NOT NULL,
    [password] [nchar](40) NOT NULL,
    [name] [nvarchar](150) NOT NULL DEFAULT (N''),
    [email] [nvarchar](255) NULL DEFAULT (NULL),
    [entity] [int] NOT NULL DEFAULT ((0)),
    [users] [int] NOT NULL DEFAULT ((0)),
    [status] [varchar](8) NOT NULL DEFAULT ('inactive'),
    [created] [datetime2](7) NULL DEFAULT (getdate()),
    [activated] [datetime2](7) NULL DEFAULT (getdate()),
    [client_type] [varchar](10) NOT NULL DEFAULT ('normal'),
    [current_size] [bigint] NOT NULL DEFAULT ((0)),
CONSTRAINT [PK_clients_id] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON),
CONSTRAINT [clients$code] UNIQUE NONCLUSTERED 
(
    [code] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)

files bàn:

CREATE TABLE [dbo].[files](
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [cid] [bigint] NOT NULL DEFAULT ((0)),
    [eid] [bigint] NOT NULL DEFAULT ((0)),
    [year] [bigint] NOT NULL DEFAULT ((0)),
    [name] [nvarchar](255) NOT NULL DEFAULT (N''),
    [extension] [int] NOT NULL DEFAULT ((0)),
    [size] [bigint] NOT NULL DEFAULT ((0)),
    [id_doc] [bigint] NOT NULL DEFAULT ((0)),
    [created] [datetime2](7) NULL DEFAULT (getdate())
CONSTRAINT [PK_files_id] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON),
 CONSTRAINT [files$estructure_unique] UNIQUE NONCLUSTERED 
(
    [year] ASC,
    [name] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)

GO

ALTER TABLE [dbo].[files]  WITH NOCHECK ADD  CONSTRAINT [FK_files_client] FOREIGN KEY([cid])
REFERENCES [dbo].[clients] ([id])
ON UPDATE CASCADE
ON DELETE CASCADE
GO

ALTER TABLE [dbo].[files] CHECK CONSTRAINT [FK_files_client]
GO

value_text bàn:

CREATE TABLE [dbo].[value_text](
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [id_file] [bigint] NOT NULL DEFAULT ((0)),
    [id_field] [bigint] NOT NULL DEFAULT ((0)),
    [value] [nvarchar](255) NULL DEFAULT (NULL),
    [id_doc] [bigint] NULL DEFAULT (NULL)
 CONSTRAINT [PK_value_text_id] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)

GO

ALTER TABLE [dbo].[value_text]  WITH NOCHECK ADD  CONSTRAINT [FK_valuesT_field] FOREIGN KEY([id_field])
REFERENCES [dbo].[fields] ([id])
ON UPDATE CASCADE
ON DELETE CASCADE
GO

ALTER TABLE [dbo].[value_text] CHECK CONSTRAINT [FK_valuesT_field]
GO

Kế hoạch thực hiện:

Kế hoạch thực hiện

* Tôi đã dịch các bảng và các trường trong câu hỏi này để hiểu chung. Trong hình ảnh này, "archivos" tương đương với "tập tin", "khách hàng" của "khách hàng" và "valores tựa" của "value lòng".

Kế hoạch thực hiện mà không có DISTINCT:

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

Kế hoạch thực hiện mà không có DISTINCTGROUP BY(truy vấn nhanh hơn một chút):

Kế hoạch thực hiện

Kiểm tra truy vấn (câu trả lời Krismorte)

Đây là kế hoạch thực hiện của truy vấn chậm hơn trước. Ở đây, truy vấn trả về cho tôi hơn 400.000 hàng, nhưng thậm chí phân trang kết quả, không có thay đổi.

Kế hoạch thực hiện chi tiết hơn: https://www.brentozar.com/pastetheplan/?id=By_UC2aBG

Truy vấn chậm

Và đây là kế hoạch thực hiện của truy vấn nhanh hơn trước. Tại đây, truy vấn trả về hơn 65.000 hàng.

Kế hoạch thực hiện chi tiết hơn: https://www.brentozar.com/pastetheplan/?id=r116e6pSM

Truy vấn nhanh


2
Vui lòng bao gồm bất kỳ chỉ mục nào khác mà bạn đã thêm vào các bảng. Bạn có thường chạy toàn bộ truy vấn như vậy không hoặc bạn có mệnh đề where mà bạn không hiển thị cho chúng tôi không?
Jonathan Fite

Câu trả lời:


7

Tôi nghĩ bạn cần chỉ số này (như Krismorte đề xuất ):

CREATE NONCLUSTERED INDEX [IX dbo.value_text id_file, id_field, value]
ON dbo.value_text (id_file, id_field, [value]);

Chỉ mục sau có thể không bắt buộc vì bạn dường như có một chỉ mục hiện có phù hợp (không được đề cập trong câu hỏi) nhưng tôi bao gồm nó để hoàn thiện:

CREATE NONCLUSTERED INDEX [IX dbo.files cid (id, year, name)]
ON dbo.files (cid)
INCLUDE
(
    id,
    [year],
    [name]
);

Thể hiện truy vấn dưới dạng:

SELECT
    FileId = F.id,
    [FileName] = F.[name],
    FileYear = F.[year],
    V.[value]
FROM dbo.files AS F
JOIN dbo.clients AS C
    ON C.id = F.cid
OUTER APPLY
(
        SELECT DISTINCT
            VT.[value]
        FROM dbo.value_text AS VT
        WHERE
            VT.id_file = F.id
            AND VT.id_field = 65739
) AS V
WHERE 
    C.id = 10
OPTION (RECOMPILE);

Điều này sẽ đưa ra một kế hoạch thực hiện như:

kế hoạch dự kiến

Đây OPTION (RECOMPILE)là tùy chọn. Chỉ thêm nếu bạn thấy hình dạng kế hoạch lý tưởng là khác nhau cho các giá trị tham số khác nhau. Có nhiều giải pháp khả thi khác cho các vấn đề "đánh hơi thông số" như vậy.

Với chỉ mục mới, bạn cũng có thể tìm thấy văn bản truy vấn ban đầu tạo ra một kế hoạch rất giống nhau, cũng có hiệu suất tốt.

Bạn cũng có thể cần cập nhật số liệu thống kê trên filesbảng vì ước tính trong gói được cung cấp cid = 19không chính xác:

Ước tính không chính xác


Sau khi cập nhật số liệu thống kê trên bảng tệp, truy vấn sẽ hoạt động rất nhanh trong tất cả các trường hợp. Nếu trong tương lai tôi thêm nhiều trường trong bảng "tệp", tôi có nên cập nhật chỉ mục hay gì không?

Nếu bạn thêm nhiều cột vào bảng tệp (và sử dụng / trả lại chúng trong truy vấn của mình), bạn sẽ cần thêm chúng vào chỉ mục (tối thiểu là các cột được bao gồm) để giữ cho chỉ mục "che". Mặt khác, trình tối ưu hóa có thể chọn quét bảng tệp thay vì tìm kiếm các cột không có trong chỉ mục. cidThay vào đó, bạn cũng có thể chọn tạo một phần của một chỉ mục phân cụm trên bảng đó. Nó phụ thuộc. Đặt một câu hỏi mới nếu bạn muốn làm rõ về những điểm này.


1

Chà, truy vấn này khá khó khăn, tôi thay đổi các quy tắc lọc và tạo hai chỉ mục bìa

create index ix_stackexchange on [value_text] (id_file,id_field,value)
create index ix_stackexchange on [files] (id,cid,name,year)

truy vấn

SELECT DISTINCT "f"."id" AS "FileId"  
, "f"."name" AS "FileName"  
, "f"."year" AS "FileYear"  
, "vt"."value" AS "value"  
FROM files "f"  
JOIN "clients" "cl" ON("f"."cid" = "cl"."id" )  
LEFT JOIN "value_text" "vt" ON ("f"."id" = "vt"."id_file" )  
where "cl"."id" = 10 AND "vt"."id_field" = 65739
GROUP BY "f"."id", "f"."name", "f"."year", "vt"."value"  

Kế hoạch truy vấn kết quả

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

Hãy thử điều này, tôi hy vọng rằng sẽ đủ


Trước hết, tôi đã sửa đổi mệnh đề where vì tôi cũng cần các hàng "tệp" trong đó id_campo là null. "trong đó" cl "." id "= 19 VÀ (" vtVE2 "." id_campo "= 628 HOẶC" vtVE2 "." id_campo "IS NULL)" Tôi không biết liệu có giải pháp nào tốt hơn không. Vì vậy, tôi đã kiểm tra truy vấn của bạn với các tham số khác nhau và kết quả rất tốt trong một số trường hợp nhưng trong các trường hợp khác, kết quả lại tệ hơn trước. Tôi đã thêm các kế hoạch thực hiện trong bài đầu tiên.
RuSSe
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.