는 장기적이고 무거운 데이터에서 어떤 PDO SQL 쿼리가 더 빠릅니까? 내가 그것을에서 데이터를 가져 오는 경우 테이블에서
내가 요청 된 데이터 가 존재 여부를 여부를 확인하고자하는 만 기록 이상이있다, 그래서 어떤 경로가 더 효율적 빠르게 입니다 그 다음 다른?id
이
PRIMARY (INT)
및
aid, rid
당신이 거의 측정으로, 거의 확실 동일 보여
INDEXED (INT)
는 장기적이고 무거운 데이터에서 어떤 PDO SQL 쿼리가 더 빠릅니까? 내가 그것을에서 데이터를 가져 오는 경우 테이블에서
내가 요청 된 데이터 가 존재 여부를 여부를 확인하고자하는 만 기록 이상이있다, 그래서 어떤 경로가 더 효율적 빠르게 입니다 그 다음 다른?id
이
PRIMARY (INT)
및
aid, rid
당신이 거의 측정으로, 거의 확실 동일 보여
INDEXED (INT)
두 가지 방법이 있습니다 것을 염두에
$Query = '
SELECT n.id
FROM names n
INNER JOIN ages a ON n.id = a.aid
INNER JOIN regions r ON n.id = r.rid
WHERE id = :id
';
$stmt->prepare($Query);
$stmt->execute(['id' => $id]);
if ($stmt->rowCount() == 1) {
$row = $stmt->fetch();
......................
} else {
exit();
}
또는
는$EXISTS = 'SELECT EXISTS (
SELECT n.fname, n.lname, a.age, r.region
FROM names n
INNER JOIN ages a ON n.id = a.aid
INNER JOIN regions r ON n.id = r.rid
WHERE id = :id
LIMIT 1
)
';
$stmt->prepare($EXISTS);
$stmt->execute(['id' => $id]);
if ($stmt->fetchColumn() == 1) {
$stmt->prepare($Query);
$stmt->execute(['id' => $id]);
$row = $stmt->fetch();
......................
} else {
exit();
}
유지 성능 차이.
SELECT n.id
FROM names n
INNER JOIN ages a ON n.id = a.aid
INNER JOIN regions r ON n.id = r.rid
WHERE id = :id
names.id
이 해당 테이블의 기본 키라고 가정합니다. 기본 키 조회는 매우 빠릅니다.
그러면 다른 두 테이블에 대한 보조 키 조회가 수행되며 해당 테이블의 다른 열에 대한 참조가 없기 때문에 인덱스 전용 액세스가됩니다.
EXPLAIN을 사용하여 MySQL의 최적화 계획을 분석하는 방법을 배워야합니다. 이것은 SQL 쿼리의 성능을 향상시키려는 경우 언제든지 연습해야하는 기술입니다.
는 https://dev.mysql.com/doc/refman/5.7/en/using-explain.html
mysql> explain SELECT n.id
-> FROM names n
-> INNER JOIN ages a ON n.id = a.aid
-> INNER JOIN regions r ON n.id = r.rid
-> WHERE id = 1;
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | n | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | Using index |
| 1 | SIMPLE | a | NULL | ref | aid | aid | 5 | const | 1 | 100.00 | Using index |
| 1 | SIMPLE | r | NULL | ref | rid | rid | 5 | const | 1 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
우리는 각 테이블 액세스 (당신이 당신의 질문에 SHOW CREATE TABLE
를 제공하지 않았지만 내가 인덱스를 있으리라 믿고있어) 인덱스를 사용하고 있음을 참조하십시오.
SELECT EXISTS(...)
mysql> explain SELECT EXISTS (
-> SELECT n.id
-> FROM names n
-> INNER JOIN ages a ON n.id = a.aid
-> INNER JOIN regions r ON n.id = r.rid
-> WHERE id = 1
-> LIMIT 1);
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+----------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+----------------+
| 1 | PRIMARY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| 2 | SUBQUERY | n | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | Using index |
| 2 | SUBQUERY | a | NULL | ref | aid | aid | 5 | const | 1 | 100.00 | Using index |
| 2 | SUBQUERY | r | NULL | ref | rid | rid | 5 | const | 1 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+----------------+
하위 쿼리는 첫 번째 쿼리 최적화 계획에 동일하게 나타남에 두 번째 솔루션과 비교; 같은 방식으로 인덱스를 사용합니다. 그러나 하위 쿼리로 강등되었습니다. 아마도 큰 차이는 아니지만 한 가지 더 있습니다.
유일한 이점은 SELECT EXISTS...
쿼리가 true/false 값이있는 행 하나만 반환하도록 보장된다는 것입니다. 첫 번째 쿼리는 쿼리에서 JOIN과 일치하는 개수에 따라 0, 1 또는 여러 행이 포함 된 결과 집합을 반환 할 수 있습니다. 차이점은 성능 차이가 아닙니다. 결과 집합을 클라이언트로 전송하는 데 많은 시간이 걸리거나 많은 메모리를 사용하여 결과 집합을 클라이언트에 보관하는 경우가 아니라면 당신이 코딩하는 방식.
만약'LIMIT 1'을 삭제했다면,'SELECT EXISTS -> SELECT'를 확인하는 것이 더 빠를까요? – Toleo
마이크로 최적화가 끝나면 두 가지 방법으로 시도해보고 [microtime()] (http://php.net/microtime) –
으로 데이터를 인덱싱해야합니까? 레코드 수를 1 백만 개로 만듭니다 '쓸모 없어? 1 백만 개의 데이터 색인을 생성하면 색인이 생성되지 않은 것처럼 많은 시간이 걸릴 것이라고 생각했기 때문에? 그리고 예상대로 예가 사용되면 모든 행의 색인이 생성됩니다. – Toleo
연령을 표준화하지 마십시오. 그것은 단지 공간과 시간의 낭비 일뿐입니다. age
('년'이라고 가정)은 1 바이트의 TINYINT UNSIGNED
(범위 : 0..255)에 맞을 수 있으며 JOIN
조회를 피할 수 있습니다. aid
은 수십억 개의 서로 다른 값을 저장할 수있는 4 바이트의 INT
인 것 같습니다. 수십억 개의 다른 연령대가 있습니까?
아마도 regions
을 변경하는 것도 가치가 있습니다.
첫 번째 쿼리에서 두 JOINs
은 나이와 지역에 행이 있는지 확인하지만 아무 것도하지 않습니다. 즉, 일 것입니다. 아마도입니다.
EXISTS
은 한 행을 찾으면 중지합니다. 따라서 LIMIT 1
은 매우 불필요합니다.
참고 쿼리 최적화에 대한 도움을 요청하는 모든 질문에는 쿼리의 각 테이블에 대한 'SHOW CREATE TABLE'출력이 포함되어야하므로 데이터 유형, 인덱스 및 제약 조건을 추측 할 필요가 없습니다. 그리고 많은 사람들처럼 스크린 샷처럼 텍스트로 게시하십시오. –