찾다
데이터 베이스MySQL 튜토리얼SqlServer StringToTable性能测试

问题起因: 最近做的项目DB数据量比较大(基本上一个月的数据就是10亿),而工程中Proc参数中包含有id拼接字符串,id拼接字符串格式:1,2,4,5,100,301。当数据量很小的情况下,这样做没有问题,但一旦数据量到达亿级,运行会很耗时,比如:当这样的参数id拼接

  • 问题起因:

最近做的项目DB数据量比较大(基本上一个月的数据就是10亿),而工程中Proc参数中包含有id拼接字符串,id拼接字符串格式:1,2,4,5,100,301。当数据量很小的情况下,这样做没有问题,但一旦数据量到达亿级,运行会很耗时,比如:当这样的参数id拼接字符串中包含有10万个id的时候(我们实际应用中确实有这么多个id需要传到数据库,而且这样的id是从库中取出后,又经过程序的筛选后剩余的id),像这样的语句:

<span>Declare</span> <span>@IDS</span> <span>nvarchar</span>(<span>max</span><span>);
</span><span>Set</span> <span>@IDS</span><span>=</span><span>'</span><span>10w个id用逗号分割组成的字符串</span><span>'</span><span>;
</span><span>Select</span> T10.<span>TEXT</span>,T10.Name <span>FROM</span> DX.M <span>as</span> T10 <span>inner</span> <span>join</span> dbo.StringToTable(<span>@IDS</span>,<span>'</span><span>,</span><span>'</span>) <span>as</span> T11 <span>on</span> T10.ID<span>=</span>T11.ID;

执行了18个小时还未查询出数据。

备注:

虚拟机配置:内存:64G;CPU核数:40。

  • DBA建议:

我测试了下,性能还算可以。在解析5000个逗号之内性能还行,太多了,性能就急速下降了。 

最初的那个版本其实还是很常用的,性能要比改写之后的要好一些(在字符串特别长的情况下)。但是同样存在,如果字符串太长,性能急速下降的问题。

如果真的有5W以上逗号的字符串。这个SqlServer在执行计划上会消耗很多性能。

(自己也可以测试一下解析5000个逗号串和解析5W个字符串的差距,并不是5000字符串消耗时间*10的线性关系) 

所以应当写一个循环,一次处理一部分。

比如以下两种方法:

1. 每次截取前1W个字符串,解析出来之后插入到临时表,然后在解析后面的,在插入到临时表,循环处理。最后临时表和实际表进行关联。

insert into #t1

select id

from dbo.stringtotable(@字符串1‍)

 

insert into #t1

select id

from dbo.stringtotable(@字符串2)‍

 

2。用in的方式,每次where条件 in 一部分。然后将结果union all起来。

类似如下

select id

from table a

where id in (@字符串1)

union all

select id

from table a

where id in (@字符串2)‍

 

两种方法都可行。在字符串较短的情况下,第二种方法应该好一些。字符串较长,第一种应该好一些。

  • 测试代码:

<span>Declare</span> <span>@MRE_MROOIDS</span> <span>Nvarchar</span>(<span>Max</span><span>);

</span><span>Set</span> <span>@MRE_MROOIDS</span><span>=</span><span>'</span><span>2,4,5,396009,</span><span>'</span><span>;
</span><span>--</span><span>Set @MRE_MROOIDS='2,4,5,6,7,8,9,10,11,14,15,16,17,18,20,21,23,24,25,26,29,30';</span>

<span>Declare</span> <span>@SplitChar</span> <span>nvarchar</span>(<span>2</span><span>);
</span><span>Declare</span> <span>@EndIndex</span> <span>int</span><span>;
</span><span>Declare</span> <span>@Step</span> <span>int</span><span>;
</span><span>Declare</span> <span>@LastChars</span> <span>nvarchar</span>(<span>MAX</span><span>);
</span><span>Declare</span> <span>@CurrentTempChars</span> <span>nvarchar</span>(<span>max</span><span>);

</span><span>Set</span> <span>@LastChars</span><span>=</span><span>@MRE_MROOIDS</span><span>;
</span><span>Set</span> <span>@Step</span><span>=</span><span>5000</span><span>;
</span><span>Set</span> <span>@EndIndex</span><span>=</span><span>0</span><span>;
</span><span>Set</span> <span>@SplitChar</span><span>=</span><span>'</span><span>,</span><span>'</span><span>;

</span><span>IF</span> <span>EXISTS</span>(<span>SELECT</span> <span>*</span> <span>FROM</span> tempdb.dbo.sysobjects <span>where</span> id<span>=</span><span>OBJECT_ID</span>(N<span>'</span><span>tempdb..#StringToTableEntry_Temp10</span><span>'</span><span>))
    </span><span>Begin</span>
        <span>Drop</span> <span>Table</span><span> #StringToTableEntry_Temp10;            
    </span><span>End</span>    
    
<span>Create</span> <span>Table</span> #StringToTableEntry_Temp10(ID <span>INT</span><span>);


</span><span>While</span>(<span>LEN</span>(<span>@LastChars</span>)<span>></span><span>@Step</span><span>)
</span><span>Begin</span>    
    <span>Set</span> <span>@EndIndex</span><span>=</span> <span>charindex</span>(<span>@SplitChar</span>,<span>@LastChars</span>,<span>@Step</span><span>);
    
    </span><span>Set</span> <span>@CurrentTempChars</span><span>=</span><span>SubString</span>(<span>@LastChars</span>,<span>0</span>,<span>@EndIndex</span><span>);
    </span><span>--</span><span> insert into temp table</span>
    <span>Insert</span> <span>Into</span><span> #StringToTableEntry_Temp10
    </span><span>Select</span> Id <span>from</span> dbo.StringToTable2(<span>@CurrentTempChars</span>,<span>'</span><span>,</span><span>'</span><span>);
    
     </span><span>Set</span> <span>@LastChars</span><span>=</span><span>SubString</span>(<span>@LastChars</span>,<span>@EndIndex</span><span>+</span><span>1</span>,<span>LEN</span>(<span>@LastChars</span>)<span>-</span><span>@EndIndex</span><span>+</span><span>1</span><span>)
     </span><span>--</span><span>Select @LastChars as LastChars;</span>
     <span>Set</span> <span>@EndIndex</span><span>=</span><span>@EndIndex</span><span>+</span><span>@Step</span><span>;     
</span><span>End</span>

<span>If</span> <span>LEN</span>(<span>@LastChars</span>)<span>></span><span>0</span> <span>Begin</span>
    <span>Insert</span> <span>Into</span><span> #StringToTableEntry_Temp10
    </span><span>Select</span> Id <span>from</span> dbo.StringToTable2(<span>@LastChars</span>,<span>'</span><span>,</span><span>'</span><span>);
</span><span>End</span>


<span>Select</span> <span>COUNT</span>(<span>0</span>) <span>From</span> #StringToTableEntry_Temp10

 

StringToTable2函数:

<span>ALTER</span> <span>FUNCTION</span> <span>[</span><span>dbo</span><span>]</span>.<span>[</span><span>StringToTable</span><span>]</span><span>
(
    </span><span>@ids</span> <span>[</span><span>nvarchar</span><span>]</span>(<span>max</span><span>),
    </span><span>@separator</span> <span>[</span><span>char</span><span>]</span>(<span>1</span><span>)
)
</span><span>RETURNS</span> <span>@IdsTable</span> <span>TABLE</span><span>
(
    </span><span>[</span><span>Id</span><span>]</span> <span>INT</span> <span>NOT</span> <span>NULL</span><span>
)
</span><span>AS</span>
<span>BEGIN</span>
    <span>IF</span>(<span>RIGHT</span>(<span>@ids</span>,<span>1</span>)<span>=</span><span>@separator</span><span>)
        </span><span>BEGIN</span>
            <span>SET</span> <span>@ids</span><span>=</span><span>SUBSTRING</span>(<span>@ids</span>,<span>0</span>,<span>LEN</span>(<span>@ids</span><span>));
        </span><span>END</span>

    <span>--</span><span>下面的方式性能更好</span>
    <span>IF</span>(<span>LEN</span>(<span>@ids</span>) <span>></span> <span>0</span><span>)
        </span><span>BEGIN</span>
            <span>DECLARE</span> <span>@i</span> <span>int</span><span>;        
            </span><span>SET</span> <span>@i</span> <span>=</span> <span>CHARINDEX</span>(<span>@separator</span>, <span>@ids</span><span>);
            
            </span><span>WHILE</span> <span>@i</span> <span>></span> <span>0</span>
                <span>BEGIN</span>
                    <span>INSERT</span> <span>@IdsTable</span> <span>VALUES</span>(<span>LEFT</span>(<span>@ids</span>, <span>@i</span> <span>-</span> <span>1</span><span>));            
                    </span><span>SET</span> <span>@ids</span> <span>=</span> <span>SUBSTRING</span>(<span>@ids</span>, <span>@i</span> <span>+</span> <span>1</span>, <span>LEN</span>(<span>@ids</span>) <span>-</span> <span>@i</span><span>);
                    </span><span>SET</span> <span>@i</span> <span>=</span> <span>CHARINDEX</span>(<span>@separator</span>, <span>@ids</span><span>);
                </span><span>END</span>
                
            <span>IF</span>(<span>LEN</span>(<span>@ids</span>) <span>></span> <span>0</span><span>)
                </span><span>BEGIN</span>
                    <span>INSERT</span> <span>@IdsTable</span> <span>VALUES</span>(<span>@ids</span><span>);
                </span><span>END</span>
        <span>END</span>        
    <span>RETURN</span><span>;
</span><span>END</span>

 

  • 测试结果:

 

@MRE_MROOIDS包含id记录

@Step长度

执行时间

100,000

100000

00:09:15

100,000

20000

00:03:48

100,000

10000

00:01:57

100,000

5000

00:01:01

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
MySQL의 장소 : 데이터베이스 및 프로그래밍MySQL의 장소 : 데이터베이스 및 프로그래밍Apr 13, 2025 am 12:18 AM

데이터베이스 및 프로그래밍에서 MySQL의 위치는 매우 중요합니다. 다양한 응용 프로그램 시나리오에서 널리 사용되는 오픈 소스 관계형 데이터베이스 관리 시스템입니다. 1) MySQL은 웹, 모바일 및 엔터프라이즈 레벨 시스템을 지원하는 효율적인 데이터 저장, 조직 및 검색 기능을 제공합니다. 2) 클라이언트 서버 아키텍처를 사용하고 여러 스토리지 엔진 및 인덱스 최적화를 지원합니다. 3) 기본 사용에는 테이블 작성 및 데이터 삽입이 포함되며 고급 사용에는 다중 테이블 조인 및 복잡한 쿼리가 포함됩니다. 4) SQL 구문 오류 및 성능 문제와 같은 자주 묻는 질문은 설명 명령 및 느린 쿼리 로그를 통해 디버깅 할 수 있습니다. 5) 성능 최적화 방법에는 인덱스의 합리적인 사용, 최적화 된 쿼리 및 캐시 사용이 포함됩니다. 모범 사례에는 거래 사용 및 준비된 체계가 포함됩니다

MySQL : 소기업에서 대기업에 이르기까지MySQL : 소기업에서 대기업에 이르기까지Apr 13, 2025 am 12:17 AM

MySQL은 소규모 및 대기업에 적합합니다. 1) 소기업은 고객 정보 저장과 같은 기본 데이터 관리에 MySQL을 사용할 수 있습니다. 2) 대기업은 MySQL을 사용하여 대규모 데이터 및 복잡한 비즈니스 로직을 처리하여 쿼리 성능 및 트랜잭션 처리를 최적화 할 수 있습니다.

Phantom은 무엇을 읽고, Innodb는 어떻게 그들을 막을 수 있습니까 (다음 키 잠금)?Phantom은 무엇을 읽고, Innodb는 어떻게 그들을 막을 수 있습니까 (다음 키 잠금)?Apr 13, 2025 am 12:16 AM

InnoDB는 팬텀 읽기를 차세대 점화 메커니즘을 통해 효과적으로 방지합니다. 1) Next-Keylocking은 Row Lock과 Gap Lock을 결합하여 레코드와 간격을 잠그기 위해 새로운 레코드가 삽입되지 않도록합니다. 2) 실제 응용 분야에서 쿼리를 최적화하고 격리 수준을 조정함으로써 잠금 경쟁을 줄이고 동시성 성능을 향상시킬 수 있습니다.

MySQL : 프로그래밍 언어는 아니지만 ...MySQL : 프로그래밍 언어는 아니지만 ...Apr 13, 2025 am 12:03 AM

MySQL은 프로그래밍 언어가 아니지만 쿼리 언어 SQL은 프로그래밍 언어의 특성을 가지고 있습니다. 1. SQL은 조건부 판단, 루프 및 가변 작업을 지원합니다. 2. 저장된 절차, 트리거 및 기능을 통해 사용자는 데이터베이스에서 복잡한 논리 작업을 수행 할 수 있습니다.

MySQL : 세계에서 가장 인기있는 데이터베이스 소개MySQL : 세계에서 가장 인기있는 데이터베이스 소개Apr 12, 2025 am 12:18 AM

MySQL은 오픈 소스 관계형 데이터베이스 관리 시스템으로, 주로 데이터를 신속하고 안정적으로 저장하고 검색하는 데 사용됩니다. 작업 원칙에는 클라이언트 요청, 쿼리 해상도, 쿼리 실행 및 반환 결과가 포함됩니다. 사용의 예로는 테이블 작성, 데이터 삽입 및 쿼리 및 조인 작업과 같은 고급 기능이 포함됩니다. 일반적인 오류에는 SQL 구문, 데이터 유형 및 권한이 포함되며 최적화 제안에는 인덱스 사용, 최적화 된 쿼리 및 테이블 분할이 포함됩니다.

MySQL의 중요성 : 데이터 저장 및 관리MySQL의 중요성 : 데이터 저장 및 관리Apr 12, 2025 am 12:18 AM

MySQL은 데이터 저장, 관리, 쿼리 및 보안에 적합한 오픈 소스 관계형 데이터베이스 관리 시스템입니다. 1. 다양한 운영 체제를 지원하며 웹 응용 프로그램 및 기타 필드에서 널리 사용됩니다. 2. 클라이언트-서버 아키텍처 및 다양한 스토리지 엔진을 통해 MySQL은 데이터를 효율적으로 처리합니다. 3. 기본 사용에는 데이터베이스 및 테이블 작성, 데이터 삽입, 쿼리 및 업데이트가 포함됩니다. 4. 고급 사용에는 복잡한 쿼리 및 저장 프로 시저가 포함됩니다. 5. 설명 진술을 통해 일반적인 오류를 디버깅 할 수 있습니다. 6. 성능 최적화에는 인덱스의 합리적인 사용 및 최적화 된 쿼리 문이 포함됩니다.

MySQL을 사용하는 이유는 무엇입니까? 혜택과 장점MySQL을 사용하는 이유는 무엇입니까? 혜택과 장점Apr 12, 2025 am 12:17 AM

MySQL은 성능, 신뢰성, 사용 편의성 및 커뮤니티 지원을 위해 선택됩니다. 1.MYSQL은 효율적인 데이터 저장 및 검색 기능을 제공하여 여러 데이터 유형 및 고급 쿼리 작업을 지원합니다. 2. 고객-서버 아키텍처 및 다중 스토리지 엔진을 채택하여 트랜잭션 및 쿼리 최적화를 지원합니다. 3. 사용하기 쉽고 다양한 운영 체제 및 프로그래밍 언어를 지원합니다. 4. 강력한 지역 사회 지원을 받고 풍부한 자원과 솔루션을 제공합니다.

InnoDB 잠금 장치 (공유 잠금, 독점 잠금, 의도 잠금, 레코드 잠금, 갭 잠금, 차세대 자물쇠)를 설명하십시오.InnoDB 잠금 장치 (공유 잠금, 독점 잠금, 의도 잠금, 레코드 잠금, 갭 잠금, 차세대 자물쇠)를 설명하십시오.Apr 12, 2025 am 12:16 AM

InnoDB의 잠금 장치에는 공유 잠금 장치, 독점 잠금, 의도 잠금 장치, 레코드 잠금, 갭 잠금 및 다음 키 잠금 장치가 포함됩니다. 1. 공유 잠금을 사용하면 다른 트랜잭션을 읽지 않고 트랜잭션이 데이터를 읽을 수 있습니다. 2. 독점 잠금은 다른 트랜잭션이 데이터를 읽고 수정하는 것을 방지합니다. 3. 의도 잠금은 잠금 효율을 최적화합니다. 4. 레코드 잠금 잠금 인덱스 레코드. 5. 갭 잠금 잠금 장치 색인 기록 간격. 6. 다음 키 잠금은 데이터 일관성을 보장하기 위해 레코드 잠금과 갭 잠금의 조합입니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기

SublimeText3 Linux 새 버전

SublimeText3 Linux 새 버전

SublimeText3 Linux 최신 버전

ZendStudio 13.5.1 맥

ZendStudio 13.5.1 맥

강력한 PHP 통합 개발 환경

SublimeText3 영어 버전

SublimeText3 영어 버전

권장 사항: Win 버전, 코드 프롬프트 지원!

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기