17

単純なmysqlクエリがありますが、レコードがたくさんある場合(現在103,0000)、パフォーマンスが非常に遅く、filesortを使用していると表示されます。これが遅い理由かどうかはわかりません。それをスピードアップするための提案はありますか?またはfilesortを使用して停止しますか?

MYSQLクエリ:

SELECT *    
FROM adverts
WHERE (price >= 0)
    AND (status = 1)
    AND (approved = 1)
ORDER BY date_updated DESC 
LIMIT 19990, 10

Explainの結果:

id   select_type   table   type    possible_keys    key    key_len    ref    rows   Extra 
1    SIMPLE        adverts range   price            price  4          NULL   103854 Using where; Using filesort

広告テーブルとインデックスは次のとおりです。

CREATE TABLE `adverts` (
  `advert_id` int(10) NOT NULL AUTO_INCREMENT,
  `user_id` int(10) NOT NULL,
  `type_id` tinyint(1) NOT NULL,
  `breed_id` int(10) NOT NULL,
  `advert_type` tinyint(1) NOT NULL,
  `headline` varchar(50) NOT NULL,
  `description` text NOT NULL,
  `price` int(4) NOT NULL,
  `postcode` varchar(7) NOT NULL,
  `town` varchar(60) NOT NULL,
  `county` varchar(60) NOT NULL,
  `latitude` float NOT NULL,
  `longitude` float NOT NULL,
  `telephone1` varchar(15) NOT NULL,
  `telephone2` varchar(15) NOT NULL,
  `email` varchar(80) NOT NULL,
  `status` tinyint(1) NOT NULL DEFAULT '0',
  `approved` tinyint(1) NOT NULL DEFAULT '0',
  `date_created` datetime NOT NULL,
  `date_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `expiry_date` datetime NOT NULL,
  PRIMARY KEY (`advert_id`),
  KEY `price` (`price`),
  KEY `user` (`user_id`),
  KEY `type_breed` (`type_id`,`breed_id`),
  KEY `headline_keywords` (`headline`),
  KEY `date_updated` (`date_updated`),
  KEY `type_status_approved` (`advert_type`,`status`,`approved`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
4

5 に答える 5

41

問題は、MySQLがクエリの実行時に1つのインデックスしか使用しないことです。WHERE句の3つのフィールドを使用する新しいインデックスを追加すると、行の検索が速くなります。

ALTER TABLE `adverts` ADD INDEX price_status_approved(`price`, `status`, `approved`);

MySQLのドキュメントによるとORDERBYOptimization

場合によっては、MySQLはインデックスを使用してORDER BYを解決できませんが、WHERE句に一致する行を見つけるためにインデックスを使用します。これらのケースには、次のものが含まれます。
行のフェッチに使用されるキーは、ORDERBYで使用されるキーと同じではありません。

これがあなたの場合に起こることです。の出力が示すEXPLAINように、オプティマイザはキーpriceを使用して行を検索します。ただし、はキーに属していないORDER BYフィールドにあります。date_updatedprice

行をより速く見つけ、行をより速くソートするには、WHEREおよびORDER BY句で使用されるすべてのフィールドを含むインデックスを追加する必要があります。

ALTER TABLE `adverts` ADD INDEX status_approved_date_updated(`status`, `approved`, `date_updated`);

並べ替えに使用するフィールドは、インデックスの最後の位置にある必要があります。priceクエリで使用される条件は値の範囲を返すため、インデックスに含めることは無意味です。

EXPLAINそれでもfilesortを使用していることが示されている場合は、MySQLに選択したインデックスを使用させることができます。

SELECT adverts.*
FROM adverts
FORCE INDEX(status_approved_date_updated)
WHERE price >= 0
AND adverts.status = 1
AND adverts.approved = 1
ORDER BY date_updated DESC 
LIMIT 19990, 10

MySQLオプティマイザはほとんどの場合正しい選択を行うため、通常はインデックスを強制する必要はありません。しかし、時にはそれは悪い選択をするか、最良の選択ではありません。パフォーマンスが向上するかどうかを確認するには、いくつかのテストを実行する必要があります。

于 2012-08-27T20:20:59.707 に答える
3

-の周りのチェックマークを削除します'0'。現在、インデックスの使用が妨げられている可能性がありますが、よくわかりません。それにもかかわらず、価格はintタイプであり、文字列ではないため、より良いスタイルです。

SELECT adverts .*    
FROM adverts
WHERE (
price >= 0
)
AND (
adverts.status = 1
)
AND (
adverts.approved = 1
)
ORDER BY date_updated DESC 
LIMIT 19990 , 10
于 2012-08-27T21:26:34.423 に答える
1

WHERE条件は、、を使用してprice選択し、次にソートに使用されます。statusapproveddate_updated

したがって、これらのフィールドを持つ単一のインデックスが必要です。approved、、、の順statusにインデックスを作成することをお勧めします。pricedate_updated

一般的なルールは、WHEREの等式を最初に配置し、次に範囲(以上、以下、間など)を配置し、最後にフィールドを並べ替えることです。(1つのフィールドを省略すると、この目的でインデックスが使用できなくなったり、使用できなくなったりする可能性があることに注意してください)。

CREATE INDEX advert_ndx ON adverts (approved, status, price, date_updated);

このように、テーブルデータへのアクセスは、LIMITその魔法が働いた後にのみ必要になり、少数のレコードのみを低速で取得します。

INSERTまた、 sとsを高速化する不要なインデックスも削除しますUPDATE

于 2012-08-27T22:04:06.943 に答える
1

date_updatedMySQLはソートにキーを使用しませんが、句priceで使用されているキーを使用するだけです。WHEREインデックスヒントの使用を試みることができます。

http://dev.mysql.com/doc/refman/5.1/en/index-hints.html

次のようなものを追加します

USE KEY FOR ORDER BY  (date_updated)
于 2012-08-27T20:37:24.270 に答える
1

2つの提案があります。まず、where句のゼロ付近の引用符を削除します。その行は次のようになります。

price >= 0

次に、次のインデックスを作成します。

CREATE INDEX `helper` ON `adverts`(`status`,`approved`,`price`,`date_created`);

これにより、MySQLは、インデックスのみを使用して、LIMIT句で指定された10行を見つけることができます。Filesort自体は悪いことではありません...処理する必要のある行数はです。

于 2012-08-27T21:46:07.003 に答える