2012-11-29 101 views
0

我有這樣一個查詢,在網站上運行:我能做些什麼來優化這個SQL查詢

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一些額外的指標,但是這只是在尋找,撿拾位置。還有一個可以搜索的交付和結算位置。到我添加索引時,所有這些插入將會大大減慢。有沒有更好的方法可以構建這個查詢來提高效率?單獨查詢?子查詢?也許甚至有辦法創建一個僅用於搜索的單獨表格?

+0

我認爲你應該考慮重新設計你的數據庫,並將一個表分成幾個表。什麼時候一個客戶有多個送貨地址? – Mirco

回答

0

通常看到像%search%這樣的東西,表示查詢無法對進行優化。 MySQL的內置索引功能非常適合諸如search%之類的內容,它可以快速查找。前面帶有通配符的任何東西意味着它將不得不逐個測試每一條記錄,這可能非常緩慢。

如果您想進行全文搜索,您應該使用FULLTEXT索引類型。多年來,它一直在危險的片狀MyISAM表類型上工作,但MySQL 5.6在InnoDB上包含對此的支持。

對這些列的全文索引將大有幫助,但您需要使用全文搜索MATCH命令而不是LIKE

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') 

我等着看如何影響它寫入發佈之前,但搜索的方式更快。我會盡力記住一旦全部推出,就會在這裏發佈。