Đây là vấn đề tương tự với những gì tôi gặp phải gần đây. Tôi cần phải chọn từ một bảng những hàng đó giao nhau với một danh sách lớn các khóa chính. Câu hỏi đặt ra là làm thế nào để gửi danh sách khóa lớn tới máy chủ SQL một cách hiệu quả dưới dạng nhanh và hiệu quả để sử dụng.
Điều gì hoạt động thực sự tốt cho loại tình huống này là loại dữ liệu XML. Nếu bạn tạo một thủ tục lưu sẵn có một tham số kiểu XML, bạn có thể định dạng trước đầu vào thành một đoạn XML. Ví dụ: giả sử đoạn XML sẽ trông như sau:
<a>
<b>1</b>
<b>3</b>
<b>7</b>
<b>14</b>
<b>147</b>
</a>
Tôi đã đặt tên các phần tử ("a" và "b") vì tên dài hơn có nghĩa là nhiều byte truyền từ khách hàng hơn máy chủ SQL. Đây là cách bạn sẽ chọn tất cả các nội dung của các yếu tố "b" như là một tập kỷ lục:
declare @x xml
set @x = '<a><b>1</b><b>3</b><b>7</b><b>14</b><b>147</b></a>'
select t.item.value('.', 'int') from @x.nodes('//a/b') as t(item)
Mặc dù cú pháp là khó hiểu, kiểu XML có thể được truy vấn giống như một bảng. Bây giờ bạn sẽ thấy nơi này đang diễn ra. Nếu chúng ta có thể truy vấn kiểu XML như một bảng, chúng ta có thể giao nhau rằng với bảng khác:
select * from MyTable where ID in
(select t.item.value('.', 'int') from @x.nodes('//a/b') as t(item))
hoặc sử dụng một tham gia
;with cte as
(select ID = t.item.value('.', 'int') from @x.nodes('//a/b') as t(item))
select * from MyTable inner join cte on MyTable.ID = cte.ID
Bạn cần phải chạy cả hai phiên bản để xem sẽ nhanh hơn cho dữ liệu của bạn. Tôi thấy JOIN hoạt động nhanh hơn với dữ liệu của tôi. Đây là một thủ tục lưu trữ mà có kiểu XML như là đầu vào và spits lại hàng chọn chúng tôi:
create procedure MyProc @x xml as
begin
set nocount on
;with cte as
(select ID = t.item.value('.', 'int') from @x.nodes('//a/b') as t(item))
select * from MyTable inner join cte on Table.ID = cte.ID
end
Một cuộc gọi mẫu của các thủ tục lưu trữ mới:
exec MyProc '<a><b>1</b><b>3</b><b>7</b><b>14</b><b>147</b></a>'
Tôi cũng thấy rằng việc thêm một lược đồ XML cho đoạn đầu vào giúp tăng tốc độ lưu trữ một chút. Tôi sẽ không đi sâu vào các chi tiết của các lược đồ XML ở đây, nhưng ý tưởng là nói cho SQL trước những gì mà đoạn XML sẽ trông như thế nào. Dưới đây là cách chúng tôi sẽ đầu vào giản đồ của chúng tôi:
create xml schema collection MyInputSchema as
'<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="a">
<xsd:complexType>
<xsd:complexContent>
<xsd:restriction base="xsd:anyType">
<xsd:sequence>
<xsd:element name="b" type="xsd:integer" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>'
Bây giờ chúng ta có thể kết hợp sơ đồ này với các đầu vào cho thủ tục lưu trữ của chúng tôi như thế này:
create procedure MyProc @x xml(MyInputSchema) as
begin
set nocount on
;with cte as
(select ID = t.item.value('.', 'int') from @x.nodes('//a/b') as t(item))
select * from MyTable inner join cte on Table.ID = cte.ID
end
Với tất cả điều này tại chỗ, tôi đã có thể gửi một Đoạn XML của 43,016 ký tự từ máy khách của tôi đến máy chủ SQL và lấy lại một tập kết quả rất nhanh. Tôi đã thử nghiệm 1.000 yêu cầu trên 10 luồng cho tổng số 10.000 yêu cầu. Kết quả là 72 yêu cầu được xử lý mỗi giây. Tất nhiên, tỷ lệ phần trăm của bạn sẽ khác nhau tùy thuộc vào phần cứng và phần mềm của bạn.
LƯU Ý: Mã này hoạt động trên SQL 2005 và cũng nên hoạt động vào năm 2008.
cũng có thể sử dụng biến bảng ở đây –