0

サイトで実行される次のようなクエリがあります。

SELECT *
FROM `orders`
WHERE
    `co_id`='12660' &&
    ((`from_region`=6 && `to_region`=60) || `id` IN('539110')) &&
    (
        `p_name` LIKE '%search%' ||
        `p_street_address` LIKE '%search%' ||
        `p_city` LIKE '%search%' ||
        `p_state` LIKE '%search%' ||
        `p_zip` LIKE '%search%' ||
        `p_non_us_address` LIKE '%search%' ||
        `p_contact` LIKE '%search%'
    ) &&
    (
        (`when_deleted` >= 1349222400 && `when_deleted` <= 1378511999) ||
        (`assigned_to_date` >= 1349222400 && `assigned_to_date` <= 1378511999) ||
        (`deleted` = "0" && `assigned_to` = "")
    )
ORDER BY p_state,p_city,p_zip,date_time DESC LIMIT 20,20;

これは、かなりの数の列にわたってテキストを検索する検索クエリです。テーブルは注文を保持し、クエリは特定の地域での注文のみをチェックし、それが特定の日付 (その間に削除または割り当てられたか、またはまだ未処理である) であることを確認し、テキストを検索します。

テーブル自体は次のようになります。

CREATE TABLE IF NOT EXISTS `orders` (
  `co_id` smallint(5) unsigned NOT NULL DEFAULT '0',
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `from_region` smallint(5) unsigned NOT NULL DEFAULT '0',
  `to_region` smallint(5) unsigned NOT NULL DEFAULT '0',
  `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `when_deleted` int(10) unsigned NOT NULL DEFAULT '0',
  `important` smallint(1) unsigned NOT NULL DEFAULT '0',
  `p_name` varchar(50) NOT NULL DEFAULT '',
  `p_street_address` varchar(80) NOT NULL DEFAULT '',
  `p_city` varchar(50) NOT NULL DEFAULT '',
  `p_state` char(2) NOT NULL DEFAULT '',
  `p_zip` varchar(10) NOT NULL DEFAULT '',
  `p_non_us_address` varchar(255) NOT NULL,
  `p_country` varchar(15) NOT NULL,
  `p_residence` tinyint(1) NOT NULL DEFAULT '0',
  `p_contact` varchar(50) NOT NULL DEFAULT '',
  `p_phone` varchar(25) NOT NULL,
  `p_cell` varchar(25) NOT NULL,
  `p_altphone` varchar(25) NOT NULL,
  `p_fax` varchar(80) NOT NULL DEFAULT '',
  `p_email` varchar(80) NOT NULL DEFAULT '',
  `p_addl_info_1` varchar(255) NOT NULL,
  `p_addl_info_2` varchar(255) NOT NULL,
  `vehs_avail` int(10) unsigned NOT NULL DEFAULT '0',
  `d_name` varchar(50) NOT NULL DEFAULT '',
  `d_street_address` varchar(80) NOT NULL DEFAULT '',
  `d_city` varchar(50) NOT NULL DEFAULT '',
  `d_state` char(2) NOT NULL DEFAULT '',
  `d_zip` varchar(10) NOT NULL DEFAULT '',
  `d_non_us_address` varchar(255) NOT NULL,
  `d_country` varchar(15) NOT NULL,
  `d_residence` tinyint(1) NOT NULL DEFAULT '0',
  `d_contact` varchar(50) NOT NULL DEFAULT '',
  `d_phone` varchar(25) NOT NULL,
  `d_cell` varchar(25) NOT NULL,
  `d_altphone` varchar(25) NOT NULL,
  `d_fax` varchar(80) NOT NULL DEFAULT '',
  `d_email` varchar(80) NOT NULL DEFAULT '',
  `d_addl_info_1` varchar(255) NOT NULL,
  `d_addl_info_2` varchar(255) NOT NULL,
  `deliver_by` int(10) unsigned NOT NULL DEFAULT '0',
  `b_CustomerId` int(10) unsigned NOT NULL,
  `b_name` varchar(50) NOT NULL DEFAULT '',
  `b_street_address` varchar(80) NOT NULL DEFAULT '',
  `b_city` varchar(50) NOT NULL DEFAULT '',
  `b_state` char(2) NOT NULL DEFAULT '',
  `b_zip` varchar(10) NOT NULL DEFAULT '',
  `b_non_us_address` varchar(255) NOT NULL,
  `b_country` varchar(15) NOT NULL,
  `b_contact` varchar(50) NOT NULL DEFAULT '',
  `b_phone` varchar(25) NOT NULL,
  `b_cell` varchar(25) NOT NULL,
  `b_altphone` varchar(25) NOT NULL,
  `b_fax` varchar(80) NOT NULL DEFAULT '',
  `b_email` varchar(80) NOT NULL DEFAULT '',
  `b_addl_info_1` varchar(255) NOT NULL,
  `b_addl_info_2` varchar(255) NOT NULL,
  `num_units` decimal(5,2) unsigned NOT NULL DEFAULT '0.00',
  `price_per_unit` decimal(9,2) unsigned NOT NULL DEFAULT '0.00',
  `price_per_load` decimal(9,2) unsigned NOT NULL DEFAULT '0.00',
  `additional_charge` decimal(9,2) NOT NULL DEFAULT '0.00',
  `additional_charge_desc` text NOT NULL,
  `fuelSurchargePercent` float(5,2) NOT NULL,
  `fuelSurchargeAmt` decimal(9,2) unsigned NOT NULL,
  `poNumber` varchar(50) NOT NULL,
  `cod` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `run_drive` tinyint(1) NOT NULL DEFAULT '0',
  `desc_vehs` text NOT NULL,
  `other_notes` text NOT NULL,
  `assigned_to` varchar(255) NOT NULL DEFAULT '',
  `assigned_to_date` int(10) unsigned NOT NULL DEFAULT '0',
  `assignedOn` datetime NOT NULL,
  `loaded` int(10) unsigned NOT NULL DEFAULT '0',
  `delivered` int(10) unsigned NOT NULL DEFAULT '0',
  `notifications_entered` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `notifications_assigned` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `notifications_loaded` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `notifications_delivered` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `notifications_email` varchar(100) NOT NULL,
  `owner` smallint(5) unsigned NOT NULL,
  `date_time` int(10) unsigned NOT NULL DEFAULT '0',
  `changed` tinyint(1) NOT NULL DEFAULT '0',
  `synced` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`co_id`,`id`),
  KEY `from_region` (`from_region`),
  KEY `to_region` (`to_region`),
  KEY `deleted` (`deleted`),
  KEY `Delivered` (`delivered`),
  KEY `owner` (`owner`),
  KEY `b_CustomerId` (`b_CustomerId`),
  KEY `co_id` (`co_id`),
  KEY `co_id-p_name` (`co_id`,`p_name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

p_name、p_street_address、p_city、p_state、p_zip、p_non_us_address、および p_contact に追加のインデックスを作成できることはわかっていますが、それは集荷場所を検索するだけです。検索可能な配達および請求場所もあります。これらすべての挿入にインデックスを追加する頃には、大幅に遅くなります。このクエリを構造化して効率を向上させるより良い方法はありますか? 個別のクエリ?サブクエリ?検索専用の別のテーブルを作成する方法さえあるのではないでしょうか?

4

2 に答える 2

0

一般的に、次のようなものが表示される%search%ということは、クエリを最適化できないことを意味します。search%MySQLの組み込みのインデックス機能は、それをすばやく検索できる場所などで非常にうまく機能します。前面にワイルドカードが付いているものはすべて、すべてのレコードに対して個別にテストする必要があることを意味します。これは非常に遅くなる可能性があります。

全文検索を実行する場合は、おそらくFULLTEXTインデックスタイプを使用する必要があります。これは、危険なほど不安定なMyISAMテーブルタイプで何年も機能してきましたが、MySQL5.6にはInnoDBでのサポートが含まれています。

これらの列の全文索引は大いに役立ちますが、の代わりに全文検索MATCHコマンドを使用する必要がありますLIKE

于 2012-11-29T15:36:22.177 に答える
0

これらのインデックスを追加することになりました:

ALTER TABLE `orders` ADD FULLTEXT p_fulltext_idx (`p_name`,`p_street_address`,`p_city`,`p_state`,`p_zip`,`p_non_us_address`,`p_contact`);
ALTER TABLE `orders` ADD FULLTEXT d_fulltext_idx (`d_name`,`d_street_address`,`d_city`,`d_state`,`d_zip`,`d_non_us_address`,`d_contact`);
ALTER TABLE `orders` ADD FULLTEXT b_fulltext_idx (`b_name`,`b_street_address`,`b_city`,`b_state`,`b_zip`,`b_non_us_address`,`b_contact`);

また、使用するクエリを変更しました。

MATCH(`p_name`, `p_street_address`, `p_city`, `p_state`, `p_zip`, `p_non_us_address`, `p_contact`) AGAINST('search')

ライブになる前に、これが書き込みにどのように影響するかを待っていますが、検索ははるかに高速です. すべてが公開されたら、ここに投稿することを忘れないようにします。

于 2012-11-30T16:46:45.333 に答える