2016-06-01 17 views
1

スクリプトの実行時間に問題があります。クエリには多くの時間がかかります。これはクエリです。クエリ実行時間の問題

select avg(price) from voiture where duration<30 AND make="Audi" AND model="A4" 

+---+---+---+---+---+---+---+---+---+---+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
+---+---+---+---+---+---+---+---+---+---+ 
| 1 | SIMPLE | voiture | ALL | NULL | NULL | NULL | NULL | 1376949 | Using where | 
+---+---+---+---+---+---+---+---+---+---+ 

select price from voiture where duration<30 AND make="Audi" AND model="A4" 
+---+---+---+---+---+---+---+---+---+---+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
+---+---+---+---+---+---+---+---+---+---+ 
| 1 | SIMPLE | voiture | ALL | NULL | NULL | NULL | NULL | 1376949 | Using where | 
+---+---+---+---+---+---+---+---+---+---+ 

このクエリは、phpMyAdminインターフェイスで実行するのに約2秒かかります。問題の内容を確認しようとしましたが、avg関数を削除するとクエリの持続時間は0.0080秒になります。
私はphpスクリプトでavgを計算するのにどれくらい時間がかかりますかと尋ねましたが、avgを使用するかorouthwith avgを使用するには2秒かかります。
は、だから私は、私のテーブルのすべての値を取り、スクリプト内でプロセスを作ることにしたので、私はこのクエリを使用します。phpMyAdminのインターフェイス上で

select * from voiture where duration<30 AND make="Audi" AND model="A4" 

+---+---+---+---+---+---+---+---+---+---+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
+---+---+---+---+---+---+---+---+---+---+ 
| 1 | SIMPLE | voiture | ALL | NULL | NULL | NULL | NULL | 1376949 | Using where | 
+---+---+---+---+---+---+---+---+---+---+ 

、それは0.0112秒かかります。しかし、私のPHPスクリプトでは、25秒かかる!ここで

$timestart2=microtime(true); 
$querysec='select * from voiture where duration<30 AND make="Audi" AND model="A4"'; 
$requestsec=mysql_query($querysec) or die(mysql_error()); 
$timeend2=microtime(true); 
$time2=$timeend2-$timestart2; 
$page_load_time2 = number_format($time2, 9); 

は、テーブル構造である:私のクエリが実行されるので、時間がかかるのはなぜ

CREATE TABLE `voiture` (
    `carid` bigint(9) NOT NULL, 
    `serviceid` bigint(9) NOT NULL, 
    `service` varchar(256) NOT NULL, 
    `model` varchar(256) DEFAULT NULL, 
    `gearingType` varchar(256) DEFAULT NULL, 
    `displacement` int(5) DEFAULT NULL, 
    `cylinders` int(2) DEFAULT NULL, 
    `fuel` varchar(32) DEFAULT NULL, 
    `mileage` int(7) DEFAULT NULL, 
    `existFlag` tinyint(1) DEFAULT NULL, 
    `lastUpdate` date DEFAULT NULL, 
    `version` varchar(256) DEFAULT NULL, 
    `bodyType` varchar(256) DEFAULT NULL, 
    `firstRegistration` date DEFAULT NULL, 
    `powerHp` int(4) DEFAULT NULL, 
    `powerKw` int(4) DEFAULT NULL, 
    `vat` varchar(256) DEFAULT NULL, 
    `price` decimal(12,2) DEFAULT NULL, 
    `duration` int(3) DEFAULT NULL, 
    `pageUrl` varchar(256) DEFAULT NULL, 
    `carImg` varchar(256) DEFAULT NULL, 
    `color` varchar(256) DEFAULT NULL, 
    `doors` int(1) DEFAULT NULL, 
    `seats` int(1) DEFAULT NULL, 
    `prevOwner` int(1) DEFAULT NULL, 
    `co2` varchar(256) DEFAULT NULL, 
    `consumption` varchar(256) DEFAULT NULL, 
    `gears` int(1) DEFAULT NULL, 
    `equipment` varchar(1024) NOT NULL, 
    `make` varchar(256) NOT NULL, 
    `country` varchar(3) NOT NULL 
) 

caridとをServiceID
上のインデックスがありますか?改善できる方法はありますか?
実行時間がphpMyAdminと私のPHPスクリプトと異なるのはなぜですか?

+1

さらに詳しい情報をお知らせください。あなたのテーブル構造は何ですか、あなたは何をインデックスしていますか?クエリ上で 'EXPLAIN'を実行しようとすると、いくつかのことがクリアされます。それが出力されていることを理解できない場合は、質問に追加すると、問題の診断に役立ちます。 –

+0

'' * from voiture where duration <30 AND make = "Audi" AND model = "A4" 'は、合計でいくつの行が返されますか? – beingalex

+0

[mysql_'データベース拡張](http://stackoverflow.com/questions/12859942/why-shouldnt-i-use-mysql-functions-in-php)を使用しないでください。 は廃止予定ですPHP7で)特にPHPを学んでいるならば、あなたのエネルギーを 'PDO'データベース拡張を学ぶのに費やしてください。 [こちらから](http://php.net/manual/en/book.pdo.php)本当にかわいいです – RiggsFolly

答えて

1

のインデックスを追加することができ、それは0.0112秒かかります。しかし、私のPHP スクリプトでは、25秒かかる!

phpMyAdminインターフェイスは、各クエリにLIMITを追加します。デフォルトではLIMIT 30です。

集計クエリの時間を短縮するには、使用する各条件(または1つの複合インデックス)にインデックスを作成する必要があります。

したがって、model,makeおよびdurationフィールドのインデックスを作成してみてください。


また、テーブルが非正規化されています。あなたは少しのためにそれを正規化するテーブルのペアを作成することができます。
例:Vendors(id, name),Models(id, name)voitureには、make/modelの代わりにvendor_id/model_idのフィールドを使用してください。これは、テキスト一致する光のルックアップテーブルをスキャンし、インデックス付きのIDを使って重いテーブルで動作します

select avg(t.price) from voiture t 
INNER JOIN Models m ON m.id = t.model_id 
INNER JOIN Vendors v ON v.id = t.vendor_id 
where t.duration<30 AND v.name="Audi" AND m.name="A4" 

次に、あなたの最初のクエリは次のようになります。

+0

良い答え、私は3つのインデックスを1つの複合インデックスに追加しました。実行時間は25秒から1.5秒になりました!私はすでに "make"と "model"テーブルを持っていますが、行のIDはmake/modelの名前です。そのためmake = "Audi"を使用しています。 – Nevi

+0

また、私は通常makeとモデル(実際にはテーブルのほとんどすべてのフィールド)よりもずっと多くのパラメータを使用していますが、すべてのフィールドを複合インデックスに入れるのは良いことですか? – Nevi

+0

それに依存します。それはあまりにも太いインデックスとそれの内部の検索は、生のテーブルのフルスキャンに対して利益がありません。テキストの主キー(あなたは 'varchar(256)'を使う)も悪い考えです。 –

0

多くの可能な解決策がありますが、まずDBレベルでis create indexを実行すると、実行時間が改善されます。

このチェックサーバーには、サーバーリソースを占有し、サーバーの速度を低下させるプロセスが存在することがあります。

0

あなたはそれがより速く

select AVG(price) from voiture where duration<30 AND make="Audi" AND model="A4" GROUP BY make 

のようにGROUP BYを使用して行うことができます。またあなたが作る列phpMyAdminのインターフェイス上で

ALTER TABLE `voiture` ADD INDEX `make` (`make`) 
+0

私はそれについて考えましたが、私のPHPスクリプトでは、価格を選択し、avg(価格)を選択すると同じ時間がかかります – Nevi

+0

私は 'make'フィールドにインデックスを追加してみてください。答えが変わった。これが機能するかどうか確認してください。 @Nevi –