我在我的一些mysql數據庫查詢中遇到了一些優化問題。在構建我的應用程序之後,我試圖使用mysqltuner進行優化並解釋,以查找非索引查詢。這是一個經常運行的查詢和不使用索引報告:使用錯誤索引的mysql查詢
SELECT count(*) AS rangedandselling
FROM
(SELECT DISTINCT `store_formats`.`Store Name`
FROM (`eds_sales`
JOIN `store_formats`
ON (`eds_sales`.`Store Nbr` = `store_formats`.`Store Nbr`)
)
WHERE `eds_sales`.`Prime Item Nbr` = '4'
AND `eds_sales`.`Date` BETWEEN CAST('2016-07-14' AS DATETIME)
AND CAST('2016-07-21' AS DATETIME)
AND `store_formats`.`Format Name` IN ('format1','format2')
AND `store_formats`.`Store Name` IN (
SELECT DISTINCT `store_formats`.`Store Name`
FROM (`eds_stock`
JOIN `store_formats`
ON (`eds_stock`.`Store Nbr` = `store_formats`.`Store Nbr`)
)
WHERE `eds_stock`.`Prime Item Nbr` = '4'
AND `eds_stock`.`Date` BETWEEN CAST('2016-07-14' AS DATETIME)
AND CAST('2016-07-21' AS DATETIME)
AND `store_formats`.`Format Name` IN ('format1','format2')
AND `eds_stock`.`Curr Traited Store/Item Comb.` = '1')
) t
這是解釋輸出:https://tools.mariadb.org/ea/pyb3h
雖然我已經收錄參與加入和查找列,它看起來就像它正在選擇另一個索引。這個其他索引被稱爲uniqness,並且由用於插入的源列中的6個不同的列組成(這些列的組合是使得行唯一的唯一因素,因此我給出了這個名稱)。然後我確定我有其他列的索引,我可以在解釋中看到它們。我不知道爲什麼會發生這種情況,有人可以幫忙嗎?
關於優化此查詢的任何想法?
這裏是那些上面的鏈接不起作用的解釋:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+---+---+---+---+---+---+---+---+---+---+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 167048 | |
| 2 | DERIVED | eds_sales | ref | uniqness,Prime Item Nbr,Store Nbr | uniqness | 4 | const | 23864 | Using where; Using index; Using temporary |
| 2 | DERIVED | store_formats | ref | Store Nbr,Store Name,Format Name | Store Nbr | 5 | equidata.eds_sales.Store Nbr | 1 | Using where |
| 2 | DERIVED | <subquery3> | eq_ref | distinct_key | distinct_key | 84 | func | 1 | Distinct |
| 3 | MATERIALIZED | store_formats | ALL | Store Nbr,Store Name,Format Name | NULL | NULL | NULL | 634 | Using where; Distinct |
| 3 | MATERIALIZED | eds_stock | ref | uniqness,Prime Item Nbr,Store Nbr | uniqness | 8 | const,equidata.store_formats.Store Nbr | 7 | Using where; Distinct |
+---+---+---+---+---+---+---+---+---+---+
我也張貼了相關的表結構:
--
-- Table structure for table `eds_sales`
--
CREATE TABLE `eds_sales` (
`id` int(12) NOT NULL,
`Prime Item Nbr` int(12) NOT NULL,
`Prime Item Desc` varchar(255) NOT NULL,
`Prime Size Desc` varchar(255) NOT NULL,
`Variety` varchar(255) NOT NULL,
`WHPK Qty` int(5) NOT NULL,
`SUPPK Qty` int(5) NOT NULL,
`Depot Nbr` int(5) NOT NULL,
`Depot Name` varchar(255) NOT NULL,
`Store Nbr` int(5) NOT NULL,
`Store Name` varchar(255) NOT NULL,
`EPOS Quantity` int(5) NOT NULL,
`EPOS Sales` float(4,2) NOT NULL,
`Date` date NOT NULL,
`Client` varchar(255) NOT NULL,
`Retailer` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `eds_sales`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `uniqness` (`Prime Item Nbr`,`Prime Item Desc`,`Prime Size Desc`,`Variety`,`WHPK Qty`,`SUPPK Qty`,`Depot Nbr`,`Depot Name`,`Store Nbr`,`Store Name`,`Date`,`Client`) USING BTREE,
ADD KEY `Prime Item Nbr` (`Prime Item Nbr`),
ADD KEY `Store Nbr` (`Store Nbr`);
表結構表eds_stock
CREATE TABLE `eds_stock` (
`Prime Item Nbr` int(12) NOT NULL,
`Prime Item Desc` varchar(255) NOT NULL,
`Prime Size Desc` varchar(255) NOT NULL,
`Variety` varchar(255) NOT NULL,
`Curr Valid Store/Item Comb.` int(12) NOT NULL,
`Curr Traited Store/Item Comb.` int(12) NOT NULL,
`Store Nbr` int(12) NOT NULL,
`Store Name` varchar(255) NOT NULL,
`Curr Str On Hand Qty` int(12) NOT NULL,
`Curr Str In Transit Qty` int(12) NOT NULL,
`Curr Str On Order Qty` int(12) NOT NULL,
`Curr Str In Depot Qty` int(12) NOT NULL,
`Curr Instock %` int(12) NOT NULL,
`Max Shelf Qty` int(12) NOT NULL,
`On Hand Qty` int(12) NOT NULL,
`Date` date NOT NULL,
`Client` varchar(255) NOT NULL,
`Retailer` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `eds_stock`
ADD UNIQUE KEY `uniqness` (`Prime Item Nbr`,`Store Nbr`,`Date`,`Client`,`Retailer`),
ADD KEY `Prime Item Nbr` (`Prime Item Nbr`),
ADD KEY `Store Nbr` (`Store Nbr`),
ADD KEY `Curr Valid Store/Item Comb.` (`Curr Valid Store/Item Comb.`);
表格結構store_formats
CREATE TABLE `store_formats` (
`id` int(12) NOT NULL,
`Store Nbr` int(4) DEFAULT NULL,
`Store Name` varchar(27) DEFAULT NULL,
`City` varchar(19) DEFAULT NULL,
`Post Code` varchar(9) DEFAULT NULL,
`Region #` int(2) DEFAULT NULL,
`Region Name` varchar(10) DEFAULT NULL,
`Distr #` int(3) DEFAULT NULL,
`Dist Name` varchar(26) DEFAULT NULL,
`Square Footage` varchar(7) DEFAULT NULL,
`Format` int(1) DEFAULT NULL,
`Format Name` varchar(23) DEFAULT NULL,
`Store Type` varchar(20) DEFAULT NULL,
`TV Region` varchar(12) DEFAULT NULL,
`Pharmacy` varchar(3) DEFAULT NULL,
`Optician` varchar(3) DEFAULT NULL,
`Home Shopping` varchar(3) DEFAULT NULL,
`Retailer` varchar(15) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `store_formats`
ADD PRIMARY KEY (`id`),
ADD KEY `Store Nbr` (`Store Nbr`),
ADD KEY `Store Name` (`Store Name`),
ADD KEY `Format Name` (`Format Name`);
而在您的心中,爲什麼該查詢必須使用索引?你認爲如果一個查詢使用索引,它使它更快?你有沒有想過不能使用索引的查詢?查看一開始就有的「SELECT COUNT(*)」。它轉化爲「在這裏計數一切」。爲了cout * everything *,你需要獲取* everything *,並且你不需要索引。根本沒有必要優化該查詢。您可以簡單地每天運行幾次,並將計數保存在某個地方,這樣每次需要計數時都不會敲擊db。 – Mjh
認爲日期範圍是一個來自php的變量,對於進入'store_formats'.'Format Name' IN('format1','format2')的商店格式數組也是如此。因此爲了存儲結果I將需要運行數千和數千個組合 –
這不是我的地方告訴人們如何處理他們的項目,但是當你創建數據庫模型時,你通常會考慮你將如何處理數據和數據是爲了。您的查詢非常難看,難以閱讀。創建複雜的模型和查詢並不難 - 這很容易。什麼是困難的是創造一些簡單的東西,在任何情況下都有效。您設計的方式不會讓自己輕易被使用或查詢。然而,正如我所提到的 - 你最初的問題是爲什麼MySQL不使用索引,答案是 - 因爲它不是必需的。 – Mjh