2016-05-26 11 views
-1

PHPコードを実行しているときはいつでも、MySQLに17,257行(サイズ:6.6 MiB)あります。遅すぎるため、Webページを開くのに30分以上かかります。 。私はmysqli_fetch_arrayをfetch_assocに変更するためにどこかを読んだが、それでも私は変更を見ることができない。助言がありますか? 最初は複雑なコードを持っていましたので、私はそれを以下のものに変更しましたが、まだ変更を見ることはできません。私は、クエリを通じて達成するためにwan't何mysqlに17,257行しかありませんが、非常に遅いPHPコード

$md=$db->query("SELECT MDid,MD_FullName FROM MDList"); 

     while($row=$md->fetch_assoc()) 
     { 
      $mdid=$row['MDid']; 
      $mdname=$row['MD_FullName']; 

      $distinct_filenames=$db->query("SELECT DISTINCT(FileName) AS Files FROM InitialLog WHERE MDid='$mdid' AND FileName NOT LIKE '%Patient Names%'"); 

      while($row2=$distinct_filenames->fetch_assoc()) 

      { 
       $filename=$row2['Files']; 

       $finalquery=$db->query("SELECT LinesCount,CharCount,WordCount,PageCount FROM InitialLog WHERE FileName='$filename' AND (DateLastSaved>='$firstdate' AND DateLastSaved<='$presentdate') AND MONTH(DateLastSaved) = (SELECT MIN(MONTH(DateLastSaved)) FROM InitialLog WHERE FileName='$filename') ORDER BY DAY(DateLastSaved) DESC LIMIT 1"); 


       while($row3=$finalquery->fetch_assoc()) 
       { 
        $linecount=$linecount+$row3['LinesCount']; 
        $charcount=$charcount+$row3['CharCount']; 
        $wordcount=$wordcount+$row3['WordCount']; 
        $pagecount=$pagecount+$row3['PageCount']; 
       } 

      } 

は次のとおりです。

テーブル:

  1. MDList(すべてのMDのMDのidから構成)

  2. InitialLog(構成されて各MDidのFileNamesとカウント数)

私の最初のクエリは、各MDidをテーブルMDlistから1つずつ選択します。

2番目のクエリは、最初のクエリから選ばれたその特定のMD用InitialLogsテーブルは異なるファイル名をとり

サードクエリは、特定のMDの各個別のファイル名の様々なカウントを返します(ファイル名は同じであってもよいです)。ファイルが存在する場合、その名前のファイルが1つ存在すれば正常に返されますので、01に存在する場合と同様に、最初の月と最後の1日に存在するファイル名の数を返します-01-2016,22-01-2016,23-02-2016となるため、最初の月の最終日である行(22-01-2016)にあるカウントが返されます。

最後に、各MDの返されたすべてのカウントを合計します。

+0

データベースのテーブルのインデックスをチェック –

+6

使用することを学ぶ、データベース内の結合 –

+0

はちょうどあなたがデータベースに送信クエリの合計数をカウント照会します。多くの高速クエリ(実際に高速であることが前提)では、実行に多くの時間が必要です。 –

答えて

1

あなたは膨大なSQLクエリを作成しています。

まあ、<Number of MD Results> * <Number of distinct filenames>のSQLクエリです。

統計をいくつか追加しているだけなので、最初に正しい値を集計した単一のクエリを作成する方が効率的です。

SUM()とJOINをご覧ください。

0

前述のように、ループ内でクエリを実行するのは、コストを(ほとんど)必要としません。 SGBDエンジンは、データ集約、結合、除外などを処理するように設計されています。

このようにするとよいでしょうが、なぜそれが良い考えでないのかについては、以下の注意をお読みください。これは、クエリロジックからの直接的な書き換えであり、より良いパフォーマンスと安全性のために書き直される可能性があります。それはフルスキャンを実行するために必要と

SELECT 
    sum(log.LinesCount), sum(log.CharCount), 
    sum(log.WordCount), sum(log.PageCount) 
FROM InitialLog log 
INNER JOIN (
    SELECT l2.FileName, l2.MD_id 
    FROM InitialLog l2 
    WHERE l2.FileName NOT LIKE '%Patient Names%' 
) filtered_name 
ON filtered_name.FileName=log.FileName 
INNER JOIN MDList md 
ON filtered_name.MD_id = md.MDid 
INNER JOIN (
    SELECT MIN(MONTH(l3.DateLastSaved)) as minmonth 
    FROM InitialLog l3 
    WHERE l3.FileName='$filename' 
) lastSaved  
ON lastSaved.minmonth = log.DateLastSaved 
WHERE 
    log.DateLastSaved>='$firstdate' 
    AND log.DateLastSaved<='$presentdate' 
ORDER BY 
    DAY(log.DateLastSaved) DESC 
LIMIT 1; 

まず、NOT LIKE '%whatever%'は、通常は悪い考えです。 JOINとヌルテストではるかに効率的です。また、このスキャンを完全に避けるためにビューなどの方法を使用することもできます(列を追加するなど)。少なくとも、パターンの開始時にはワイルドカード(%)を避けるようにしてください。

次に、クエリにパラメータを挿入するために文字列連結を使用していますが、それは悪いことです。 SQLインジェクションを避けるために、実際のパラメータで準備されたクエリを使用する必要があります。

最後に、あなたは矛盾comparaisonsを避けるために(何でも、またはトリガーによって更新された列を追加し、ビューを設定)あなたの日付を変更することを検討してください。

+0

ありがとうございます、残念ながらあなたのお問い合わせは私にnullの結果を返します –

+0

@MariumMalikあなたの質問をサンプルデータと予想される動作で更新してください。ご想像のとおり、リバースエンジニアリングを3つのネストされたクエリは、彼らが行うことになっているのか知らない簡単な仕事ではありません:)私が編集した – Preuk

+0

。理解しやすいと思う –

関連する問題