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

Trận đấu gần nhất, Phần 1

Karen Ly, nhà phân tích thu nhập cố định của Jr. tại RBC, đã đưa ra cho tôi một thử thách T-SQL liên quan đến việc tìm kiếm kết quả phù hợp nhất, trái ngược với việc tìm kiếm một kết quả phù hợp chính xác. Trong bài viết này, tôi đề cập đến một dạng thử thách tổng quát, đơn giản.

Thử thách

Thử thách liên quan đến việc kết hợp các hàng từ hai bảng, T1 và T2. Sử dụng mã sau để tạo một cơ sở dữ liệu mẫu có tên là testdb và bên trong đó là các bảng T1 và T2:

  SET NOCOUNT ON;
 
  IF DB_ID('testdb') IS NULL
    CREATE DATABASE testdb;
  GO
 
  USE testdb;
 
  DROP TABLE IF EXISTS dbo.T1, dbo.T2;
 
  CREATE TABLE dbo.T1
  (
    keycol INT NOT NULL IDENTITY
      CONSTRAINT PK_T1 PRIMARY KEY,
    val INT NOT NULL,
    othercols BINARY(100) NOT NULL
      CONSTRAINT DFT_T1_col1 DEFAULT(0xAA)
  );
 
  CREATE TABLE dbo.T2
  (
    keycol INT NOT NULL IDENTITY
      CONSTRAINT PK_T2 PRIMARY KEY,
    val INT NOT NULL,
    othercols BINARY(100) NOT NULL
      CONSTRAINT DFT_T2_col1 DEFAULT(0xBB)
  );

Như bạn thấy, cả T1 và T2 đều có một cột số (kiểu INT trong ví dụ này) được gọi là val. Thách thức là đối sánh với từng hàng từ T1 với hàng từ T2 nơi chênh lệch tuyệt đối giữa T2.val và T1.val là thấp nhất. Trong trường hợp quan hệ (nhiều hàng khớp trong T2), hãy khớp hàng trên cùng dựa trên thứ tự tăng dần val, keycol. Đó là, hàng có giá trị thấp nhất trong cột val và nếu bạn vẫn còn quan hệ, thì hàng có giá trị móc khóa thấp nhất. Công cụ buộc dây được sử dụng để đảm bảo tính xác định.

Sử dụng mã sau để điền vào T1 và T2 với các tập hợp nhỏ dữ liệu mẫu để có thể kiểm tra tính đúng đắn của các giải pháp của bạn:

  TRUNCATE TABLE dbo.T1;
  TRUNCATE TABLE dbo.T2;
 
  INSERT INTO dbo.T1 (val)
    VALUES(1),(1),(3),(3),(5),(8),(13),(16),(18),(20),(21);
 
  INSERT INTO dbo.T2 (val)
    VALUES(2),(2),(7),(3),(3),(11),(11),(13),(17),(19);

Kiểm tra nội dung của T1:

  SELECT keycol, val, SUBSTRING(othercols, 1, 1) AS othercols
  FROM dbo.T1
  ORDER BY val, keycol;

Mã này tạo ra kết quả sau:

  keycol      val         othercols
  ----------- ----------- ---------
  1           1           0xAA
  2           1           0xAA
  3           3           0xAA
  4           3           0xAA
  5           5           0xAA
  6           8           0xAA
  7           13          0xAA
  8           16          0xAA
  9           18          0xAA
  10          20          0xAA
  11          21          0xAA

Kiểm tra nội dung của T2:

  SELECT keycol, val, SUBSTRING(othercols, 1, 1) AS othercols
  FROM dbo.T2
  ORDER BY val, keycol;

Mã này tạo ra kết quả sau:

  keycol      val         othercols
  ----------- ----------- ---------
  1           2           0xBB
  2           2           0xBB
  4           3           0xBB
  5           3           0xBB
  3           7           0xBB
  6           11          0xBB
  7           11          0xBB
  8           13          0xBB
  9           17          0xBB
  10          19          0xBB

Đây là kết quả mong muốn cho dữ liệu mẫu đã cho:

  keycol1     val1        othercols1 keycol2     val2        othercols2
  ----------- ----------- ---------- ----------- ----------- ----------
  1           1           0xAA       1           2           0xBB
  2           1           0xAA       1           2           0xBB
  3           3           0xAA       4           3           0xBB
  4           3           0xAA       4           3           0xBB
  5           5           0xAA       4           3           0xBB
  6           8           0xAA       3           7           0xBB
  7           13          0xAA       8           13          0xBB
  8           16          0xAA       9           17          0xBB
  9           18          0xAA       9           17          0xBB
  10          20          0xAA       10          19          0xBB
  11          21          0xAA       10          19          0xBB

Trước khi bạn bắt đầu thực hiện thử thách, hãy kiểm tra kết quả mong muốn và đảm bảo rằng bạn hiểu logic đối sánh, bao gồm cả logic kết hợp. Ví dụ:hãy xem xét hàng trong T1 trong đó keycol là 5 và val là 5. Hàng này có nhiều kết quả phù hợp nhất trong T2:

  keycol      val         othercols
  ----------- ----------- ---------
  4           3           0xBB
  5           3           0xBB
  3           7           0xBB

Trong tất cả các hàng này, sự khác biệt tuyệt đối giữa T2.val và T1.val (5) là 2. Sử dụng logic bẻ khóa dựa trên thứ tự val tăng dần, keycol tăng dần hàng trên cùng ở đây là hàng trong đó val là 3 và keycol là 4.

Bạn sẽ sử dụng các bộ dữ liệu mẫu nhỏ để kiểm tra tính hợp lệ của các giải pháp của mình. Để kiểm tra hiệu suất, bạn cần các bộ lớn hơn. Sử dụng mã sau để tạo một hàm trợ giúp được gọi là GetNums, hàm này tạo ra một chuỗi các số nguyên trong một phạm vi được yêu cầu:

  DROP FUNCTION IF EXISTS dbo.GetNums;
  GO
 
  CREATE OR ALTER FUNCTION dbo.GetNums(@low AS BIGINT, @high AS BIGINT) RETURNS TABLE
  AS
  RETURN
    WITH
      L0   AS (SELECT c FROM (SELECT 1 UNION ALL SELECT 1) AS D(c)),
      L1   AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
      L2   AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
      L3   AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
      L4   AS (SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
      L5   AS (SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
      Nums AS (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS rownum
               FROM L5)
    SELECT TOP(@high - @low + 1) @low + rownum - 1 AS n
    FROM Nums
    ORDER BY rownum;
  GO

Sử dụng mã sau để điền vào T1 và T2 với các bộ dữ liệu mẫu lớn:

  DECLARE
    @numrowsT1 AS INT = 1000000,
    @maxvalT1  AS INT = 10000000,
    @numrowsT2 AS INT = 1000000,
    @maxvalT2  AS INT = 10000000;
 
  TRUNCATE TABLE dbo.T1;
  TRUNCATE TABLE dbo.T2;
 
  INSERT INTO dbo.T1 WITH(TABLOCK) (val)
    SELECT ABS(CHECKSUM(NEWID())) % @maxvalT1 + 1 AS val
    FROM dbo.GetNums(1, @numrowsT1) AS Nums;
 
  INSERT INTO dbo.T2 WITH(TABLOCK) (val)
    SELECT ABS(CHECKSUM(NEWID())) % @maxvalT2 + 1 AS val
    FROM dbo.GetNums(1, @numrowsT2) AS Nums;

Các biến @ numrowsT1 và @ numrowsT2 kiểm soát số hàng mà bạn muốn các bảng được điền vào. Các biến @ maxvalT1 và @ maxvalT2 kiểm soát phạm vi giá trị khác biệt trong cột val và do đó ảnh hưởng đến mật độ của cột. Đoạn mã trên điền vào các bảng với 1.000.000 hàng mỗi bảng và sử dụng phạm vi từ 1 - 10.000.000 cho cột val trong cả hai bảng. Điều này dẫn đến mật độ trong cột thấp (số lượng lớn các giá trị khác biệt, với số lượng trùng lặp nhỏ). Việc sử dụng các giá trị tối đa thấp hơn sẽ dẫn đến mật độ cao hơn (số lượng các giá trị riêng biệt nhỏ hơn và do đó có nhiều bản sao hơn).

Giải pháp 1, sử dụng một truy vấn con HÀNG ĐẦU

Giải pháp đơn giản và rõ ràng nhất có lẽ là giải pháp truy vấn T1 và sử dụng toán tử ÁP DỤNG CHÉO áp dụng truy vấn với bộ lọc TOP (1), sắp xếp các hàng bằng sự khác biệt tuyệt đối giữa T1.val và T2.val, sử dụng T2.val , T2.keycol là người kết thúc. Đây là mã của giải pháp:

  SELECT
     T1.keycol AS keycol1, T1.val AS val1, SUBSTRING(T1.othercols, 1, 1) AS othercols1,
     A.keycol AS keycol2, A.val AS val2, SUBSTRING(A.othercols, 1, 1) AS othercols2
  FROM dbo.T1
    CROSS APPLY
      ( SELECT TOP (1) T2.*
        FROM dbo.T2
        ORDER BY ABS(T2.val - T1.val), T2.val, T2.keycol ) AS A;

Hãy nhớ rằng có 1.000.000 hàng trong mỗi bảng. Và mật độ của cột val là thấp trong cả hai bảng. Rất tiếc, vì không có vị từ lọc nào trong truy vấn được áp dụng và thứ tự liên quan đến một biểu thức thao tác các cột, nên ở đây không có khả năng tạo các chỉ mục hỗ trợ. Truy vấn này tạo ra kế hoạch trong Hình 1.

Hình 1:Kế hoạch cho Giải pháp 1

Đầu vào bên ngoài của vòng lặp quét 1.000.000 hàng từ T1. Đầu vào bên trong của vòng lặp thực hiện quét toàn bộ T2 và sắp xếp TopN cho mỗi giá trị T1.val riêng biệt. Trong kế hoạch của chúng tôi, điều này xảy ra 998.657 lần vì chúng tôi có mật độ rất thấp. Nó đặt các hàng trong một ống chỉ mục, được khóa bởi T1.val, để nó có thể sử dụng lại những hàng đó cho những lần xuất hiện trùng lặp của giá trị T1.val, nhưng chúng tôi có rất ít bản sao. Kế hoạch này có độ phức tạp bậc hai. Giữa tất cả các lần thực thi dự kiến ​​của nhánh bên trong của vòng lặp, nó dự kiến ​​sẽ xử lý gần một nghìn tỷ hàng. Khi nói về số lượng lớn hàng để truy vấn xử lý, khi bạn bắt đầu đề cập đến hàng tỷ hàng, mọi người đã biết bạn đang xử lý một truy vấn đắt tiền. Thông thường, mọi người không thốt ra những thuật ngữ như nghìn tỷ, trừ khi họ đang thảo luận về khoản nợ quốc gia của Hoa Kỳ hoặc sự sụp đổ của thị trường chứng khoán. Bạn thường không xử lý những con số như vậy trong ngữ cảnh xử lý truy vấn. Nhưng các kế hoạch có độ phức tạp bậc hai có thể nhanh chóng kết thúc với những con số như vậy. Chạy truy vấn trong SSMS có bật Bao gồm thống kê truy vấn trực tiếp mất 39,6 giây để xử lý chỉ 100 hàng từ T1 trên máy tính xách tay của tôi. Điều này có nghĩa là truy vấn này sẽ mất khoảng 4,5 ngày để hoàn thành. Câu hỏi đặt ra là bạn có thực sự thích xem các kế hoạch truy vấn trực tiếp không? Có thể là một kỷ lục Guinness thú vị để thử và thiết lập.

Giải pháp 2, sử dụng hai truy vấn con HÀNG ĐẦU

Giả sử bạn đang tìm kiếm một giải pháp mất vài giây chứ không phải vài ngày để hoàn thành, thì đây là một ý tưởng. Trong biểu thức bảng được áp dụng, hãy hợp nhất hai truy vấn TOP (1) bên trong — một truy vấn lọc một hàng trong đó T2.val =T1.val (theo thứ tự của T2.val, T2.keycol). Thật dễ dàng tạo chỉ mục để hỗ trợ các truy vấn như vậy bằng cách cho phép tìm kiếm một hàng. Vẫn trong biểu thức bảng được áp dụng, hãy sử dụng truy vấn TOP (1) bên ngoài đối với kết quả hai hàng, dựa trên thứ tự của ABS (D.val - T1.val), D.val, D.keycol. Sẽ có một loại TopN liên quan, nhưng nó sẽ được áp dụng cho hai hàng cùng một lúc.

Dưới đây là các chỉ mục được đề xuất để hỗ trợ giải pháp này:

  CREATE INDEX idx_val_key ON dbo.T1(val, keycol) INCLUDE(othercols);
  CREATE INDEX idx_val_key ON dbo.T2(val, keycol) INCLUDE(othercols);
  CREATE INDEX idx_valD_key ON dbo.T2(val DESC, keycol) INCLUDE(othercols);

Đây là mã giải pháp hoàn chỉnh:

  SELECT
     T1.keycol AS keycol1, T1.val AS val1, SUBSTRING(T1.othercols, 1, 1) AS othercols1,
     A.keycol AS keycol2, A.val AS val2, SUBSTRING(A.othercols, 1, 1) AS othercols2
  FROM dbo.T1
    CROSS APPLY
      ( SELECT TOP (1) D.*
        FROM ( SELECT TOP (1) *
               FROM dbo.T2
               WHERE T2.val < T1.val
               ORDER BY T2.val DESC, T2.keycol
 
               UNION ALL
 
               SELECT TOP (1) *
               FROM dbo.T2
               WHERE T2.val >= T1.val
               ORDER BY T2.val, T2.keycol ) AS D
        ORDER BY ABS(D.val - T1.val), D.val, D.keycol ) AS A;

Hãy nhớ rằng chúng ta có 1.000.000 hàng trong mỗi bảng, với cột val có các giá trị trong phạm vi 1 - 10.000.000 (mật độ thấp) và các chỉ mục tối ưu tại chỗ.

Kế hoạch cho truy vấn này được thể hiện trong Hình 2.

Hình 2:Kế hoạch cho Giải pháp 2

Quan sát việc sử dụng tối ưu các chỉ số trên T2, dẫn đến một kế hoạch với tỷ lệ tuyến tính. Kế hoạch này sử dụng một ống chỉ mục theo cách giống như kế hoạch trước đó đã làm, tức là, để tránh lặp lại công việc trong nhánh bên trong của vòng lặp đối với các giá trị T1.val trùng lặp. Dưới đây là thống kê hiệu suất mà tôi nhận được để thực hiện truy vấn này trên hệ thống của mình:

  Elapsed: 27.7 sec, CPU: 27.6 sec, logical reads: 17,304,674

Giải pháp 2, với bộ đệm bị vô hiệu hóa

Bạn không thể không tự hỏi liệu ống chỉ mục có thực sự có lợi ở đây hay không. Vấn đề là để tránh lặp lại công việc cho các giá trị T1.val trùng lặp, nhưng trong tình huống như của chúng tôi, nơi chúng tôi có mật độ rất thấp, có rất ít trùng lặp. Điều này có nghĩa là rất có thể công việc liên quan đến bộ đệm lớn hơn là chỉ lặp lại công việc cho các bản sao. Có một cách đơn giản để xác minh điều này — sử dụng cờ theo dõi 8690, bạn có thể vô hiệu hóa bộ đệm trong kế hoạch, như sau:

  SELECT
     T1.keycol AS keycol1, T1.val AS val1, SUBSTRING(T1.othercols, 1, 1) AS othercols1,
     A.keycol AS keycol2, A.val AS val2, SUBSTRING(A.othercols, 1, 1) AS othercols2
  FROM dbo.T1
    CROSS APPLY
      ( SELECT TOP (1) D.*
        FROM ( SELECT TOP (1) *
               FROM dbo.T2
               WHERE T2.val < T1.val
               ORDER BY T2.val DESC, T2.keycol
 
               UNION ALL
 
               SELECT TOP (1) *
               FROM dbo.T2
               WHERE T2.val >= T1.val
               ORDER BY T2.val, T2.keycol ) AS D
        ORDER BY ABS(D.val - T1.val), D.val, D.keycol ) AS A
  OPTION(QUERYTRACEON 8690);

Tôi nhận được kế hoạch được hiển thị trong Hình 3 cho việc thực thi này:

Hình 3:Kế hoạch cho Giải pháp 2, đã tắt bộ đệm

Quan sát rằng ống chỉ mục đã biến mất và lần này nhánh bên trong của vòng lặp được thực thi 1.000.000 lần. Dưới đây là thống kê hiệu suất mà tôi nhận được cho lần thực thi này:

  Elapsed: 19.18 sec, CPU: 19.17 sec, logical reads: 6,042,148

Đó là giảm 44% thời gian thực hiện.

Giải pháp 2, với phạm vi giá trị được sửa đổi và lập chỉ mục

Vô hiệu hóa bộ đệm có ý nghĩa rất nhiều khi bạn có mật độ thấp trong các giá trị T1.val; tuy nhiên, việc tạo ống đệm có thể rất có lợi khi bạn có mật độ cao. Ví dụ:chạy mã sau để tạo lại T1 và T2 với cài đặt dữ liệu mẫu @ maxvalT1 và @ maxvalT2 thành 1000 (1.000 giá trị khác biệt tối đa):

  DECLARE
    @numrowsT1 AS INT = 1000000,
    @maxvalT1  AS INT = 1000,
    @numrowsT2 AS INT = 1000000,
    @maxvalT2  AS INT = 1000;
 
  TRUNCATE TABLE dbo.T1;
  TRUNCATE TABLE dbo.T2;
 
  INSERT INTO dbo.T1 WITH(TABLOCK) (val)
    SELECT ABS(CHECKSUM(NEWID())) % @maxvalT1 + 1 AS val
    FROM dbo.GetNums(1, @numrowsT1) AS Nums;
 
  INSERT INTO dbo.T2 WITH(TABLOCK) (val)
    SELECT ABS(CHECKSUM(NEWID())) % @maxvalT2 + 1 AS val
    FROM dbo.GetNums(1, @numrowsT2) AS Nums;

Chạy lại Giải pháp 2, trước tiên không có cờ theo dõi:

  SELECT
     T1.keycol AS keycol1, T1.val AS val1, SUBSTRING(T1.othercols, 1, 1) AS othercols1,
     A.keycol AS keycol2, A.val AS val2, SUBSTRING(A.othercols, 1, 1) AS othercols2
  FROM dbo.T1
    CROSS APPLY
      ( SELECT TOP (1) D.*
        FROM ( SELECT TOP (1) *
               FROM dbo.T2
               WHERE T2.val < T1.val
               ORDER BY T2.val DESC, T2.keycol
 
               UNION ALL
 
               SELECT TOP (1) *
               FROM dbo.T2
               WHERE T2.val >= T1.val
               ORDER BY T2.val, T2.keycol ) AS D
        ORDER BY ABS(D.val - T1.val), D.val, D.keycol ) AS A;

Kế hoạch cho việc thực hiện này được thể hiện trong Hình 4:

Hình 4:Kế hoạch cho Giải pháp 2, với phạm vi giá trị 1 - 1000

Trình tối ưu hóa đã quyết định sử dụng một kế hoạch khác do mật độ cao trong T1.val. Quan sát rằng chỉ mục trên T1 được quét theo thứ tự chính. Vì vậy, đối với mỗi lần xuất hiện đầu tiên của một giá trị T1.val riêng biệt, nhánh bên trong của vòng lặp sẽ được thực thi và kết quả được lưu trong một cuộn bảng thông thường (rebind). Sau đó, đối với mỗi lần xuất hiện đầu tiên của giá trị, một tua lại được áp dụng. Với 1.000 giá trị khác biệt, nhánh bên trong chỉ được thực hiện 1.000 lần. Điều này dẫn đến thống kê hiệu suất tuyệt vời:

  Elapsed: 1.16 sec, CPU: 1.14 sec, logical reads: 23,278

Bây giờ, hãy thử chạy giải pháp với bộ đệm bị vô hiệu hóa:

  SELECT
     T1.keycol AS keycol1, T1.val AS val1, SUBSTRING(T1.othercols, 1, 1) AS othercols1,
     A.keycol AS keycol2, A.val AS val2, SUBSTRING(A.othercols, 1, 1) AS othercols2
  FROM dbo.T1
    CROSS APPLY
      ( SELECT TOP (1) D.*
        FROM ( SELECT TOP (1) *
               FROM dbo.T2
               WHERE T2.val < T1.val
               ORDER BY T2.val DESC, T2.keycol
 
               UNION ALL
 
               SELECT TOP (1) *
               FROM dbo.T2
               WHERE T2.val >= T1.val
               ORDER BY T2.val, T2.keycol ) AS D
        ORDER BY ABS(D.val - T1.val), D.val, D.keycol ) AS A
  OPTION(QUERYTRACEON 8690);

Tôi nhận được kế hoạch được hiển thị trong Hình 5.

Hình 5:Kế hoạch cho Giải pháp 2, với phạm vi giá trị 1 - 1.000 và bộ đệm bị tắt

Về cơ bản, nó giống với kế hoạch được hiển thị trước đó trong Hình 3. Nhánh bên trong của vòng lặp được thực hiện 1.000.000 lần. Dưới đây là thống kê hiệu suất mà tôi nhận được cho lần thực thi này:

  Elapsed: 24.5 sec, CPU: 24.2 sec, logical reads: 8,012,548

Rõ ràng, bạn muốn cẩn thận không vô hiệu hóa bộ đệm khi bạn có mật độ cao trong T1.val.

Cuộc sống tốt đẹp khi hoàn cảnh của bạn đủ đơn giản để bạn có thể tạo ra các chỉ số hỗ trợ. Thực tế là trong một số trường hợp trong thực tế, có đủ logic bổ sung trong truy vấn, điều này loại trừ khả năng tạo các chỉ mục hỗ trợ tối ưu. Trong những trường hợp như vậy, Giải pháp 2 sẽ không hoạt động tốt.

Để chứng minh hiệu suất của Giải pháp 2 mà không có chỉ mục hỗ trợ, hãy tạo lại T1 và T2 trở lại với cài đặt dữ liệu mẫu @ maxvalT1 và @ maxvalT2 thành 10000000 (phạm vi giá trị 1 - 10M), đồng thời xóa các chỉ mục hỗ trợ:

  DROP INDEX IF EXISTS idx_val_key ON dbo.T1;
  DROP INDEX IF EXISTS idx_val_key ON dbo.T2;
  DROP INDEX IF EXISTS idx_valD_key ON dbo.T2;
 
  DECLARE
    @numrowsT1 AS INT = 1000000,
    @maxvalT1  AS INT = 10000000,
    @numrowsT2 AS INT = 1000000,
    @maxvalT2  AS INT = 10000000;
 
  TRUNCATE TABLE dbo.T1;
  TRUNCATE TABLE dbo.T2;
 
  INSERT INTO dbo.T1 WITH(TABLOCK) (val)
    SELECT ABS(CHECKSUM(NEWID())) % @maxvalT1 + 1 AS val
    FROM dbo.GetNums(1, @numrowsT1) AS Nums;
 
  INSERT INTO dbo.T2 WITH(TABLOCK) (val)
    SELECT ABS(CHECKSUM(NEWID())) % @maxvalT2 + 1 AS val
    FROM dbo.GetNums(1, @numrowsT2) AS Nums;

Chạy lại Giải pháp 2, với Bao gồm Thống kê Truy vấn Trực tiếp được bật trong SSMS:

  SELECT
     T1.keycol AS keycol1, T1.val AS val1, SUBSTRING(T1.othercols, 1, 1) AS othercols1,
     A.keycol AS keycol2, A.val AS val2, SUBSTRING(A.othercols, 1, 1) AS othercols2
  FROM dbo.T1
    CROSS APPLY
      ( SELECT TOP (1) D.*
        FROM ( SELECT TOP (1) *
               FROM dbo.T2
               WHERE T2.val < T1.val
               ORDER BY T2.val DESC, T2.keycol
 
               UNION ALL
 
               SELECT TOP (1) *
               FROM dbo.T2
               WHERE T2.val >= T1.val
               ORDER BY T2.val, T2.keycol ) AS D
        ORDER BY ABS(D.val - T1.val), D.val, D.keycol ) AS A;

Tôi nhận được kế hoạch được hiển thị trong Hình 6 cho truy vấn này:

Hình 6:Kế hoạch cho Giải pháp 2, không lập chỉ mục, với phạm vi giá trị 1 - 1.000.000

Bạn có thể thấy một mẫu rất giống với mẫu được hiển thị trước đó trong Hình 1, chỉ khác là lần này kế hoạch quét T2 hai lần cho mỗi giá trị T1.val riêng biệt. Một lần nữa, độ phức tạp của kế hoạch tăng lên bậc hai. Chạy truy vấn trong SSMS có bật Bao gồm thống kê truy vấn trực tiếp mất 49,6 giây để xử lý 100 hàng từ T1 trên máy tính xách tay của tôi, có nghĩa là truy vấn này sẽ mất khoảng 5,7 ngày để hoàn thành. Tất nhiên, điều này có thể có nghĩa là tin tốt nếu bạn đang cố gắng phá kỷ lục Guinness thế giới về việc xem một cách say sưa một kế hoạch truy vấn trực tiếp.

Kết luận

Tôi muốn cảm ơn Karen Ly từ RBC đã giới thiệu cho tôi thử thách đối đầu thú vị nhất này. Tôi khá ấn tượng với mã của cô ấy để xử lý nó, bao gồm rất nhiều logic bổ sung dành riêng cho hệ thống của cô ấy. Trong bài viết này, tôi đã chỉ ra các giải pháp hoạt động hợp lý khi bạn có thể tạo các chỉ mục hỗ trợ tối ưu. Nhưng như bạn có thể thấy, trong trường hợp đây không phải là một tùy chọn, rõ ràng là thời gian thực thi mà bạn nhận được là rất cao. Bạn có thể nghĩ ra các giải pháp sẽ hoạt động tốt ngay cả khi không có các chỉ số hỗ trợ tối ưu không? Còn tiếp…


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kết nối Google BigQuery với Phần mềm IRI Voracity

  2. Bảng lừa đảo SQL UNION với 10 mẹo dễ dàng và hữu ích

  3. So sánh Hiệu suất Windows Azure VM, Phần 1

  4. Nhấn và đỗ xe:Mô hình dữ liệu ứng dụng đỗ xe

  5. Thiết kế cơ sở dữ liệu với Vertabelo