2009-05-27 19 views
10

Tôi không giỏi SQL.Làm thế nào để tăng tốc độ tham gia đơn giản

Tôi đang tìm kiếm một cách để tăng tốc độ một đơn giản tham gia như thế này:

SELECT 
    E.expressionID, 
    A.attributeName, 
    A.attributeValue 
FROM 
    attributes A 
JOIN 
    expressions E 
ON 
    E.attributeId = A.attributeId 

Tôi đang làm hàng chục này ngàn lần và nó lấy ngày càng nhiều như bảng được lớn hơn. Tôi đang nghĩ đến các chỉ mục - Nếu tôi tăng tốc các lựa chọn trên các bảng đơn, tôi có thể đặt các chỉ mục nonclustered trên expressionID cho bảng biểu thức và một bảng khác trên (attributeName, attributeValue) cho bảng thuộc tính - nhưng tôi không ' t biết làm thế nào điều này có thể áp dụng cho tham gia.

EDIT: Tôi đã có một nhóm chỉ số trên expressionId (PK), attributeId (PK, FK) trên bảng biểu và một clustered index trên attributeId (PK) trên bảng thuộc tính

Tôi đã thấy câu hỏi this nhưng tôi yêu cầu một cái gì đó tổng quát hơn và có lẽ đơn giản hơn nhiều.

Bất kỳ trợ giúp nào được đánh giá cao!

+0

Bạn có mệnh đề WHERE trong truy vấn này không? Có bao nhiêu hàng đang được trả lại? – JerSchneid

+0

no WHERE - Tôi đang sử dụng bảng này để điền bảng tạm thời, sau đó được lọc xuống với một số mệnh đề phụ thuộc vào tập hợp các cặp tên-giá trị để có được biểu thức phù hợpId – JohnIdol

+1

Bạn nên đăng nửa sau của truy vấn. Tôi đặt cược chậm lại là do chèn một số lượng lớn các bản ghi vào bảng tạm thời đó. Nó có thể có thể được cải thiện rất nhiều bằng cách kết hợp chúng để các mệnh đề WHERE được sử dụng trước đó để ngăn chặn chèn lớn. – JerSchneid

Trả lời

16

Bạn chắc chắn muốn có chỉ mục trên attributeID trên cả hai bảng attributesexpressions. Nếu bạn hiện không có các chỉ mục đó, tôi nghĩ bạn sẽ thấy một sự tăng tốc lớn.

+5

Không quên cả hai cột phải thuộc cùng một kiểu dữ liệu và, nếu chúng là dữ liệu ký tự, của cùng một đối chiếu. – Tomalak

+1

Biết khóa chính sẽ giúp ích. Một cột đơn lẻ là khóa chính đã được lập chỉ mục. Có thể bảng biểu thức của bạn có hai trường tạo nên khóa chính. Điều này có nghĩa là việc tạo một chỉ mục trên E.attributeId sẽ là cách để đi. Khóa chính sẽ tạo một chỉ mục sử dụng cả E.ID và E.attributeId. Thêm chỉ mục cho chỉ E.attributeId sẽ tăng tốc nó. – Kieveli

+1

Thực ra, khóa chính không được tự động hóa trên tất cả các nền tảng. Ví dụ, MySql không tạo chỉ mục theo mặc định trên khóa chính. –

6

Trong thực tế, bởi vì có rất ít cột được trả lại, tôi sẽ xem xét một chỉ số bao phủ cho truy vấn này

ví dụ: một chỉ số bao gồm tất cả các lĩnh vực trong truy vấn.

+0

làm cách nào để tôi lập chỉ mục tham gia? (không bao giờ làm) – JohnIdol

+2

Tôi nghĩ rằng Goblyn đang đề xuất thêm một chỉ mục trên A.attributeId, A.attributeName, A.attributeValue và một trên E.attributeId và E.expressionID ... nhưng tôi không chắc chắn 100%. Lý thuyết của việc này là tất cả dữ liệu cho truy vấn sẽ đến trực tiếp từ các chỉ mục và không bao giờ chạm vào bảng. – Greg

+0

Xin lỗi, tôi không rõ ràng về điều đó. Greg là chính xác. Trong trường hợp này sẽ có hai chỉ số được bao phủ, một cho mỗi bảng và phép nối sẽ diễn ra giữa hai chỉ mục được bao phủ mà không liên quan đến bảng thực tế. –

3

Một số điều bạn cần quan tâm là các chỉ mục, kế hoạch truy vấn và thống kê.

Đặt chỉ mục trên attributeId. Hoặc, hãy chắc chắn rằng các chỉ mục tồn tại trong đó attributeId là cột đầu tiên trong khóa (SQL Server vẫn có thể sử dụng các chỉ mục nếu nó không phải là cột thứ nhất, nhưng nó không phải là nhanh).

Đánh dấu truy vấn trong Trình phân tích truy vấn và nhấn^L để xem gói. Bạn có thể xem cách các bảng được nối với nhau. Hầu như luôn luôn, sử dụng chỉ mục tốt hơn không (có trường hợp rìa nếu bảng đủ nhỏ, chỉ mục có thể làm chậm bạn xuống - nhưng hiện tại, chỉ cần biết rằng 99% chỉ mục thời gian là tốt).

Chú ý đến thứ tự các bảng được nối. SQL Server duy trì số liệu thống kê về kích thước bảng và sẽ xác định số liệu nào tốt hơn để tham gia trước. Thực hiện một số điều tra về các thủ tục SQL Server nội bộ để cập nhật số liệu thống kê - quá dài nên tôi không có thông tin đó tiện dụng.

Điều đó sẽ giúp bạn bắt đầu. Thực sự, toàn bộ một chương có thể được viết về cách một cơ sở dữ liệu có thể tối ưu hóa ngay cả một truy vấn đơn giản như vậy.

1

Một điều cần làm là thêm một số chỉ số như thế này:

attributes.{attributeId, attributeName, attributeValue} 
expressions.{attributeId, expressionID} 

Đây là hacky! Nhưng hữu ích nếu đó là phương sách cuối cùng.

Điều này tạo ra kế hoạch truy vấn có thể được "lập chỉ mục trả lời" theo chỉ mục. Thông thường, chỉ mục thực sự gây ra một I/O gấp đôi trong truy vấn ở trên của bạn: một chỉ mục để đạt chỉ mục (tức làthăm dò vào bảng), một cái khác để tìm nạp hàng thực tế được tham chiếu bởi chỉ mục (để kéo thuộc tínhName, vv).

Điều này đặc biệt hữu ích nếu "thuộc tính" hoặc "biểu thức" là một bảng rộng. Đó là, một bảng đắt tiền để lấy hàng từ đó.

Cuối cùng, cách tốt nhất để tăng tốc truy vấn của bạn là thêm mệnh đề WHERE!

+0

những chỉ số sẽ giết tôi vào chèn? về WHERE - Tôi đang sử dụng phép nối này để điền vào một bảng tạm thời mà tôi sẽ sử dụng để tìm biểu thức (nếu có) cho một tập hợp các cặp tên-giá trị đã cho (thuộc tính). Vì vậy, tôi đoán tôi có thể lọc với OR disjuncts attributeNames + AttributeValues ​​trên truy vấn này để tăng tốc độ nó – JohnIdol

+0

Tôi sẽ phải tự động nối thêm OR disjuncts mặc dù 'vì tôi cần smt như WHERE (attributeName =' X 'AND attributeValue =' Y ') OR (attributeName = 'Z' AND attributeValue = 'W') ... và cứ thế! Vì vậy, tôi có thể sẽ mất thời gian lặp qua bảng với các cặp giá trị tên và xây dựng các mệnh đề này – JohnIdol

+0

Luôn có sự cân bằng các chỉ mục để chèn. Một lần nữa (và không may), không có câu trả lời một kích thước phù hợp. Nếu bạn chỉ có một hoặc hai chỉ mục, và cho rằng chỉ số này không được nhóm lại, nó có khả năng sẽ không giết bạn. Điều đó nói rằng, đây là một chỉ số được đánh giá cao hướng tới một truy vấn cụ thể, vì vậy hãy sử dụng theo quyết định của bạn. – Matt

2

Tôi đặt cược vấn đề của bạn là số lượng lớn các hàng đang được chèn vào bảng tạm thời đó. Có cách nào bạn có thể thêm mệnh đề WHERE trước khi bạn SELECT mỗi hàng trong cơ sở dữ liệu không?

+0

Tôi đoán tôi có thể lọc bằng OR disjuncts trên thuộc tính attributeNames + AttributeValues ​​trên truy vấn này để tăng tốc nhưng vấn đề là tôi 'd phải tự động nối thêm OR disjuncts' vì tôi cần smt như WHERE (attributeName = 'X' AND attributeValue = 'Y') HOẶC (attributeName = 'Z' AND attributeValue = 'W') ... để có được cuối cùng ExpressionId của một tập hợp các cặp tên-giá trị đã cho. Vì vậy, tôi có thể mất thời gian lặp qua bảng với các cặp tên-giá trị và xây dựng các OR disjuncts cho mệnh đề WHERE. – JohnIdol

+1

Điều đó vẫn có thể tốt hơn? Hoặc bạn có thể nhìn vào bộ nhớ đệm mà bảng tạm thời. Hoặc là đệm nó trong một số bộ nhớ ở tầng giữa, hoặc làm cho bảng tạm thời đó là một bảng vĩnh viễn và cập nhật nó khi các hàng từ các bảng khác thay đổi? – JerSchneid

+0

Nếu tôi không thể có được những cải tiến đáng kể khi chơi với các chỉ mục, tôi sẽ đi với tính năng lọc động của phép nối như mô tả din nhận xét trước đó - Tôi muốn tránh việc có các bảng lưu trữ trong bộ nhớ đệm! – JohnIdol

1

Nếu tôi hiểu sơ đồ của bạn một cách chính xác, bạn đang nói rằng bảng của bạn kinda giống như thế này:

Expressions: PK - ExpressionID, AttributeID 
Attributes: PK - AttributeID 

Giả sử rằng mỗi PK là một nhóm chỉ số, mà vẫn có nghĩa là một Quét chỉ mục được yêu cầu trên bảng biểu thức. Bạn có thể muốn xem xét việc tạo chỉ mục trên các biểu thức Biểu thức chẳng hạn như: AttributeID, ExpressionID. Điều này sẽ giúp ngăn chặn việc quét chỉ mục hiện đang xảy ra.

+0

sự hiểu biết của bạn là chính xác. Bạn có nghĩa là thêm một chỉ số nonclustered trên biểu thức cho (ExpressionId, AttributeId) khác với chỉ mục nhóm đã có? – JohnIdol

Các vấn đề liên quan