簡體   English   中英

在這種情況下,MyISAM比mysql中的InnoDB快得多

[英]In this case MyISAM is dramatically faster than InnoDB in mysql

我一直在編寫計算結果,該算法計算InnoDB表中客戶之間的距離。 例如,如果我的客戶是A,B,C和D,則數據庫中的表格如下所示:

From | To    | Distance
  A     B        344
  A     C        274
  A     D        182
  B     C        338

等等...我認為我將達到5000萬,這是很多行。

其他列是product_type和value。 那些告訴我客戶B(列中的customer_to)買了多少product_type。 這意味着我每次都有多次,具體取決於客戶B購買的product_types數量。

我需要查詢將每個客戶與他的鄰居購買的產品和價值分組。 查詢如下所示:

select customer_from, product_type, avg(value) as opportunity
from customer_distances
where distance < 500
group by customer_from, product_type
order by opportunity desc; 

innodb表無法回答我那個查詢。 盡管我將net_read_timeout更改為28800,但在查詢期間mysql連接丟失了。

我認為它與用於事務處理的innodb構建有關,而不是用於密集查詢。 所以我用MyIsam作為引擎創建了一個新表,並插入 - 從innodb表中選擇所有記錄。

正如預期的那樣,選擇速度非常快(70 segs),所有其他選擇都像count(distinct customer_from),幾乎是瞬間的。

出於好奇,我試圖繼續在myisam表中插入距離的過程。 當程序開始運行至少比在innodb表上工作時快100倍時,我感到很驚訝 - 對於INSERTS!

對於每個客戶,程序會插入3000行(每個product_type每個鄰居一個。每個客戶有300個鄰居和10個product_types)。 使用innodb表插入一個客戶需要40到60秒(aprox.3000行)。 使用myisam表,插入3個客戶(9000行aprox)需要1秒鍾。

一些額外的信息:

總而言之,問題是:為什么MyISAM快速插入語句? 你怎么看?

編輯1:我正在為兩個表添加創建語句,即innodb和myisam。 編輯2:我刪除了一些無用的信息,並在這里和那里形成了一點點。

/* INNODB TABLE */
CREATE TABLE `customer_distances` (
  `customer_from` varchar(50) NOT NULL,
  `customer_from_type` varchar(50) DEFAULT NULL,
  `customer_from_segment` varchar(50) DEFAULT NULL,
  `customer_from_district` int(11) DEFAULT NULL,
  `customer_from_zone` int(11) DEFAULT NULL,
  `customer_from_longitud` decimal(15,6) DEFAULT NULL,
  `customer_from_latitud` decimal(15,6) DEFAULT NULL,
  `customer_to` varchar(50) NOT NULL,
  `customer_to_type` varchar(50) DEFAULT NULL,
  `customer_to_segment` varchar(50) DEFAULT NULL,
  `customer_to_district` int(11) DEFAULT NULL,
  `customer_to_zone` int(11) DEFAULT NULL,
  `customer_to_longitud` decimal(15,6) DEFAULT NULL,
  `customer_to_latitud` decimal(15,6) DEFAULT NULL,
  `distance` decimal(10,2) DEFAULT NULL,
  `product_business_line` varchar(50) DEFAULT NULL,
  `product_type` varchar(50) NOT NULL,
  `customer_from_liters` decimal(10,2) DEFAULT NULL,
  `customer_from_dollars` decimal(10,2) DEFAULT NULL,
  `customer_from_units` decimal(10,2) DEFAULT NULL,
  `customer_to_liters` decimal(10,2) DEFAULT NULL,
  `customer_to_dollars` decimal(10,2) DEFAULT NULL,
  `customer_to_units` decimal(10,2) DEFAULT NULL,
  `liters_opportunity` decimal(10,2) DEFAULT NULL,
  `dollars_opportunity` decimal(10,2) DEFAULT NULL,
  `units_oportunity` decimal(10,2) DEFAULT NULL,
  PRIMARY KEY (`cliente_desde`,`cliente_hasta`,`grupo`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/* MYISAM TABLE */
CREATE TABLE `customer_distances` (
  `customer_from` varchar(50) NOT NULL,
  `customer_from_type` varchar(50) DEFAULT NULL,
  `customer_from_segment` varchar(50) DEFAULT NULL,
  `customer_from_district` int(11) DEFAULT NULL,
  `customer_from_zone` int(11) DEFAULT NULL,
  `customer_from_longitud` decimal(15,6) DEFAULT NULL,
  `customer_from_latitud` decimal(15,6) DEFAULT NULL,
  `customer_to` varchar(50) NOT NULL,
  `customer_to_type` varchar(50) DEFAULT NULL,
  `customer_to_segment` varchar(50) DEFAULT NULL,
  `customer_to_district` int(11) DEFAULT NULL,
  `customer_to_zone` int(11) DEFAULT NULL,
  `customer_to_longitud` decimal(15,6) DEFAULT NULL,
  `customer_to_latitud` decimal(15,6) DEFAULT NULL,
  `distance` decimal(10,2) DEFAULT NULL,
  `product_business_line` varchar(50) DEFAULT NULL,
  `product_type` varchar(50) NOT NULL,
  `customer_from_liters` decimal(10,2) DEFAULT NULL,
  `customer_from_dollars` decimal(10,2) DEFAULT NULL,
  `customer_from_units` decimal(10,2) DEFAULT NULL,
  `customer_to_liters` decimal(10,2) DEFAULT NULL,
  `customer_to_dollars` decimal(10,2) DEFAULT NULL,
  `customer_to_units` decimal(10,2) DEFAULT NULL,
  `liters_opportunity` decimal(10,2) DEFAULT NULL,
  `dollars_opportunity` decimal(10,2) DEFAULT NULL,
  `units_oportunity` decimal(10,2) DEFAULT NULL,
  PRIMARY KEY (`cliente_desde`,`cliente_hasta`,`grupo`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

插入

  • 默認情況下,InnoDB會立即“提交”每個INSERT 這可以通過一次聚集100-1000行來解決。
  • 批量插入將加速MyISAM和InnoDB - 可能是10倍。
  • 了解autocommitBEGIN..COMMIT

選擇

  • InnoDB比MyISAM消耗更多的磁盤空間 - 通常為2x-3x; 這可能影響表掃描
  • 對於該查詢,(customer_from,product_type,distance)上的復合索引可能對兩個引擎都有幫助。

調音

  • 當運行 MyISAM的,設置key_buffer_size的RAM和20% innodb_buffer_pool_size=0
  • 運行InnoDB中,設置key_buffer_size只有10M和innodb_buffer_pool_size的RAM 70%。

規范化,節省空間

  • 更小 - >更多可緩存 - >更少I / O - >更快(在任一引擎中)
  • 在大多數情況下, DECIMAL(10,2)並不是最好的。 考慮FLOAT用於非貨幣(例如distance )。 考慮更少的數字; 最多可處理99,999,999.99,占用5個字節。
  • 擁有復制列通常不是一個好主意,例如customer_fromcustomer_to的10列。 有一個Customers表,其中包含兩者。
  • 您的每個緯度和縱向都是7個字節,並且具有不必要的分辨率。 建議使用latidud DECIMAL(6,4)longitud (7,4)總共 7個字節。 (這些分辨率為16米/ 52英尺。)

結果

在這些建議之后,50M行表將非常小,並且在兩個引擎中運行得非常快。 然后再次運行比較。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM