我有一个sql查询,用于在两列中搜索名称:
set statistics time on
select top 200 lsp.Id, sp.Id as SanPhamId, t.Title, sp.MaNhaSanXuat, lsp.NhaSanXuat_id, ISNULL(lsp.GiaSi, 0) AS GiaSi, ISNULL(lsp.GiaLe, 0) AS GiaLe, ISNULL(lsp.GiaThau, 0) AS GiaThau
, ISNULL(lsp.GiaVangLai, 0) AS GiaVangLai, ISNULL(lsp.GiaLoai1, 0) AS GiaLoai1, ISNULL(lsp.GiaLoai2, 0) AS GiaLoai2, ISNULL(lsp.GiaLoai3, 0) AS GiaLoai3, ISNULL(lsp.GiaLoai4, 0) AS GiaLoai4, ISNULL(lsp.ChietKhau, 0) AS ChietKhau, ta.TermRecord_id
, case when aut.DisplayAlias in(N'donvi/cay-x-met', 'donvi/tam-x-met', 'donvi/cuon-x-met') then cast(sp.SoLuongCoTheBan as nvarchar) + ' x '+ cast(sp.ChieuDaiCoTheBan as nvarchar)
when aut.DisplayAlias = N'donvi/cay-x-met-cđ' then case sp.TinhTrang when 'TonKho' then cast(round(sp.ChieuDaiCoTheBan/sp.ChieuDaiNhap, 2) as nvarchar) else cast(sp.SoLuongCoTheBan as nvarchar) end
else cast(sp.SoLuongCoTheBan as nvarchar) end as CotheBan
, sp.TinhTrang, aut.DisplayAlias, autlh.DisplayAlias as LoaiHang
from
Futurify_QLBH_KhoHang_LoaiSanPhamPartRecord lsp
inner join Orchard_Taxonomies_TermContentItem ta on lsp.Id = ta.TermsPartRecord_id
inner join Orchard_Framework_ContentItemVersionRecord pub on pub.ContentItemRecord_id = lsp.Id
inner join Title_TitlePartRecord t on t.Id = pub.Id
inner join Futurify_QLBH_KhoHang_SanPhamPartRecord sp on sp.LoaiSanPham_id = lsp.Id
inner join Orchard_Framework_ContentItemVersionRecord spver on spver.ContentItemRecord_id = sp.Id
inner join Orchard_Autoroute_AutoroutePartRecord aut on aut.ContentItemRecord_id = sp.DonVi_Id
inner join Orchard_Framework_ContentItemVersionRecord termVer on termVer.Id = aut.Id
inner join Orchard_Taxonomies_TermContentItem termlh on lsp.Id = termlh.TermsPartRecord_id
inner join Orchard_Framework_ContentItemVersionRecord termlhver on termlh.TermRecord_id = termlhver.ContentItemRecord_id
inner join Orchard_Autoroute_AutoroutePartRecord autlh on autlh.Id = termlhver.Id
where ta.Field IN ('DonVi', 'LoaiSong') AND termVer.Published = 1 and pub.Published = 1 and spver.Published = 1 and sp.TrangThaiSanPham = 'Active' and termlhver.Published = 1 and termlh.Field = 'LoaiHang'
and (t.Title LIKE N'%tns%' COLLATE Latin1_General_CI_AI or sp.MaNhaSanXuat LIKE N'%tns%' COLLATE Latin1_General_CI_AI)
order by lsp.Id
set statistics time off
我的问题是行(靠近最后一行)
and (t.Title LIKE N'%tns%' COLLATE Latin1_General_CI_AI or sp.MaNhaSanXuat LIKE N'%tns%' COLLATE Latin1_General_CI_AI)
当我搜索字符串" tns"时,性能太慢:CPU时间= 1515毫秒,经过时间= 1530毫秒。
但是当我搜索字符串" ton" :CPU时间= 203毫秒,经过时间= 204毫秒。
然后我删除了第二个COLLATE Latin1_General_CI_AI
and (t.Title LIKE N'%tns%' COLLATE Latin1_General_CI_AI or sp.MaNhaSanXuat LIKE N'%tns%')
我搜索字符串时的表现" tns"改进:CPU时间= 203毫秒,经过时间= 205毫秒。
当我搜索字符串" ton"也改进了:CPU时间= 79毫秒,经过时间= 138毫秒。
COLLATE Latin1_General_CI_AI
做了什么?
为什么搜索这些字符串时的性能如此不同?
很幸运,专栏sp.MaNhaSanXuat
没有使用重音,所以我可以删除第二个COLLATE Latin1_General_CI_AI
,但如果它使用重音,我该怎么做才能改善表现?
答案 0 :(得分:0)
尝试使用二进制排序规则来提高性能:
ALTER TABLE dbo.Title_TitlePartRecord
ADD Title2 AS UPPER(VarCol) COLLATE Latin1_General_100_Bin2 PERSISTED
GO
ALTER TABLE dbo.Futurify_QLBH_KhoHang_SanPhamPartRecord
ADD MaNhaSanXuat2 AS UPPER(MaNhaSanXuat) COLLATE Latin1_General_100_BIN2 PERSISTED
GO
DECLARE @mask NVARCHAR(100) = N'tns'
...
WHERE ta.Field IN ('DonVi', 'LoaiSong')
AND termVer.Published = 1
AND pub.Published = 1
AND spver.Published = 1
AND sp.TrangThaiSanPham = 'Active'
AND termlhver.Published = 1
AND termlh.Field = 'LoaiHang'
AND (
t.Title2 LIKE N'%' + UPPER(@mask) + N'%' COLLATE Latin1_General_100_Bin2
OR
sp.MaNhaSanXuat LIKE N'%' + UPPER(@mask) + N'%' COLLATE Latin1_General_100_Bin2
)
...
OPTION(RECOMPILE)
答案 1 :(得分:0)
确保您的列已定义(在您的 CREATE TABLE
语句中)以使用您需要的排序规则(在您的情况下为 Latin1_General_CI_AI
)并确保您为列设置了索引.然后从您的查询中删除 COLLATE Latin1_General_CI_AI
部分。这应该就是这里所需要的。
您的查询运行缓慢,因为您没有声明适当的索引,或者您的列的排序规则与您在查询中使用的显式排序规则不同。使用与基础列上的排序规则不同的排序规则在性能方面始终是一个危险信号,因为它可能会跳过索引(部分或全部)并因此导致性能不佳。检查您的执行计划以了解细节。