2016-10-11 2 views
0

내 사이트가 내용을로드하는 데 너무 오래 걸리며 mysql 서비스에 사용되는 CPU로드가 가끔 200 %에 도달합니다. 표를 확인하면 표가 모든 열이 색인으로 사용되었음을 알게되었습니다. 이게 맞습니까? 성능에 영향을 미칠 수 있습니까?mysql 데이터베이스의 모든 컬럼을 인덱스하는 것이 맞습니까?

내 서버 구성 : 16GB RAM, 3.4GHz 대부분의 테이블에는 약 25k ~ 50k 라인이 있습니다. 그리고 10 ~ 20 칼럼. 모든 열을 인덱싱

All tables indexing are like this example. All columns as indexes

+0

큰 데이터베이스라고 할 수는 없지만 실제로는 작다고합니다. – RiggsFolly

+0

불필요한 색인은 자원 낭비입니다. 그러나 어떤 인덱스가 가장 적절한지를 결정하는 것은 실제로 실행중인 실제 쿼리와 이러한 쿼리에 대한 성능 기대치에 달려 있습니다. 성능 조정은 "색인"보다 훨씬 많습니다. 해당 테이블의 모든 인덱스가 적절할 수 있습니다. 제공된 정보에서 우리는 "*이 특별한 인덱스 세트가 가장 적절하다고 밝혀진 신중한 분석 *"과 "* 나는 단지 모든 컬럼에 인덱스를 생성합니다. 올바른 색인을 가지지 않아서 불에 태워진다. "" – spencer7593

+0

누군가 (나)가 아닌 50 달러를주고 당신을 위해 그것을 소트하십시오. – Drew

답변

0

이 올바르지 않습니다. 쓰기 조작의 성능에 영향을줍니다. 각 추가 색인은 쓰기 조작 후에 갱신하는 데 추가 시간이 필요합니다. 또한 각 색인은 추가 공간을 필요로합니다. 검색에 사용될 열만 색인화해야합니다.

+0

... 인덱싱을위한 후보는 외래 키 및 조인 조건 자, ORDER BY, GROUP BY 등에서 사용되는 열 (일부는 "검색 전용"범주에 속하지 않습니다.) – spencer7593

2

아니요, 모든 열에 대해 색인을 생성하지 않습니다. WHERE 절에 특별히 관련된 열을 인덱싱하고 경우에 따라 ORDER BY에 포함되는 경우 열을 인덱싱합니다.

SELECT name FROM users WHERE type='admin' AND active=1 

당신이 인덱스를 할 수 있습니다이 경우 :

SELECT name FROM users WHERE type='admin' 

이 경우 당신이 active,type에 인덱스를 원하는 것 : 당신이 type에 인덱스 싶어이 경우

active,type,name에 :

SELECT name FROM users WHERE type-='admin' AND active=1 ORDER BY name LIMIT 10 

더 많은 인덱스 더 느린 쓰기는 추가되지만 더 빠른 읽기가 추가됩니다. 이것은 고전적인 트레이드 오프입니다. 가시적 인 이점이있을 경우에만 필요한 색인을 신중하게 평가하고 적용하십시오. 그들이 거기 있어야한다고 생각하기 때문에 그냥 두드리지 마십시오.

초소형 테이블의 경우 인덱스가 < 인 인덱스가 1000 개이면 인덱스를 사용하면 테이블 스캔 시간이 오래 걸리기 때문에 그다지 도움이되지 않습니다. 별로 중요하지 않은 것들은 절대적으로 필수적입니다.

성능상의 문제가있는 경우 스키마가 색인의 부족이 아니라 가장 큰 장애물임을 제안합니다.

+2

.. . 더하기 외래 키 및 조인 술어의 열 및 경우에 따라 GROUP BY는 색인 ("EXPLAIN 출력의"그룹 별 색인 사용 ")을 사용하여 충족 될 수 있습니다. 일부 쿼리의 경우 "커버 인덱스"가 다른 인덱스보다 유용합니다. +10. 또한 바쁜 시스템에서 고려해야 할 중요한 사항은 잠금에 대한 경합입니다. (스토리지 엔진 선택은 성능에 영향을 줄 수 있습니다.) – spencer7593

+1

@ spencer7593 모든 중요한 문제가 있지만 가장 기본적인 경우입니다. 왜 인덱스를 추가 할 것인지에 대한 철저한 목록은 매우 길다. – tadman

+1

동의합니다. 매우 드물지만 예외적 인 상황에서만 가장 적절한 인덱스 세트가 테이블의 모든 컬럼에 대한 단일 색인이됩니다. OP 테이블의 그 인덱스 세트는 무릎 덩어리 반응의 결과 인 것 같습니다. "* 인덱스가 없을 때 불에 타서 모든 컬럼에 인덱스를 추가합니다." (그것은 부분적으로 이해할 수 있습니다. 적절한 색인의 생성이 성능 문제에 대한 야간의 "기적의 치료"처럼 보일 때 ... 모든 성능 문제에 대한 해독제가 될 것입니다.) – spencer7593

0

아니요, 모든 열을 인덱싱하지 않아야합니다. 데이터를 쓸 때 속도가 느려집니다. CPU가 때때로 200 %에 도달하는 것은 정상적인 현상이 아닙니다. 난 당신이 SQL을 확인하는 것이 좋습니다.

SELECT 문을 최적화하는 것이 좋습니다.

http://dev.mysql.com/doc/refman/5.6/en/statement-optimization.html

1.Optimize 캐시 쿼리. 함수 대신 매개 변수를 사용하십시오.

(@의 tadman의 제안을 주셔서 감사합니다) 당신이 현명하게 SELECT

// no cache 
$sql = "SELECT username FROM user WHERE signup_date >= CURDATE()"; 

// cache 
$today = date("Y-m-d"); 
$sql = "SELECT username FROM user WHERE signup_date >= '$today'"); 

2.EXPLAIN. 잠재적 인 성능 문제를 찾는 데 도움이됩니다.

EXPLAIN select name,phone from user where name="JakLiao"; 

3. 첫 번째 행 결과 만 필요하면 "LIMIT N"을 사용하십시오.

SELECT * FROM user WHERE country = 'China' limit 1; 

4. where 절에서 색인을 사용해야합니다.

//row "name" should add index. 
select * from user where name LIKE 'Jak%' limit 10; 

5. 테이블을 조인 할 때 인덱스를 사용하십시오.

select company_name FROM users LEFT JOIN companies ON (users.state = companies.state) WHERE users.id = 123; 

6. 마십시오 "* 선택"

//not suggest 
SELECT * FROM user WHERE user_id = 1; 
//suggest 
SELECT username FROM user WHERE user_id = 1; 

7. 절차 (ANALYZE), MYSQL 분석 데이터베이스와 데이터를 당신을 도울 것입니다. 8. 테이블의 행을 알고 싶을 때 COUNT (1).

//not suggest 
SELECT count(*) FROM user; 
//suggest 
SELECT count(1) FROM user; 
+0

팁을 주셔서 감사합니다. 매우 도움이되었습니다 .MySQL 변수는 어떻습니까? 최대 연결 수, 시간 초과 ...때로는 "너무 많은 연결"오류가 발생했습니다. –

+0

여기에 몇 가지 좋은 제안이 있습니다. 숫자 8을 대체 할 수도 있습니다. 필요하지 않을 때'SQL_CALC_FOUND_ROWS'를 피하는 것을 권합니다. 'COUNT (*)'와 'COUNT (1)'의 차이는 신화입니다. 숫자 1의 경우 MySQL 쿼리 캐시는 위험한 짐승이 될 수 있습니다. 질의를 캐시 할 수없는'NOW()'외에도 많은 이유가있다. (우리 가게에서 우리는'query_cache_type = 2'를 가지고 있고 캐시하고자하는 문장에'SQL_CACHE' 힌트를 포함 시켰습니다.) – spencer7593

+1

여기 조언은 대부분 합리적이지만, 쓸모없는 mysql_query 함수를 사용하면이 대답을 상당히 혼란스럽게 만듭니다. 이 함수는 죽었고, PHP 7에서 삭제되었습니다. 가능한 한 항상 사용 된 인터페이스와 상관없이, PDO 나 mysqli 나 ORM과 같은 조언을 해보십시오. – tadman

관련 문제