2013-01-12 2 views
0

나는 웹 사이트를 만들고있다. geekwiz.com. 그것을로드 테스트, 오랫동안.PHP PDO 거대한 데이터베이스 쿼리 속도 최적화

저는 php에 익숙하지 않고 mysql_query에서 PDO로 변경되었습니다. 첫 번째 페이지에 제품을 표시하기 위해 여러 개의 쿼리를 수행해야하며 테이블에는 150 만 개가 넘는 레코드가 있습니다.

어떻게하면 더 빨리 만들 수 있습니까? 여기

내가 만든 코드 :

#connection 
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); 
$DBH->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); 

별도의 파일

#fetch data 
require_once('db_config.php'); 
$STH = $DBH->query(" 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('notebook pc - other') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Desktop PC') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Hard Drives - External') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Camcorders - Analog/Digital') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Monitors - LCD Flat Panel') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Software - PC Games') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('third party accessories') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE advertisercategory LIKE ('LED TV') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Motherboards - %') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE advertisercategory LIKE ('LED TV') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Hard Drives - External') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('CPU Cooling') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('CPU Thermal Paste/Grease') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Keyboards') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Memory (USB Flash Drive)') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Memory (Desktop Memory)') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Memory (Notebook Memory)') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Mouse') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Printer - Inkjet Printers') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Projectors') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9; 
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Processors - Desktops') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9; 

"); 

$STH->setFetchMode(PDO::FETCH_OBJ); 

while ($row = $STH->fetch()) { 
echo "<ul>"; 
echo "<li>" .$row->name ."</li>"; 
echo "<li>" .$row->buyurl ."</li>"; 
echo "<li>" .$row->imageurl ."</li>"; 
echo "<li>" .$row->price ."</li>"; 
echo "<li>" .$row->manufacturer ."</li>"; 
echo "<li>" .$row->manufacturerid ."</li>"; 
echo "</ul>"; 
} 

답변

0

음, 스타터, PDO는 거대한 데이터베이스 속도 최적화와는 전혀 무관하다.
"브루클린, 뉴욕에서 탬파로 갈 수 있도록 내 포드 에스코트를 운전하는 방법"과 비슷한 질문을하고 있다고 생각해보십시오. 자동차 제조는 여기에 무관합니다. DB 드라이버도 마찬가지입니다.

이제 데이터베이스에 저장하십시오.
많은 작업을 수행하려면이 필요합니다.

먼저 Mysql FULLTEXT를 사용하여 카테고리를 만드는 것은 절대적으로 불가능합니다. 범주 구조가있는 테이블에 링크 된 숫자 인덱스 여야합니다.

그래서 쿼리는이 일

SELECT * FROM catalog WHERE category=1 AND special = 'YES' AND instock = 'YES' 
AND standardshippingcost=0 ORDER BY lastupdated DESC limit 3; 

처럼되고 그리고 제대로 색인 경우, 그것은 꽤 빨리 할 수 ​​있습니다. 예를 들어 특별 제안의 수가 제한적이라면 데이터베이스의 레코드 수에 관계없이이 필드의 색인을 사용하면 빨리 처리 할 수 ​​있습니다.

그러나 전체 데이터베이스 아키텍처는 다를 수 있습니다. 뿐만 아니라 최적화를위한 다른 방법이있을 수 있습니다. 그러나 우리는 귀하의 프로젝트가 확실하지 못하다는 것을 알지 못합니다. 솔직히 간단히 Q & 형식이 아닙니다.

+0

멋진 thks 그래서 기본적으로 좋은 DB를 리메이크합니다 : D – Outcast

0

해당 그룹 SQL 쿼리를 수행하는 saveCacheData.php이라는 PHP 스크립트를 작성하십시오.이 스크립트는 데이터를 cacheData.php과 같은 파일로 덤프합니다.

기본 페이지에서 require_once('cacheData.php')으로 SQL 쿼리를 대체하십시오.

이제 mysql 테이블 catalog의 데이터가 업데이트되면 file_get_contents('saveCacheData.php')도 수행해야합니다 (또는 데이터를 캐시하는 일종의 cron 작업을 수행해야합니다).

나는 당신의 DB 디자인이 훨씬 더 좋을 것이라고 생각하지만 DB 데이터를 디스크에 캐싱하는 것이 좋은 생각이기도합니다.

+0

예 저는 주로 프론트 엔드 개발자입니다. 백엔드에 들어가기 시작합니다. 방금 ​​DB에있는 필드를 만들고 구문 분석 한 결과 xml 파일이 너무 많습니다. 여러 테이블을 만들고 데이터 색인을 생성해야 도움이됩니다. – Outcast

+0

어떻게 할 수 있습니까? th – Outcast

2

몇 가지 문제가 있으며, 내가 말한 것을 좋아하지 않을 것입니다.

text/varchar로 정렬하는 것은 속도가 느리며 업데이트하는 데 오래 걸립니다. 그 대신에 텍스트를 모두 정수로 변환해야합니다. 따라서 advertisercategory에는 실제 텍스트가 없어야합니다. 대신 실제 텍스트가 저장된 테이블에 링크되는 고정 길이 INT이어야합니다. specialinstock도 마찬가지입니다.standardshippingcost은 작은 따옴표로되어 있기 때문에 varchar처럼 보이며, 보이는 것처럼 보이면 사실이 아니어야합니다. 숫자 일 경우 숫자 여야합니다. 스키마가 확실하지 않으므로 standardshippingcost은 FK의 catalog에 연결된 자체 테이블에 있어야 할 수도 있습니다. lastupdated은 유닉스 시간에 INT이어야합니다.

데이터가 빠르게 1)이 notebook pc - other보다 적은 공간 (따라서 적은 메모리 정렬) 소요 2) 업데이트가되기 때문에 INT가해야하는 이유 (I)는 이노를 사용하고 있으리라 믿고있어.

그래서, 정렬 할 때, PHP는 배열로, advertisercategory, instock, standardshippingcost, standardshippingcostlastupdated (자동 증가 PRIMARY을해야합니다) 당신의 id의의 SELECT 모든. 원하는 것을 얻을 수있는 가장 효율적인 방법을 찾으십시오 (갈 때 바로 가기가 나타납니다). 마지막으로 SELECT 특정 데이터를 PRIMARY 키로 입력하십시오.

나는 설명하기 위해 뒤로 갈 것이다. 이 방법론이 최고의 성능을 발휘할 수있는 이유는 다른 인덱스없이 InnoDB 테이블의 PRIMARY에서 SELECT을 제거하면 테이블이 얼마나 큰지 상관 없으므로 "즉시"반환됩니다. 엄청나게 복잡한 쿼리를 사용하는 것은 경험 한 것처럼 느립니다. 이것이 실제로 데이터를 검색하는 방법입니다.

PHP는 논리가있는 MySQL보다 빠릅니다. 그것은 그것이 무엇을위한 것입니다. 스택에 많은 Q가 있습니다. 그래서 PHP를 정렬하고 싶습니다. 또한 데이터에 통계 또는 다른 종류의 패턴이 표시되는 경우 더 나은 알 고리를 작성하여 정렬 작업을 더 빠르게 수행 할 수 있습니다.

유닉스 데이터 외에도 다른 열은 너무 길어서는 안됩니다. advertisercategory은 조금 커질 수는 있지만 notebook pc - other인데 이미 길이가 19 인 것과 비교할 수 없습니다. 귀하의 질문에 약 advertisercategory가 표시되므로 INTLENGTH2으로 표시 될 수 있습니다. 잠재적 가치는 100 개이기 때문입니다. 이렇게하면 정렬 할 때 공간과 메모리가 절약됩니다.

또한 클러스터 된 테이블이 항상 단단하고 조각 모음을 유지하기 때문에 업데이트 할 때 고정 길이 int를 사용하면 더 빠릅니다. UPDATE 클러스터 된 InnoDB의 중간에있는 행이 'Memory (USB Flash Drive)'에서 'Projectors' 인 경우 방금 데이터베이스가 전체 데이터베이스 조각 모음을 수행하여 방금 만든 간격을 제거하게됩니다. 고정 길이 int 열에서 1에서 10으로 변경하는 경우 두 가지 모두 동일한 간격을 차지하므로 간격을 만들지 않으므로 클러스터의 조각 모음이 필요하지 않습니다.

이렇게하면 성능이 크게 향상되지만, 더 많은 코드가 포함될 것입니다. 그래서 우선 순위, 성능 또는 개발 시간은 무엇입니까?


Whoop! 유닉스 시간 설명을 잊어 버렸습니다. 초 단위로 INT에 저장하고 마이크로 초 동안 DECIMAL 단위로 저장할 수 있기 때문에이 값을 사용하려고합니다. 이 방법을 사용하면 PHP가 유닉스에 있기 때문에 PHP에서 가장 쉬운 조작이 가능합니다.