3

MySQL に 2 つのテーブルがあり、table1 には 1,013,347 のエンティティと 38 の属性があり、table2 には 7,343,905 のエンティティと 10 の属性があります。次のクエリ (ページネーションの行数を取得することになっています) では、table1.ID は PK、table2.ID はその FK (両方ともインデックス付き) であり、HAVING 句は特定のパーセンテージを超える場合に値を取得します。 、この場合は 50%

SELECT SQL_CALC_FOUND_ROWS * 
FROM table1 INNER JOIN table2 ON table1.ID = table2.ID 
WHERE table1.attribute1 LIKE 'D%' 
GROUP BY table2.ID 
HAVING (COUNT(table2.ID) * (100/18)) >= '50'

ここに投稿した簡略化された状態でも、このクエリはコマンド ラインから実行するのに 5 分以上かかります。クエリ、PHP コード (値 '50' と 'D' は PHP 変数を介して割り当てられます)、および/または処理を高速化するために MySQL 構成 (私はデフォルト設定の最新の XAMPP)。どんな助けでも大歓迎です。

EDIT1: VARCHAR(9) である ID 属性を除いて、すべての属性は TINYTEXT です。

EDIT2: EXPLAIN SELECT... 戻り値:

+----+-------------+--------+------+---------------+-------------+---------+------+---------+---------------------------------+
| id | select_type | table  | type | possible_keys | key         | key_len | ref  | rows    | Extra                           |
+----+-------------+--------+------+---------------+-------------+---------+------+---------+---------------------------------+
|  1 | SIMPLE      | table2 | ALL  | NULL          | NULL        | NULL    | NULL | 7343905 | Using temporary; Using filesort |
|  1 | SIMPLE      | table1 | ref  | ID            | ID          | 29      | func |       1 | Using where                     |
+----+-------------+--------+------+---------------+-------------+---------+------+---------+---------------------------------+
2 rows in set (0.00 sec)
4

2 に答える 2

3

潜在的な改善点は次のとおりです。

  • タイプ VARCHAR(9) の ID を使用しており、それらのフィールドを使用して結合を実行しています。結合を高速化するために、varchar の代わりに整数の代理キーを導入することをお勧めします。このディスカッションを参照してください。
  • 通常、LIKE 演算子は高価です。使用法を検討してください。マークが提案したように、table1.attribute1 にインデックスを付ける必要があります。
  • LIKE を完全に省略することで、クエリを高速化できる可能性があります。たとえば、'D%' を使用する代わりに、RIGHT()を使用できますが、はるかに高速になるかどうかはわかりません。テーブル内のデータが頻繁に変更されない場合は、table1.attribute1 の値が事前にカットされた新しいインデックス付きの列を作成できます。ただし、php スクリプトによって LIKE の後に挿入される値によって異なります。
于 2012-04-21T23:47:02.923 に答える
1

パフォーマンスを改善するためのいくつかのアイデア

  1. インデックスtable2.ID(必須)およびtable1.IDも
  2. 可能であれば、id列をbigintおよびtable1.attribute1をvarcharにします。列の推定データ長に基づいて、varchar列の適切なサイズを定義するように注意してください
  3. SQL(100/18)内で計算を行うのではなく、次のように置き換えます

    HAVING(COUNT(table2.ID)*(5.5555))> = 50

(table2.IDは現在bigintであるため、数学的比較はわずかに高速である必要があります)

ご覧のとおり、このクエリではlike句が不可欠ですが、likeは高価ですが、table1.attribute1にもインデックスを付けるとよいでしょう。

お役に立てれば

于 2012-04-22T04:17:21.210 に答える