茫茫網海中的冷日
         
茫茫網海中的冷日
發生過的事,不可能遺忘,只是想不起來而已!
 恭喜您是本站第 1671801 位訪客!  登入  | 註冊
主選單

Google 自訂搜尋

Goole 廣告

隨機相片
IMG_60D_00156.jpg

授權條款

使用者登入
使用者名稱:

密碼:


忘了密碼?

現在就註冊!

DB研討會 : [轉貼]只談MySQL (第15天) Subquery

發表者 討論內容
冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15771
[轉貼]只談MySQL (第15天) Subquery
只談MySQL (第15天) Subquery
標籤:linux mysql

昨天談到Subquery...今天我就針對這個主題做點分享...

Subquery的運用很泛的, 大致有下列:

1. Subquery做為數值運算
例如:
SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2 WHERE column2='20091027');

由資料表t2的column2為'20091027'的資料錄中的column1取得值再去和t1的column1欄位值做比較
或是另一個例子:
SELECT column1, (SELECT column1 FROM t2 WHERE column2='20091027') FROM t1 WHERE column2 = '20091027';

傳回t1的column1資料, t2的column1資料, 而t1及t2的column2值都必需為'20091027'

2. 運用Subqueries作比較運算
例:
SELECT * FROM t1 WHERE column1 = (SELECT MAX(column2) FROM t2);

傳回t1中column1等於t2中的column2最大值的資料錄

3. 和ANY, IN, SOME合用的Subqueries
例如:
SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2); ..t1中的s1等於t2中s1欄位的任一值
SELECT s1 FROM t1 WHERE s1 IN (SELECT s1 FROM t2); .. 同上 = ANY
SELECT s1 FROM t1 WHERE s1 <> ANY (SELECT s1 FROM t2); ..t1中的s1不等於t2中s1欄位的任一值
SELECT s1 FROM t1 WHERE s1 <> SOME (SELECT s1 FROM t2); ..同上<>ANY


4. 和ALL合用的Subqueries
例如:
SELECT s1 FROM t1 WHERE s1 > ALL (SELECT s1 FROM t2);

..t1中s1值大於t2中的s2欄位的所有值

5. Row Subqueries
舉例來說最明白:
SELECT column1,column2,column3
FROM t1
WHERE (column1,column2,column3) IN
(SELECT column1,column2,column3 FROM t2); 或
SELECT column1,column2,column3
FROM t1
WHERE ROW(column1,column2,column3) IN
(SELECT column1,column2,column3 FROM t2);

兩條指令都是一樣的, 看出ROW的用法了嗎?

6. EXISTS和NOT EXISTS
例如:
SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);
SELECT column1 FROM t1 WHERE NOT EXISTS (SELECT * FROM t2);

判斷Subquery是否有資料錄....有的話, 第一條WHERE成立, 第二條不成立

7. 在FROM中的Subqueries
舉例來說:
SELECT AVG(sum_column1)
FROM (SELECT SUM(column1) AS sum_column1
FROM t1 GROUP BY column1) AS t1;

用了一個Subquery當成資料來源t1...可以把Subquery當成暫存資料表或檢視表
關於Subquery, 我們先介紹到這裏, 以後我們會再來討論Subquery的優化問題(Optimization)


原文出處:只談MySQL (第15天) Subquery - iT邦幫忙::IT知識分享社群
冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15771
[轉貼]善用 sub query 優化 order by limit
善用 sub query 優化 order by limit
2009年9月22日 pigo

假設 , 我們有個 Table 叫 test , 有 20 萬筆記錄 , test 有 20 個欄位好了 , 其中有一個欄位 post_time 有建立索引可以排序用的 , 而有個主鍵 id

下一道指令
SQLSELECT * FROM test ORDER BY post_time DESC LIMIT 150000,10

這道指令看似簡單 , 理論上應該跑很快 ~ 實際上卻不然 , 也許跑上 20 秒 , 因為這牽扯到 MySQL Server 的 sort buffer 大小 , 因為這道指令可能會因為 buffer 不足而改用 disk 作 sort , 這樣就很慢了

這時候就要搬出 subquery 了 , 怎麼作 ? 看看下面
SQLSELECT * FROM test  AS t
INNER JOIN ( SELECT id FROM test ORDER BY post_time DESC LIMIT 15000,10 ) AS s
ON t.id=s.id

我相信 , 這道指令應該 1 秒都不用

為何會如此呢 ?

因為我們在 subquery 中只有抓 id , 這樣 mysql 就只需要少量記憶體就可以存放資料列進行排序 , 原始的作法就是每一列有多少資料 , mysql 就必須分配多少記憶體 , 如果資料數太大 , 記憶體不夠分配 , 自然就是用 disk 了

但如果我們要抓的資料只是前面幾筆 , 例如 LIMIT 100,10 , 那麼原本的寫法會比較快 , 因此這可以在程式中判斷而交互使用兩種 QUERY 的方式


原文出處:壞蛋的部落格 » 善用 sub query 優化 order by limit
冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15771
[轉貼]MySQL 子查詢(sub query) limit 的用法
MySQL 子查詢(sub query) limit 的用法
select * from (select * from table order by a limit 100 ) as newtable order by newtable.b

newtable 是一個別名,取什麼都可以
原因是:
error(#1248 Every derived table must have its own alias)



原文出處:MySQL 子查詢(sub query) limit 的用法 @ Arrack筆記 :: 痞客邦 PIXNET ::
冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15771
[轉貼][ MySQL ] When the subselect runs faster
[ MySQL ] When the subselect runs faster
When the subselect runs faster
http://www.mysqlperformanceblog.com/2010/03/18/when-the-subselect-runs-faster/

幾週之前,從我們其中一個客戶那邊接到一個協助查詢最佳化的請求。
這個查詢語法很簡單就像這樣:
SELECT * FROM `table` WHERE (col1='A'||col1='B') ORDER BY id DESC LIMIT 20 OFFSET 0

這個欄位在資料表的情形像這樣:
`col1` enum('A','B','C','CD','DE','F','G','HI') default NULL

該資料表包含 549252 筆列資料,而當然的他有一個索引是設定在 col1 欄位。
MySQL 估計該索引的基數( cardinality )為 87,雖然在這個例子當中我們知道這是不正確的索引基數,
因為他不可能超過 9,這個欄位只有 8 ( 再加上 NULL ) 個不同的內容。
+----+-------------+-------+-------+---------------+------+---------+------+--------+-----------------------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows   | Extra
+----+-------------+-------+-------+---------------+------+---------+------+--------+-----------------------------+
|  1 | SIMPLE	  | table  | range | col1		 | col1 | 2	   | NULL | 549252 | Using where; Using filesort
+----+-------------+-------+-------+---------------+------+---------+------+--------+-----------------------------+

這個查詢花得時間超過 5 分鐘( 由於列資料太多並且資料表不適用於快取情形 )
當妳嘗試執行的時候,MySQL 首先會透過索引試著找出每一列 col1 為 A 或 B 情形。
接著它將會使用檔案排序的方式按照 ID 排列後回傳前 20 筆資料而其餘的忽略。

在這個例子 MySQL 需要 2 個索引,一個用來找尋列資料,另外一個回傳找到的資料的正確排序方式。
MySQL 只會選擇其中一個來執行查詢 - 找到列資料的索引。
當沒有使用 LIMIT 的時候這是一個正確的決定,就算只有一個索引的時後也是如此。
因為這通常可以根據 WHERE 的查詢子句,比較快速回傳所需列數的資料。
特別是在這個例子當中,WHERE 查詢並不是非常具有選擇性。

所以我嘗試這樣:
select * from table where id in (SELECT id FROM `table` WHERE (col1='A'||col1='B')) ORDER BY id DESC LIMIT 20 OFFSET 0;

在這個例子我們強迫 MySQL 取得已經排列過順序的資料,並且從子查詢當中檢查它是否符合我們原本的 WHERE 查詢。
如果妳透過 EXPLAIN 查看你會發現結果非常嚇人,但是事實上相依的子查詢執行只會在結果當中產生 20 筆列資料。
+----+--------------------+-------+-----------------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
+----+--------------------+-------+-----------------+---------------+---------+---------+------+--------+-------------+
| 1 | PRIMARY | table | index | NULL | PRIMARY | 4 | NULL | 765105 | Using where
| 2 | DEPENDENT SUBQUERY | table | unique_subquery | PRIMARY,col1 | PRIMARY | 4 | func | 1 | Using where
+----+--------------------+-------+-----------------+---------------+---------+---------+------+--------+-------------+

這樣的結果反應了一個好很多回應時間:
(20 rows in set (0.01 sec))


透過使用子查詢改寫這個查詢我們確實提昇了一百倍的效能。看來子查詢並不全都是會降低效能的。
即便我們證明了使用子查詢並不總是降低效能,但這個方法並不是最好的方法。
我們並不需要使用單獨的子查詢,去確保 MySQL 在檢查資料表是否符合 WHERE 查詢的時候使用特定的索引。
我們可以使用 FORCE INDEX 提示去複寫 MySQL 所採用的索引。
mysql> explain select * from table FORCE INDEX(PRIMARY) where (col1='A'||col1='B') order by id desc limit 20 offset 0;
+----+-------------+-------+-------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
+----+-------------+-------+-------+---------------+---------+---------+------+--------+-------------+
| 1 | SIMPLE | table | index | NULL | PRIMARY | 4 | NULL | 549117 | Using where
+----+-------------+-------+-------+---------------+---------+---------+------+--------+-------------+
mysql> select * from table FORCE INDEX(PRIMARY) where (col1='A'||col1='B') order by id desc limit 20 offset 0;
...
20 rows in set (0.00 sec)

當 WHERE 查詢非常不具備選擇性的時候這個方法非常管用,
除此之外 MySQL 可能需要掃描非常大量的列資料才能找到相符的資料。妳可以使用另外一個幾年前由 Peter 所撰寫的技巧


原文出處:[ MySQL ] When the subselect runs faster - 黑書記事 - 無名小站
前一個主題 | 下一個主題 | 頁首 | | |



Powered by XOOPS 2.0 © 2001-2008 The XOOPS Project|