2011-05-30 37 views
3

下面是我的表和我運行一些需要大量時間(10-40秒)的一些查詢。我應該添加哪些索引以使表現更好,而不會讓表格太大。另外我被告知,如果我使用'abc%'作爲我的查詢,我可以使用索引。這是真的?提高大量行的性能(1,000,000條記錄)

phppos_items

+-----------------------+--------------+------+-----+---------+----------------+ 
| Field     | Type   | Null | Key | Default | Extra   | 
+-----------------------+--------------+------+-----+---------+----------------+ 
| name     | varchar(255) | NO |  | NULL |    | 
| category    | varchar(255) | NO |  | NULL |    | 
| supplier_id   | int(11)  | YES | MUL | NULL |    | 
| item_number   | varchar(255) | YES | UNI | NULL |    | 
| description   | varchar(255) | NO |  | NULL |    | 
| cost_price   | double(15,2) | NO |  | NULL |    | 
| unit_price   | double(15,2) | NO |  | NULL |    | 
| quantity    | double(15,2) | NO |  | 0.00 |    | 
| reorder_level   | double(15,2) | NO |  | 0.00 |    | 
| location    | varchar(255) | NO |  | NULL |    | 
| item_id    | int(10)  | NO | PRI | NULL | auto_increment | 
| allow_alt_description | tinyint(1) | NO |  | NULL |    | 
| is_serialized   | tinyint(1) | NO |  | NULL |    | 
| deleted    | int(1)  | NO |  | 0  |    | 
+-----------------------+--------------+------+-----+---------+----------------+ 

#checking if item exists 
SELECT * FROM (`phppos_items`) WHERE `item_id` = 1 

#Get all offset + limit, can take 20+ seconds, take longer as offset gets bigger 
SELECT * FROM (`phppos_items`) WHERE `deleted` = 0 ORDER BY `name` asc LIMIT 16, 16 

#Count all non deleted, haven't tested yet bug I would imagine it would take awhile as deleted is not indexed 
SELECT * FROM (`phppos_items`) WHERE `deleted` = 0 

#Filtering, haven't tested yet, but I would guess it would take a while as there are no indexes on any of these fields 
SELECT * FROM (`phppos_items`) WHERE `quantity` <= reorder_level AND `is_serialized` = 1 AND `description` = '' AND `deleted` = 0 ORDER BY `name` asc 

#Get info about a particular item. This is pretty fast 
SELECT * FROM (`phppos_items`) WHERE `item_id` = 1 

#Get info about an item based on item_number, this seems pretty fast 
SELECT * FROM (`phppos_items`) WHERE `item_number` = '1234' 

#Search queries, very slow 
SELECT * FROM (`phppos_items`) WHERE `deleted` = 0 AND `name` LIKE '%abc%' ORDER BY `name` asc 
SELECT DISTINCT `category` FROM (`phppos_items`) WHERE `deleted` = 0 AND `category` LIKE '%abc%' ORDER BY `category` asc 
SELECT * FROM (`phppos_items`) WHERE `deleted` = 0 AND `item_number` LIKE '%abc%' ORDER BY `item_number` asc 
SELECT * FROM (`phppos_items`) WHERE `deleted` = 0 AND `name` LIKE '%abc%' ORDER BY `name` asc 
SELECT * FROM (`phppos_items`) WHERE `deleted` = 0 AND `item_number` LIKE '%abc%' ORDER BY `item_number` asc 
SELECT * FROM (`phppos_items`) WHERE (name LIKE '%abc%' or item_number LIKE '%abc%' or category LIKE '%abc%') and deleted=0 ORDER BY `name` asc LIMIT 16 

#Category search, pretty fast 
SELECT DISTINCT `category` FROM (`phppos_items`) WHERE `deleted` = 0 AND `category` LIKE '%abc%' ORDER BY `category` asc 

#Get Categories, pretty fast 
SELECT DISTINCT `category` FROM (`phppos_items`) WHERE `deleted` = 0 ORDER BY `category` asc 

回答

3

一般的經驗法則是看WHERE條款和索引使用有列。看看你有第一個候選人將增加指數deleteditem_number。 MySQL會爲你提供主鍵索引。 SHOW INDEX將顯示錶格的索引信息。

你說在LIKE參數開頭沒有通配符是真的。看看這個questionINDEX爲字符串構建的方式是從開始到結束查看字符串,並以這種方式將其插入到索引中。從您的查詢看起來,您可能需要查看FULLTEXT索引或可能重新修復問題,因此您不必創建FULLTEXT索引。

4

您的搜索查詢根本不使用任何索引,也不能對當前查詢使用索引。

如果你做了like '%....%'比不可能使用索引。

你這裏的選項有:

  1. 更改您的查詢是這樣的:like '...%'
  2. 使用帶有全文搜索
  3. 使用一個單獨的全文搜索引擎MyISAM表(獅身人面像,Solr的,等等。 ..)

至於你limit/offset問題。

而不是使用offset,請嘗試使用類似name > 'previous name'。雖然這樣的事情只會在name是唯一的情況下正常工作。一般來說,您不會希望使用超過1000的limit/offset,因爲數據庫將不得不遍歷所有這些行。

1

拇指的另一個很好的規則從來都不是在一個不平凡的查詢中使用

select * 

。相反,列出你需要的列。

如果你只檢查行的存在,你可以使用

select count(*)