2010-11-15 35 views
5

Nếu bạn có một truy vấn như:SQLite tham gia tối ưu hóa

select a.Name, a.Description from a 
inner join b on a.id1 = b.id1 
inner join c on b.id2 = c.id2 
group by a.Name, a.Description 

Điều gì sẽ là các cột tối ưu nhất đối với chỉ số cho truy vấn này trong SQLite nếu bạn xem xét rằng có hơn 100.000 hàng trong mỗi bảng?

Lý do tôi yêu cầu là tôi không nhận được hiệu suất với truy vấn với nhóm mà tôi mong đợi từ một RDBMS (SQL Server) khác khi tôi áp dụng cùng một tối ưu hóa.

Tôi có nghĩ rằng tất cả các cột được tham chiếu trên một bảng trong truy vấn trong SQLite cần được đưa vào một chỉ mục tổng hợp để có hiệu suất tốt nhất?

+2

Tâm lý bên trong của tôi co giật khi bạn có một nhóm theo mệnh đề mà không có bất kỳ hàm tổng hợp nào. Bạn đang cố gắng đạt được gì với nhóm? –

+1

@ MyOtherMe: Xem câu trả lời của tôi dưới đây, tôi nghĩ rằng anh ấy muốn có một sự khác biệt của tất cả các mô tả và tên được tham chiếu trong bảng b và c. – MPelletier

+0

Thats chính xác những gì tôi đang sau. – gmn

Trả lời

4

Vấn đề là bạn đang mong đợi SQLite có các đặc tính hiệu suất giống như một RDBMS đầy đủ. Nó sẽ không. SQLLite không có khả năng nhớ cache khá nhiều trong bộ nhớ, phải xây dựng lại bộ nhớ cache mỗi khi bạn chạy ứng dụng, có thể bị giới hạn trong việc thiết lập số lõi, v.v. v.v. Tradeoffs để sử dụng một RDBMS nhúng trên một đầy đủ.

Theo như tối ưu hóa, hãy thử lập chỉ mục các cột tra cứu và kiểm tra. Sau đó thử tạo chỉ mục bao gồm. Hãy chắc chắn kiểm tra cả hai selects và đường dẫn mã cập nhật cơ sở dữ liệu, bạn đang tăng tốc một lần với chi phí của cơ sở dữ liệu kia. Tìm chỉ mục cung cấp sự cân bằng tốt nhất giữa hai cho nhu cầu của bạn và đi với nó.

+0

Cảm ơn câu trả lời, trước đó tôi đã cố thêm một chỉ mục tổng hợp trên a.Id1, a.name, a.description và một hỗn hợp trên b.id1, ​​b.id2 và một chỉ mục khác trên c.id2. Tuy nhiên, không ai trong số này đã giúp với hiệu suất của nhóm. Đây là loại câu hỏi thúc đẩy câu hỏi vì dường như không thể loại bỏ đủ nhóm bằng hiệu suất trong tình huống này với SQLite. Tôi đoán đây chỉ là một trong những hạn chế của việc có một cơ sở dữ liệu nhúng. – gmn

1

Hãy coi chừng: Tôi không biết gì về những phức tạp có thể có của SQLite và các kế hoạch thực thi của nó.

Bạn chắc chắn cần chỉ mục trên a.id1, b.id1, b.id2c.id2. Tôi nghĩ chỉ số tổng hợp (b.id1, b.id2) có thể mang lại hiệu suất tăng nhỏ. Tương tự cũng vậy cho (a.id1, a.Name, a.Description).

2

Từ SQLite query optimization overview:

Khi làm một tra cứu được lập chỉ mục của một hàng, các thủ tục thông thường là để thực hiện tìm kiếm nhị phân trên các chỉ số để tìm các mục nhập chỉ mục, sau đó giải nén rowid từ chỉ số và sử dụng rằng rowid để thực hiện tìm kiếm nhị phân trên bảng gốc. Do đó, việc tra cứu được lập chỉ mục điển hình bao gồm hai tìm kiếm nhị phân. Tuy nhiên, nếu tất cả các cột được lấy từ bảng đã có sẵn trong chỉ mục, SQLite sẽ sử dụng các giá trị chứa trong chỉ mục và sẽ không bao giờ tìm kiếm hàng của bảng gốc. Điều này tiết kiệm một tìm kiếm nhị phân cho mỗi hàng và có thể làm cho nhiều truy vấn chạy nhanh gấp hai lần.

Đối với bất kỳ RDBMS nào khác, tôi muốn nói để đặt chỉ mục nhóm trên b.id1 và c.id2. Đối với SQLite, bạn có thể tốt hơn bao gồm bất kỳ cột nào từ b và c mà bạn muốn tra cứu trong các chỉ mục đó.

+0

Bao gồm các chỉ mục tồn tại trong mọi RDBMS và có tác dụng tương tự trên các tra cứu. Vấn đề là các chỉ mục lớn làm tổn thương hiệu suất chèn/cập nhật và vì vậy bạn phải sắp xếp sự cân bằng giữa hiệu suất cập nhật và hiệu suất được chọn. – Donnie

+0

Cảm ơn bạn đã trả lời, xin vui lòng tha thứ sự thiếu hiểu biết của tôi ở đây, nhưng bạn có nói rằng nó có thể trong SQLite để tạo ra một chỉ mục bao gồm các cột từ nhiều bảng, tương tự như một cái nhìn được lập chỉ mục trong SQLServer? – gmn

+1

Không, tôi đã nói rằng khi bạn tạo một chỉ mục trên B, không chỉ tạo chỉ mục trên B.id mà còn bao gồm tất cả các cột dữ liệu mà bạn cần từ B trong chỉ mục. Điều này sẽ giúp bạn tiết kiệm một tìm kiếm nhị phân cho các cột dữ liệu đó. Trong một DBMS khác, bạn có thể thậm chí còn nhanh hơn bằng cách bao gồm các cột từ nhiều bảng trong một chỉ mục, nhưng SQLite không phải là nâng cao. – thomaspaulb

0

Kể từ khi bạn không sử dụng các bảng khác cho các cột trở lại của mình, có lẽ đây sẽ nhanh hơn:

SELECT DISTINCT a.Name, a.Description 
FROM a, b, c 
WHERE a.id1 = b.id1 
AND b.id2 = c.id2 

Nhìn vào cột trở lại, kể từ khi tiêu chuẩn vẻ là duy nhất mà họ phải được liên kết từ a đến b đến c, bạn có thể tìm tất cả các cặp a.Namea.Description độc đáo.

SELECT DISTINCT a.Name, a.Description 
FROM a 
WHERE a.id1 IN (
SELECT b.id1 
FROM b 
WHERE b.id2 IN (
    SELECT c.id2 
    FROM c 
) 
) 

Hoặc, tùy thuộc vào nếu mỗi cặp a.Namea.Description đã độc đáo, cần có một số lợi ích trong việc tìm hiểu đầu tiên của id duy nhất sau đó lấy các cột khác.

SELECT a.Name, a.Description 
FROM a 
WHERE a.id1 IN (
SELECT DISTINCT a.id1 
FROM a 
WHERE a.id1 IN (
    SELECT b.id1 
    FROM b 
    WHERE b.id2 IN (
    SELECT c.id2 
    FROM c 
    ) 
) 
) 
1

Tôi nghĩ rằng các chỉ mục trên a.id1 và b.id2 sẽ mang lại cho bạn nhiều lợi ích nhất có thể khi nhận được JOIN. Nhưng SQLite cung cấp GIẢI THÍCH, và nó có thể giúp bạn xác định xem có hiệu quả tránh được trong kế hoạch thực thi hiện tại hay không.