Home » Posts tagged "select"

S3 Select 宣佈支援 Parquet 與 bzip2

Amazon S3S3 Select 宣佈支援 Parquet 格式:「Amazon S3 Announces New Features for S3 Select」。

本來 S3 Select 就已經支援 CSV 與 JSON 格式,大多數的引擎也都可以直接吃,這次宣佈支援 JSON Arrays,以及 Parquet 格式:

Today, Amazon S3 Select works on objects stored in CSV and JSON format. Based on customer feedback, we’re happy to announce S3 Select support for Apache Parquet format, JSON Arrays, and BZIP2 compression for CSV and JSON objects. We are also adding support for CloudWatch Metrics for S3 Select, which lets you monitor S3 Select usage for your applications.

另外一個上面也有提到的是宣佈支援 bzip2 格式,不知道有沒有打算支援壓縮率更好的其他格式...

Amazon S3 的流量,以及 S3 與 Glacier 都推出 Select 功能

Twitter 上看到會場的照片,Amazon S3 單一 region 就有 37 Tb/sec 的量:

在這種量下面對 DDoS 沒什麼感覺 XDDD

另外是 Amazon S3 與 Amazon Glacier 都推出了 Select 功能:「S3 Select and Glacier Select – Retrieving Subsets of Objects」。

看示範的程式碼就可以看出用途了,原文中間那段有 sytax error,我這邊就幫忙修掉了:

handler = PrintingResponseHandler()
s3 = boto3.client('s3')
response = s3.select_object_content(
    Bucket="super-secret-reinvent-stuff",
    Key="stuff.csv",
    SelectRequest={
        'ExpressionType': 'SQL',
        'Expression': 'SELECT s._1 FROM S3Object AS s',
        'InputSerialization': {
            'CompressionType': 'NONE',
            'CSV': {
                'FileHeaderInfo': 'IGNORE',
                'RecordDelimiter': '\n',
                'FieldDelimiter': ',',
            }
        },
        'OutputSerialization': {
            'CSV': {
                'RecordDelimiter': '\n',
                'FieldDelimiter': ',',
            }
        }
    }
)

這樣可以大幅降低 I/O,節省成本:

Glacier Select 也是類似的想法,不需要整包拉出來再處理,可以在一開始就設定條件。

Quotient filter

之前有提過「Cuckoo Filter:比 Bloom Filter 多了 Delete」,最近在「A general purpose counting filter: making every bit count」這邊看到 Quotient filter,也是類似 Bloom filter 的資料結構,但想要解決更多問題。

一般的 Bloom filter (BF) 會有這些問題:

  • The inability to delete items
  • Poor scaling out of RAM
  • The inability to resize dynamically
  • The inability to count the number of occurrences of each item, especially with skewed input distributions.

而文章裡提到的 Quotient filter (QF) 就是要解這些問題。另外還提到了 Rank-and-Select-based Quotient filter (RSQF) 以及 Counting Quotient filter (CQF)。雖然多了一些空間需求,但看起來解掉不少問題... (尤其是刪除的能力)

效能上也還不錯,尤其是讀取速度的部份... 不過不知道相對於 Cuckoo filter 差多少。

PostgreSQL 9.5 預定提供的 Row Locking 改善

在「More Concurrency: Improved Locking In PostgreSQL」這邊提到 PostgreSQL 的 Row Locking 的改善,也就是 SELECT ... FOR UPDATESELECT ... FOR SHARE

查了一下 SELECT 的文件,在 7.2 開始提供 FOR UPDATE (PostgreSQL: Documentation: 7.2: SELECT),在 8.1 開始提供 FOR SHARE (PostgreSQL: Documentation: 8.1: SELECT),以維基百科上的紀錄來看,7.2 是 2002 年二月,8.1 是 2005 年十一月,都是已經提很久的功能了。

FOR UPDATEFOR SHARE 可以降低對 transaction 的依賴程度,PostgreSQL 的預設值是 READ COMMITTED,配合 Row Locking 就已經可以做到不少效果了,不需要用到 SERIALIZABLE 等級。

而在最新的 PostgreSQL 9.5 (目前還是開發版),則又多提供了 FOR UPDATE SKIP LOCKED 功能,以官方提供的範例來說,就可以直接避開選位造成的 lock 問題了:

This makes sense because 100 users checking for a free seat concurrently will get 100 different rows. The consequence is that you are not stuck with 1 CPU but you can nicely scale out to all CPUs in the system. As conflicts cannot happen anymore, nobody has to wait on somebody else.

對 locking 控制的更細微。

MySQL 裡搜尋 CHAR/VARCHAR (String) 欄位時要注意的事情

MySQL 表格欄位是 CHAR 或 VARCHAR 時,寫搜尋條件要記得使用 string 格式,而非數字。意思是,要避免這種 SQL query:

SELECT * FROM foo WHERE `column_string` = 123456;

原因是即使 column_string 加上了 B-tree index,也無法利用這個 index 加速查詢。

原因是,除了最明確的 '123456' 會符合外,還有很多種 case 符合:

mysql> SELECT 123456 = '0123456';
+--------------------+
| 123456 = '0123456' |
+--------------------+
|                  1 |
+--------------------+
1 row in set (0.00 sec)

mysql> SELECT 123456 = ' 123456';
+--------------------+
| 123456 = ' 123456' |
+--------------------+
|                  1 |
+--------------------+
1 row in set (0.00 sec)

這使得 index 無用武之地。

但如果欄位本身是數字 (INT/BIGINT),搜尋時用字串反而沒關係:MySQL 會先把字串轉型為數字再比較,所以會用到 index。

總而言之:

  • 可以用 INT/BIGINT 時,不要用 CHAR/VARCHAR 儲存。
  • 使用 CHAR/VARCHAR 的欄位當搜尋條件時,要用字串形式當作搜尋條件。(除非你很清楚你在做什麼)

今天上場當救援投手時解掉的問題...

熱 MySQL InnoDB 的方式...

之前寫過一篇「熱 MySQL 的方法...」,主要是利用 InnoDB 在 SELECT COUNT(*) 時會掃過一次 primary key 來熱:

pt-find --charset=utf8 --print -h $1 -u USER -p PASSWORD | xargs -t -P8 -I% -n1 sh -c "echo 'SELECT COUNT(*) FROM %;' | mysql -h $1 > /dev/null"

但想要熱整個表格時 (data 部份),這個方法就不夠力了,今天才想到可以這樣做:

SELECT COUNT(*) FROM (SELECT * FROM table_name) t;

這方法會把整個表格資料拉出來,但又不會造成大量的網路 i/o (以及洗畫面)。實際測過後發現效果還不錯... (對於 table scan 使用量很大的表格,靠這個把整個表個塞進 InnoDB buffer)

Archives