0

ウェブサイト geekwiz.com を構築しています。読み込みをテストしてください。

私は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>";
}
4

3 に答える 3

2

いくつかの問題があり、おそらく私の言うことが気に入らないでしょう。

text/varchar によるソートは非常に遅く、更新には永遠に時間がかかります。代わりにすべきことは、そのテキストをすべて整数に変換することです。そのadvertisercategoryため、実際のテキストを含めることはできません。INT代わりに、実際のテキストが格納されているテーブルにリンクする固定長にする必要があります。specialと についても同様instockです。 standardshippingcost一重引用符で囲まれているため、varchar のように見えますが、見た目どおりであれば、実際にはそうではありません。数値の場合は数値にする必要があります。あなたのスキーマがよくわからないので、FK によって standardshippingcostリンクされた独自のテーブルにある必要があるかもしれません。UNIX時間である必要があります。cataloglastupdatedINT

データが必要な理由INTは、1) 必要なスペースが少ないため (したがって、並べ替え時のメモリが少ない) notebook pc - other、2) 更新が高速になるためです (InnoDB を使用していると仮定しています)。

したがって、ソートすると、SELECTすべてのids (自動インクリメントである必要がありますPRIMARY)、advertisercategoryinstockstandardshippingcoststandardshippingcostおよびlastupdatedが PHP 配列になります。欲しいものを手に入れるための最も効率的な方法を見つけてください (進むにつれてショートカットが見つかります)。最後に、キーごとSELECTの特定のデータ。PRIMARY

遡って説明します。この方法論が最高のパフォーマンスをもたらす理由は、他のインデックスなしで InnoDB テーブルをSELECTオフにするPRIMARYと、テーブルの大きさに関係なく、「すぐに」返されるためです。あなたが経験したように、巨大で難解なクエリを使用すると時間がかかります。これは、実際にデータを取得する方法です。

PHP は MySQL よりもロジックが高速です。それが目的です。これを示すスタックには多くの Q があります。そのため、PHP でソートする必要があります。さらに、データに何らかの統計的またはその他の種類のパターンが見られる場合は、より優れたアルゴリズムを記述して、並べ替えをさらに高速化できます。

UNIX の日付は別として、他の列は長すぎないようにしてください。 advertisercategoryは少し大きくなる可能性がありますが、notebook pc - otherすでに19. advertisercategoryあなたの Qには約 30秒ありますが、それはINT LENGTH 2100 の潜在的な値であるためです。これにより、並べ替え時にスペースとメモリが節約されます。

また、固定長の int を使用すると、更新時に高速になります。これは、クラスター化されたテーブルが常にタイトで最適化されているためです。UPDATEクラスタ化された InnoDB の途中で から まで行を'Memory (USB Flash Drive)'作成した場合は'Projectors'、作成したばかりのギャップを取り除くために、データベースがデータベース全体を最適化するようにしました。11から10固定長の int 列に変更した場合、どちらも同じ量のスペースを使用し、ギャップを作成せず、クラスターのデフラグを必要としないため、そのようなことはしませんでした。

この方法で行うと、大幅なパフォーマンスの向上に驚かれることでしょうが、そうです、これにはより多くのコードが必要になります。では、優先順位、パフォーマンス、または開発時間は何ですか?


おっと!UNIX時間の説明を忘れました。INT秒単位とDECIMALマイクロ秒単位で保存できるため、これを使用します。このようにすると、PHP は UNIX にあるため、PHP での操作が最も簡単になります。

于 2013-02-10T02:15:51.107 に答える
1

そのグループ SQL クエリを実行する という名前の php スクリプトを作成します。このスクリプトsaveCacheData.phpは、データをcacheData.php.

メイン ページで、SQL クエリを に置き換えますrequire_once('cacheData.php')

ここで、mysql テーブルのデータcatalogが更新されるたびに、必ず実行file_get_contents('saveCacheData.php')(またはデータをキャッシュするある種の cron ジョブを実行) してください。

ところで、DB の設計はもっと良くなると思いますが、多くの場合、DB データをディスクにキャッシュすることも良い考えです。

于 2013-01-12T09:16:11.073 に答える
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&A 形式の問題ではありません。

于 2013-01-12T07:22:27.947 に答える