Laravel 프로젝트에서 트래픽이 증가함에 따라 데이터베이스가 쿼리 속도를 쿼리하는 것은 드문 일이 아닙니다. 최근 부동산 플랫폼의 백엔드를 최적화했을 때이 문제를 발견하고 그로부터 몇 가지 교훈을 얻었습니다.
데이터베이스 최적화는 개발 가능하고 고성능 응용 프로그램의 주요 영역 중 하나입니다. 데이터 검색 속도를 향상시키고 응답 시간과 페이지로드 시간을 단축하고 서버로드를 줄이고 비용을 최소화 할 수 있습니다.
부동산 플랫폼의 도전
상상 : 여러 도시에 서비스를 제공하고 고급 검색 필터가 장착 된 훌륭한 부동산 플랫폼을 구축합니다. 부동산 목록이 빠르게로드되고 검색 필터가 빠르게 반응하며 모든 것이 완벽 해 보입니다. 그러나 응용 프로그램 규모의 확장과 사용자 기반의 성장으로 인해 개발 프로세스 중에 완벽하게 수행 된 문의는 더 길고 길어지기 시작했습니다. 친숙하게 들리나요?
이것이 바로 우리 플랫폼이 직면 한 것입니다. Sentry Alert는 프로덕션 환경에서 느린 데이터베이스 쿼리가있어 경고를 제공합니다. 모니터링은 검색 결과 쿼리가 완료하는 데 5 초 이상 걸린다는 것을 보여줍니다. 이것은 우리가 약속하는 빠른 경험과는 거리가 멀다!
공통 쿼리 결함 (피하는 방법)
1. n 1 문의 질문 : 데이터베이스의 비밀 적
당신은 게임을 할 때 기억하고, 한 적이 많은 작은 적을 물리 칠 것인가? 이것은 본질적으로 Laravel의 n 1 쿼리 문제와 동일합니다. 부동산 목록을 얻은 다음 각 부동산에 대해 추가 문의를하여 관련 데이터를 얻습니다. 알기 전에 데이터베이스는 수백 개의 문의를 다루고 있습니다.
다음은 전형적인 표현입니다 :
2. 데이터베이스 인덱스의 기술
데이터베이스 색인을 쓰기 인덱스와 비교할 수 있습니다. 각 페이지를 스캔하지 않고 원하는 것을 찾는 데 도움이됩니다. 그러나 인덱스는 각 열에만 추가되지 않습니다. -Depth로 탐색합시다.
다른 유형의 인덱스를 이해하십시오
인덱스 전략의 모범 사례
조합 인덱스의 열 순서는 중요합니다
선택적 인덱스
모든 열에 인덱스가 필요한 것은 아닙니다. 일부 열을 색인화 할 열을 선택하면 다음이 포함됩니다
where 절에서 자주 사용되는 열과 명령문별로 사용됩니다.
인덱스 외부 키 열
선택성이 낮은 열을 색인하지 않음 (예 : 부울 로고)
<code>// 优化前
$properties = Property::all();
foreach ($properties as $property) {
echo $property->agent->name; // 每个房产都会触发一个新的查询
}
// 优化后
// 使用 `with()` 进行预加载
$properties = Property::with(['agent'])->get();
foreach ($properties as $property) {
echo $property->agent->name; // 不需要额外的查询!
}</code>
로그인 후 복사
로그인 후 복사
모니터링 인덱스 사용
<code>// 基本的单列索引
Schema::table('properties', function (Blueprint $table) {
$table->index('price');
});
// 多列的组合索引
Schema::table('properties', function (Blueprint $table) {
$table->index(['city', 'price']); // 顺序很重要!
});
// 唯一索引
Schema::table('properties', function (Blueprint $table) {
$table->unique('property_code');
});</code>
로그인 후 복사
로그인 후 복사
3. 필요한 내용을 선택하십시오.
내가 본 것 중 가장 일반적인 오류 중 하나는 기본적으로 Select *를 사용하는 것입니다. 이것은 식료품 점에가는 것과 같지만 가게 전체에서 물건을 사는 것과 같으며 식사 재료 만 있으면됩니다. 다음은 더 나은 방법입니다 :
<code>// 优化前
$properties = Property::all();
foreach ($properties as $property) {
echo $property->agent->name; // 每个房产都会触发一个新的查询
}
// 优化后
// 使用 `with()` 进行预加载
$properties = Property::with(['agent'])->get();
foreach ($properties as $property) {
echo $property->agent->name; // 不需要额外的查询!
}</code>
로그인 후 복사
로그인 후 복사
4. 큰 데이터 세트의 분할
큰 데이터 세트를 처리 할 때는 시스템의 자원을 압도하고 병목 현상을 유발할 수있는 단일 작업에서 모든 컨텐츠를 처리하십시오. 대신 Laravel의 청크 방법을 사용하여 기록 가능한 배치 프로세싱 레코드를 관리 할 수 있습니다.
5. 효과적이고 효과적인 캐시 전략
캐시는 모든 것을 기억할 수있는 좋은 조수와 같습니다. 그러나 어시스턴트와 마찬가지로 명확한 지침이 필요합니다.
<code>// 基本的单列索引
Schema::table('properties', function (Blueprint $table) {
$table->index('price');
});
// 多列的组合索引
Schema::table('properties', function (Blueprint $table) {
$table->index(['city', 'price']); // 顺序很重要!
});
// 唯一索引
Schema::table('properties', function (Blueprint $table) {
$table->unique('property_code');
});</code>
로그인 후 복사
로그인 후 복사
전문 팁 : 모든 것을 캐시하지 마십시오! 초점 :
자주 액세스하는 데이터
높은 비용으로 데이터를 계산합니다
자주 변경되지 않은 데이터는 입니다
<code> // 良好:匹配查询模式
$properties = Property::where('city', 'New York')
->whereBetween('price', [200000, 500000])
->get();
// 索引应匹配此模式
$table->index(['city', 'price']); // 首先是城市,然后是价格</code>
로그인 후 복사
모범 사례
먼저 모니터링 한 다음 를 최적화하십시오
조기 최적화의 함정에 들어 가지 마십시오. Laravel의 구축 된 쿼리 로그 또는 망원경과 같은 도구를 사용하여 실제 병목 현상을 식별하십시오.
주기 대신 모임으로 생각하는
데이터베이스를 쿼리하는 Foreach 루프를 작성한 것을 알 때마다 한 걸음 물러서서 단일 쿼리를 사용하여 처리 할 수 있는지 물어보십시오.
전략적으로 전화
모든 것이 캐시 될 필요는 없습니다. 자주 액세스하고 비용 쿼리에주의하십시오. -
색인을 만듭니다
책의 디렉토리로 인덱스를 싸우고 있습니다. 사물을 신속하게 찾을 수있는 충분한 세부 사항이 필요하지만 너무 많지는 않지만 디렉토리는 책 자체보다 길다.
-
피해야하는 일반적인 결함
불필요한 관계 를 "사전로드"하지 마십시오
주기에서 쿼리 실행을 피하십시오 (위장에 대한 n 1 문제의 트랩)
모든 것을 캐시하지 마십시오.
대형 데이터 세트의 비 인덱스 열에 OrderBY를 사용할 때 조심하십시오
Clauses에서 거의 사용되지 않는 열에 대한 인덱스를 생성하지 마십시오.
자주 업데이트를 피하십시오
결론 : 이것은 목적지가 아닌 여행입니다
데이터베이스 최적화는 목록에서 선택할 수있는 한 번의 작업이 아닙니다. 정원을 돌보는 것과 비슷합니다 -- 정기적 인 유지 보수 및 최상의 결과를 얻기위한주의를 기울입니다. 이러한 기본 지식부터 시작하여 응용 프로그램의 성능을 모니터링하면 방법이 계속 향상됩니다.
목표는 당신이 아는 모든 최적화 기술을 달성하는 것은 아닙니다. 대신, 코드 유지 보수와 성능 사이에 특정 사용 사례에 적합한 균형 포인트를 찾아야합니다. 때로는 간단한 프리로드 명세서가 복잡한 최적화 전략을 수행하기 위해 몇 시간을 소비하는 것보다 더 도움이됩니다.
라벨 프로젝트에서 어떤 문제가 발생했으며 Laravel 프로젝트에서 어떤 문제가 발생 했습니까? 의견에서 논의합시다! <..>
위 내용은 Laravel Performance Tuning : 확장 성을위한 데이터베이스 쿼리 최적화의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!