2017-03-15 1 views
0

나는 1 억권이 넘는 거대한 테이블을 가지고 있습니다. 해당 테이블의 형식은 다음과 같이이다 :내 테이블의 색인 생성

id (AUTO_INCREMENT) - main key | username VARCHAR(100) | email VARCHAR(100) | ip VARCHAR(30) | hash VARCHAR(150) | salt VARCHAR(100) 

나는 색인 아주 새로운 오전과 내가이 쿼리를 실행했을 때 나는 잠재력을 실현 :

"SELECT * FROM users WHERE id = 1000000;" 

쿼리는 경우 반면 번개 속도로 데이터를 공급을

"SELECT * FROM users WHERE email = '[email protected]';" 

그것은 결과를 가져 분 이상 걸릴 것이라고, 나는 테이블이 인덱싱되지 않기 때문에이 알고 : 나는 예를 들어 다른 쿼리를 실행합니다. 다음과 같이 나는 테이블에 대해 실행해야 할

쿼리는 다음과 같습니다

"SELECT * FROM users WHERE INSTR('email', '[email protected]');" 

"SELECT * FROM users WHERE INSTR('username', 'testuser');" 

내가 제공 할 수있는 일부 thurther 정보를 사용자 이름과 이메일 열이 고유하지 않은 것입니다 . 그리고 컬럼을 만들 때 "DEFAULT NULL"또는 "NOT NULL"일 수 있는지 명시하지 않았습니다.

이 테이블을 인덱싱하는 가장 좋은 방법은 위 쿼리를 실행할 수 있는지 궁금합니다. Iv'e는 연구를 시도했지만 조금 혼란 스럽습니다.

오, 또 하나주의 할 점은, 내가 사용하는 데이터베이스는 mariadb이고 백엔드는 innodb입니다.

답변

0

우리는 심지어 색인에 도착하기 전에 향상시킬 수있는 몇 가지가 있습니다) :

  • 열 정의 : 이
    • 아이디, 이름과 이메일 보인다는 괜찮아요.
    • ip : 이것을 int unsigned으로 저장 한 다음 MySQL INET_ATON과 0을 사용합니다.은 값을 저장/검색하는 함수입니다. IPv6 주소 또는 IPv4 및 IPv6를 혼합하여 저장하려는 경우 상황이 다소 복잡해 지지만 전체적으로 동일하게 작동합니다 (Google은이 문제에 대한 귀하의 친구입니다).
    • 해시 : 최대 150 자까지 가변 길이가 될 수있는 해시를 들어 본 적이 없습니다. characters;) 해시 길이를 확인한 다음 BINARY 필드를이 길이로 사용하십시오 (또는 CHAR을 2 진수가 아닌 16 진수로 저장하려는 경우 길이를 두 배로 사용하십시오). BINARY(20) 또는 CHAR(40)에 대한 SHA-1
    • 소금 : 최대 길이는 소금에 대해 나에게 조금 위에 보인다. 그러나 무엇이라도 당신의 보트를 뜨게한다.
  • 쿼리 : INSTR을 사용 하시겠습니까? 이 방법은 검색어가 텍스트의 어느 위치 에나있는 모든 행을 반환하기 때문에 묻습니다. ThisIsMySuperFancytestuser!!!. 특히 이것은 사용자가 원하는 것일 수는 없습니다.) 또한 인덱스를 사용할 수 없게됩니다. 도메인을 열어두기를 원할 경우 사용자에게는 SELECT * FROM users WHERE username = 'testuser';을, 이메일에는 SELECT * FROM users WHERE email LIKE '[email protected]%';을 입력하면됩니다. (사용하려는 B- 트리 색인은 LIKE의 와일드 카드와 함께 사용할 수 있으므로 시작 부분에 있지 않으므로 SELECT * FROM users WHERE email LIKE '%[email protected]%';은 색인을 사용할 수 없습니다 [이 검색어는 기본적으로 귀하의 검색어와 동일합니다. 인덱스를 사용하는 경우 INSTR 예를 들어, https://dev.mysql.com/doc/refman/5.7/en/index-btree-hash.html를 참조하십시오.

을 이제 인덱스. 당신은 단순히이 CREATE INDEX inx_username ON table (username); 같은 인덱스를 추가 할 수 있습니다. 미묘하고 개는의 톤이있다, 그래서 나는 긴 책 통로를 걸어 추천 (또는 Google;) 최소한 MySQL 참조 : https://dev.mysql.com/doc/refman/5.7/en/create-index.html을보십시오. 일부 메모리를 저장하기 위해 열의 첫 번째 n 문자를 인덱싱하는 것과 같은 것을 배웁니다.)

행운을 빕니다

+0

정보를 제공해 주셔서 감사합니다.저는 150 자 정도의 해시를 가지고 있습니다 : P,하지만 ip와 salt는 고려할 것입니다. 또한 %% 쿼리가 INSTR보다 더 이상한 결과를 가져 오지 못하기 때문에 INSTR을 사용하기 시작했습니다. 나는 어떤 점에서 그것에 대해 좀 더 살펴야 할 것이다. 사용자 이름과 전자 메일에 대한 색인을 추가 할 수 있었고 INSTR이 영향을받지 않았으며 색인을 사용해야 할 때 어떤 결과도 가져 오지 않았다고 생각했습니다. 그래서 나는 쿼리가 왜 결과를 덜 가져 오는 지 알아 내야 할 것 같아요. 당신이 그 방향으로 나를 지적 할 수 있다면, 나는 그것을 감사 할 것입니다. – niftysql

0

먼저 SELECT *을 사용하는 대신 쿼리에서 실제로 필요한 데이터 열에 SELECT field1, field2, field3 ...을 사용하는 것이 좋습니다.

많은 양의 데이터를 다룰 때 많은 수의 연결 테이블을 만드는 것이 일반적입니다. 하나의 데이터를 다른 데이터에 연결하는 유일한 목적의 테이블입니다. 이메일 예제에서 ID와 이메일을 연결하는 테이블을 가질 수 있으며 그런 다음 해당 ID에 대한 쿼리를 실행합니다.

다른 솔루션은 동일한 스키마를 가진 여러 테이블을 가지며 서로 나란히 비동기 적으로 쿼리를 실행하는 것입니다. 1 대신 테이블 10 개가 있으면 1 분이 아닌 6 초가 걸릴 것입니다.

+0

문제는 내 응용 프로그램입니다. ID를 쿼리 할 수 ​​없습니다. 사용자 이름이나 이메일을 쿼리해야합니다. – niftysql

0

전적으로 인덱스 작성과 열이 null 값을 가질 수 있다는 사실과 고유하거나 다를 수 있다는 사실과는 아무런 관련이 없습니다.

인덱싱은 쿼리하는 데 큰 이점이 있습니다. 각 쿼리 매개 변수에 인덱스를 만들어야합니다. 예를 들어, 쿼리에 따라 당신은 발견 :

CREATE INDEX index_name 
ON table_name (email); 

CREATE INDEX index_name2 
ON table_name (id, email); 

PS : 기본 키에도 외국 사람에 어느 인덱스를 만들 필요합니다. 자세한 정보가 필요하면 read this해야합니다.

+0

안녕하세요, 답장을 보내 주셔서 감사합니다. UNIQUE 인덱스는 컬럼의 각 행에서 고유 한 데이터 여야한다고 가정합니다. 따라서 이러한 인덱스를 사용하면 기존 테이블에 얼마나 오래 걸릴까요? 나는 그것이 창조하고 삽입하는 것이 빠르다고 들었다. 또한 인덱스 이름을 포함하도록 쿼리를 편집해야합니까? – niftysql

+0

테이블이 보유 할 수있는 데이터와 관계없이 언제든지 인덱스를 생성 할 수 있습니다. 먼저 추천 한 2 개의 색인을 작성하고 해당 매개 변수 (전자 메일 또는 ID 및 전자 메일 둘 다)를 기반으로 선택한 쿼리를 실행하면 차이점을 알 수 있습니다. 그 후 필요한만큼 인덱스를 생성하십시오 –

0

시도

CREATE INDEX tableName_indexName 
ON tableName (email); 

CREATE INDEX tableName_indexName 
ON tableName (username); 
+0

고마워요. 얼마나 오래 걸릴지 생각해보십시오. – niftysql

+0

100m 레코드 테이블에서 각자 약 45 분이 걸릴 수도 있습니다. – justMe

+0

훌륭하게, 나는 다시보고하려고합니다. 내 localhost my.cnf는 2GB 램으로 설정됩니다. 차이가 있는지 확실하지 않음 – niftysql