質問

私はローンのみで商品を販売するeショップに取り組んでいます。どのカテゴリでもページごとに 10 個の製品を表示します。各製品には 3 つの異なる価格タグ、つまり 3 つの異なるローン タイプが付いています。テスト中はすべてが非常にうまくいき、クエリの実行時間も完璧でしたが、今日変更を運用サーバーに転送すると、サイトは約 2 分で「崩壊」しました。ローンの種類を選択するために使用されるクエリは時々最大 10 秒間ハングし、頻繁に発生するため、追いつくことができません。 遅いですね. 。データの保存に使用されるテーブルには約 200 万のレコードがあり、各選択は次のようになります。

SELECT * 
FROM products_loans 
WHERE KOD IN("X17/Q30-10", "X17/12", "X17/5-24") 
AND 369.27 BETWEEN CENA_OD AND CENA_DO;

3 つのローン タイプと、CENA_OD と CENA_DO の間の範囲内にある必要がある価格のため、3 行が返されます。

ただし、ページごとに 10 個の製品を表示する必要があるため、次を使用して変更された選択を通じて実行する必要があります。 または, 、これに対する他の解決策が見つからなかったので。それについて質問しました ここ, 、しかし答えは得られませんでした。参照元の投稿で述べたように、これは別個に行う必要があります。 いいえ 結合で使用できる列です (もちろん価格とコードは除きますが、結果は非常に悪いものでした)。ここにあります show create table, 、kod および CENA_OD/CENA_DO は INDEX 経由で非常にインデックス化されています。

CREATE TABLE `products_loans` (
  `KOEF_ID` bigint(20) NOT NULL,
  `KOD` varchar(30) NOT NULL,
  `AKONTACIA` int(11) NOT NULL,
  `POCET_SPLATOK` int(11) NOT NULL,
  `koeficient` decimal(10,2) NOT NULL default '0.00',
  `CENA_OD` decimal(10,2) default NULL,
  `CENA_DO` decimal(10,2) default NULL,
  `PREDAJNA_CENA` decimal(10,2) default NULL,
  `AKONTACIA_SUMA` decimal(10,2) default NULL,
  `TYP_VYHODY` varchar(4) default NULL,
  `stage` smallint(6) NOT NULL default '1',
 PRIMARY KEY  (`KOEF_ID`),
 KEY `CENA_OD` (`CENA_OD`),
 KEY `CENA_DO` (`CENA_DO`),
 KEY `KOD` (`KOD`),
 KEY `stage` (`stage`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

また、すべてのローン タイプを選択し、後で PHP でフィルタリングすることもうまく機能しません。各タイプには 50,000 を超えるレコードがあり、選択にも時間がかかりすぎるためです...

速度の向上に関するアイデアは大歓迎です。

編集:

ここで説明します

+----+-------------+----------------+-------+---------------------+------+---------+------+--------+-------------+
| id | select_type | table          | type  | possible_keys       | key  | key_len | ref  | rows   | Extra       |
+----+-------------+----------------+-------+---------------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | products_loans | range | CENA_OD,CENA_DO,KOD | KOD  | 92      | NULL | 190158 | Using where |
+----+-------------+----------------+-------+---------------------+------+---------+------+--------+-------------+

結合インデックスを試してみたところ、テスト サーバーのパフォーマンスが 0.44 秒から 0.06 秒に向上しました。ただし、自宅から実稼働サーバーにアクセスできないため、明日試してみる必要があります。

役に立ちましたか?

解決

のようなクエリをリファクタリングしてみます:

SELECT * FROM products_loans 
WHERE KOD IN("X17/Q30-10", "X17/12", "X17/5-24") 
AND CENA_OD >= 369.27
AND CENA_DO <= 369.27;

(インデックスを選択する際、MySQLは非常にスマートではありません)とパフォーマンスをチェックします。

次のtryは、複合キーを追加することです - (KOD、CENA_OD、CENA_DO)

そして、次の主要な試みが価格から分離された製品を持っているあなたのベースをリファクタリングすることです。これは本当に役立つはずです。

PS:右のインデックスを選ぶとき、あなたはまた、のpostgresqlに移行することができ、それが賢くMySQLのよりもです。

他のヒント

あなたの問題は、(間隔内のすべてのポイントのより通常のクエリではなく)ポイントを含む間隔を検索していることです。これらのクエリは標準の B ツリー インデックスではうまく機能しないため、代わりに R ツリー インデックスを使用する必要があります。残念ながら、MySQL では列の R ツリー インデックスを選択できませんが、列のタイプを GEOMETRY に変更し、幾何学的関数を使用して間隔にポイントが含まれているかどうかを確認することで、目的のインデックスを取得できます。

見る カスノイさんの記事 隣接リストとネストされたセット:MySQL そこで彼はこれについてさらに詳しく説明しています。ユースケースは異なりますが、必要なテクニックは同じです。以下は記事の関連部分の抜粋です。

既知の値を含むすべての範囲を検索する必要がある特定のクラスのタスクもあります。

  • IP 範囲禁止リスト内の IP アドレスの検索
  • 日付範囲内で指定された日付を検索する

他にもいくつかあります。これらのタスクは、MySQL の R-Tree 機能を使用することで改善できます。

MySQLは唯一の1つのキーを使用することができます。あなたは常に列の実際のデータ(範囲)に応じて、3列によってエントリを取得した場合、次のいずれかが非常によく、性能の深刻な量を追加することができます:

ALTER TABLE products_loans ADD INDEX(KOD, CENA_OD, CENA_DO);
ALTER TABLE products_loans ADD INDEX(CENA_OD, CENA_DO, KOD);

列の順序が重要であることに注意してください!それはパフォーマンスが改善されない場合は、私たちにクエリのEXPLAIN出力が得られます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top