Sql 用不同的字符串比较拉丁语1_General_CI_AI slow performance
我有一个sql查询,用于在两列中搜索名称:Sql 用不同的字符串比较拉丁语1_General_CI_AI slow performance,sql,sql-server,performance,Sql,Sql Server,Performance,我有一个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.GiaV
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
我的问题是线路(靠近最后一条线路)
当我搜索字符串“tns”时,性能太慢:CPU时间=1515毫秒,运行时间=1530毫秒
但当我搜索字符串“ton”时:CPU时间=203毫秒,运行时间=204毫秒
然后我删除了第二个COLLATE拉丁语1\u General\u CI\u 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毫秒
校对拉丁语1\u General\u CI\u AI
做了什么
为什么搜索这些字符串时的性能如此不同
幸运的是,
sp.MaNhaSanXuat
列没有使用重音,因此我可以删除第二个COLLATE Latin1\u General\u CI\u AI
,但如果它使用重音,我应该如何提高性能?尝试使用二进制排序规则来提高性能:
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)
确保定义了列(在
CREATE TABLE
语句中)以使用所需的排序规则(在您的情况下是Latin1\u General\u CI\u AI
),并确保为列设置了索引。然后从查询中删除COLLATE拉丁语1\u General\u CI\u AI
部分。这应该是这里所需要的一切
查询运行缓慢,原因可能是没有声明适当的索引,或者列的排序规则与查询中使用的显式排序规则不同。在性能方面,使用与基础列不同的排序规则总是一个危险信号,因为它可能会跳过索引(部分或全部),从而导致性能下降。检查您的执行计划以了解详细信息。您是否在查询执行之间清除了
缓存/缓冲区
?是的,我在删除第二个COLLATE-Latin1\u-General\u-CI\u-AI
后清除了缓存,性能确实得到了提高,当我将COLLATE-Latin1\u-General\u-CI\u-AI
添加回来时,搜索字符串“tns”时的性能又变慢了(大约1500ms),但搜索字符串“ton”时仍然很快,我再次测试,每次执行查询时都会清除缓存/缓冲区。结果与上面相同。搜索字符串“tns”时的执行时间总是比搜索字符串“ton”长得多(1500ms vs 160ms,在t.Title
和sp.MaNhaSanXuat
列上使用COLLATE-Latin1\u-General\u-CI\u-AI
时,在sp.MaNhaSanXuat
列上不使用COLLATE-Latin1\u-General\u-CI\u-AI
时,性能得到改善(240ms vs-90ms)比较执行计划。我怀疑这些计划是不同的,因为在未指定COLLATE
子句时,可以获得更准确的行数估计。使用非sargableCOLLATE
表达式的行数估计可能有显著差异。尝试使用二进制排序来提高性能
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)