簡體   English   中英

MySQL OUTER LEFT JOIN性能

[英]MySQL OUTER LEFT JOIN performance

我正在更新現有的基於Web的清單系統,該系統從MySQL數據庫中提取數據。 存儲的數據的主要結構是具有一對多關系的“項目”和“標簽”(項目可以具有多個對應的標簽)

現有的數據前端系統是一個Backbone.js應用程序,該應用程序在登錄時提取整個數據存儲區,並在內存中處理該數據,並在必要時通過RESTful接口將其提交回數據庫。 (這不是我本來要設計系統的方式,但是現在它已成為Backbone和Spine應用程序中的常見模式,以及大多數教程和書籍如何教授這些框架)。

為了提供由前端執行的初始提取,以捕獲整個數據集(此時約有1000個項目和10,000個項目標簽),后端對項目表執行SELECT查詢,然后對標簽進行后續SELECT查詢表中提取的每個項目。 表現很糟糕。 我認為可以通過JOIN進行改進,弄清楚一個選擇查詢優於1000個。以下查詢獲取我需要的數據,但是即使在我的本地開發服務器上執行也要花費15秒以上的時間。 是什么賦予了? 我們是否可以在不設置其他基礎架構(例如緩存鍵值存儲)的情況下改進此系統或查詢?

SELECT items.*, itemtags.id as `tag_id`, itemtags.tag, itemtags.type
FROM items LEFT OUTER JOIN
     itemtags
     ON items.id = itemtags.item_id
ORDER BY items.id;

表結構如下:

CREATE TABLE `items` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `num` int(11) NOT NULL,
  `title` varchar(100) NOT NULL,
  `length_inches` int(10) unsigned DEFAULT NULL,
  `length_feet` int(10) unsigned DEFAULT NULL,
  `width_inches` int(10) unsigned DEFAULT NULL,
  `width_feet` int(10) unsigned DEFAULT NULL,
  `height_inches` int(10) unsigned DEFAULT NULL,
  `height_feet` int(10) unsigned DEFAULT NULL,
  `depth_inches` int(10) unsigned DEFAULT NULL,
  `depth_feet` int(10) unsigned DEFAULT NULL,
  `retail_price` int(10) unsigned DEFAULT NULL,
  `discount` int(10) unsigned DEFAULT NULL,
  `decorator_price` int(10) unsigned DEFAULT NULL,
  `new_price` int(10) unsigned DEFAULT NULL,
  `sold` int(10) unsigned NOT NULL,
  `push_date` int(10) unsigned DEFAULT NULL,
  `updated` int(10) unsigned NOT NULL,
  `created` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1747 DEFAULT CHARSET=latin1;

CREATE TABLE `itemtags` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `item_id` int(10) unsigned NOT NULL,
  `tag` varchar(100) NOT NULL,
  `type` varchar(100) NOT NULL,
  `created` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=61474 DEFAULT CHARSET=latin1;

在性能方面,您可能沒有進行同類比較。

SQL查詢完全在做以下事情:

  • 將兩個表連接在一起
  • items.id對結果排序
  • 返回所有結果

原始版本是否同時執行所有這三個操作並等待它們完成?

我的猜測是,原始代碼會按您想要的順序拉回項目,然后僅在任意給定時間拉動少數實際需要的標簽。

此外,尚不清楚items.*數據的大小。 制定查詢的方式,您將每個項目的查詢次數拉了10次左右-可能比原始數據要大得多。

真正的問題是為什么您需要所有這些信息在應用程序的內存中。 您擁有數據庫,只需在需要時取回所需的內容即可。 您熟悉limitoffset嗎?這些可能正是您真正想要的。

我認為您可以使用此:

SELECT *, a.id as `tag_id`, a.tag, a.type
FROM items LEFT OUTER JOIN
     (SELECT id, item_id, tag, type from itemtags ORDER BY 1,2,3) a
     ON items.id = a.item_id
ORDER BY items.id;

我並沒有做太多改變,只是別名。 a並不表示任何重要意義。

我沒有填寫表格,但您原來的查詢用了4毫秒,我的查詢用了1毫秒。

http://sqlfiddle.com/#!2/b9551/6

無論您的數據集中有什么內容,您的應用程序都可以提取整個數據存儲。 由於數據存儲和數據集不是同義詞。

您也沒有任何indexes 您應該在ID, ITEM_ID上放置索引ID, ITEM_ID以優化表以更快地返回結果。 我在子查詢中創建了一個索引,其order by 希望這可以幫助。

暫無
暫無

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

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