MySQL 데이터베이스 쿼리에는 일정 시간이 걸립니다.
P粉764836448
2023-08-31 22:29:19
<p>행이 24,000개 있는 대규모 메시지 데이터베이스가 있습니다.</p>
<pre class="brush:php;toolbar:false;">행 0-24를 표시합니다(총 2455455행, 쿼리 소요 시간은 0.0006초). </pre>
<p> 메시지가 있으므로 대화를 더 빨리 로드해야 합니다. 대화가 적은 사용자의 경우 로드 방법은 다음과 같습니다(사용자의 대화 수는 3.2k개입니다). </p>
<pre class="brush:php;toolbar:false;">행 0-24를 표시합니다(총 3266행, 쿼리 소요 시간 0.0345초) [id: 5009666... - 4375619...]. </pre>
<p>대화가 많은 사용자의 경우 로드 속도가 느려집니다(사용자의 대화 수가 40,000개임): </p>
<pre class="brush:php;toolbar:false;">행 0-24를 표시합니다(총 40296행, 쿼리 소요 시간 5.1763초) [id: 5021561... - 5015545...]. </pre>
<p>저는 다음 열에 색인 키를 사용합니다. </p>
<pre class="brush:php;toolbar:false;">id, to_id, from_id, 시간, 본</pre>
<p>데이터베이스 테이블: </p>
<pre class="brush:php;toolbar:false;">CREATE TABLE `메시지`(
`id` int(255) NULL이 아닙니다.
`to_id` int(20) NULL이 아님,
`from_id` int(20) NULL이 아님,
`메시지` 긴 텍스트는 NULL이 아닙니다.
`time` double NOT NULL,
`seen` int(2) NOT NULL,
) 엔진=InnoDB 기본 문자 집합=latin1;
INSERT INTO `messages`(`id`, `to_id`, `from_id`, `message`, `time`, `seen`) 값
(2, 6001, 2, '안녕하세요', 1587581995.5222, 1);
ALTER TABLE `메시지`
기본 키 추가(`id`),
키 `time_idx`(`time`)를 추가하세요.
키 `from_idx`(`from_id`)를 추가하세요.
키 `to_idx`(`to_id`)를 추가하세요.
키 추가 `seenx` (`seen`),
키 `idx`(`id`) 추가;
ALTER TABLE `메시지`
수정 `id` int(255) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5021570;
COMMIT;</pre>
<p>저는 다음 검색어를 사용합니다: </p>
<pre class="brush:php;toolbar:false;">SELECT
*
에서
메시지,
(
선택하다
MAX(id) as lastid
에서
메시지
어디
(
message.to_id = '1' -- 비교할 ID(로그인한 사용자의 ID)
OR message.from_id = '1' -- 비교할 ID(로그인한 사용자의 ID)
)
그룹 기준
연결(
LEAST(messages.to_id, message.from_id),
'.',
최고(messages.to_id, message.from_id)
)
) 대화로
어디
ID = 대화.lastid
주문
message.id DESC</pre>
<p>데이터베이스 구조를 다시 만들어야 하는 경우 대화가 많은 사용자를 위해 어떻게 더 빠르게 만들 수 있는지 모르겠습니다. </p>
흠, 어쩌면 테이블에 인덱스를 추가해 볼 수도 있습니다: https://www.drupal.org/docs/7/guidelines-for-sql/the-benefits-of-indexing-large-mysql-tables#: ~ :text=%20색인 생성&text=%20문%20to%20create%20색인,%20색인%20은%20고유한 %20이어야 합니다. 쿼리하는 행을 기반으로 복합 인덱스를 추가해야 합니다.
이렇게 해도 쿼리 시간이 개선되지 않으면 쿼리를 개선해야 합니다.
참고:
CONCAT-LEAST-GREATEST - "friends_id"를 생성하기 위한 것인가요? 어쩌면 당신이 정말로 원하는 것은 "conversation_id"일까요? 현재는 두 명의 사용자가 여러 개의 "대화"를 할 수 없습니다. 그렇죠?
정말 필요한 경우 대화 ID에 대한 새 열을 만드세요. (현재 GROUP BY는 비효율적입니다.) 다음 코드에서는 이러한 ID가 필요하지 않습니다.
으아악그리고 다음과 같은 "포함" 및 "복합" 색인을 갖습니다.
으아악새 색인이 이 두 색인의 다른 모든 작업을 처리할 수 있으므로 KEY(to_id), KEY(from_id)를 제거했습니다.
동일한 효과가 있지만 실행 속도가 더 빠른 것 같아요.
결합:
으아악(이 두 인덱스를 추가하세요)
더보기
저는 한때 UNION DISTINCT가 대화 ID의 필요성을 대체할 수 있다고 잘못 생각한 적이 있습니다. 그러나 그것은 진실이 아니다. 나는 즉시 몇 가지 해결책을 보았습니다: