SELECT Expires


동영상 설명은 아래에 있습니다.

Expire 정보를 조회

레디스에서는 expire 명령으로 키에 만료시간을 설정할 수 있습니다.
하지만 만료시간이 설정된 키를 따로 조회할 수 있는 기능은 없었습니다.
엔터프라이즈 버전에서는 만료시간이 설정된 키들을 아래와 같은 쿼리로 조회할 수 있습니다.
SELET * FROM EXPIRES.*;
Datatype 부분에 expires를 지정해서 조회하면 됩니다.
컬럼은 key와 ttl 입니다. 일반 쿼리에서는 만료시간을 얻기 위해서 ttl() function을 사용했는데 여기서는 ttl이 컬럼으로 제공됩니다.

주의
  • 키 조건은 where를 사용하세요. Expires.key* 이런 조건은 적용되지 않습니다.

테스트 데이터 입력: Expire를 입력합니다.

Example

명령>expire myint1 86100
명령>expire myint2 86200
명령>expire mylist1 86300
명령>expire mylist2 86400
명령>expire myname1 86500
명령>expire myname2 86600
명령>expire myset1 86700
명령>expire myset2 86800

SELECT

  • Count(), min(), max()같은 일반적인 function을 사용할 수 있습니다.
  • Count(key)보다 count(*)가 더 빠릅니다.
    Count(*)는 키 전체 개수를 한번에 가져오고, count(key)는 키를 하나씩 일일이 셉니다.

Example

명령>select count(*) from expires.*;   opcode
결과> 0) count(*)
1) 8
명령>select count(key) from expires.*;   opcode
결과> 0) count(key)
1) 8
명령>select * from expires.*;   opcode
결과> 0) key|ttl
1) myname1|86500
2) mylist1|86300
3) mylist2|86400
4) myname2|86600
5) myint2|86200
6) myset2|86800
7) myset1|86700
8) myint1|86100
명령>select key, ttl from expires.*;   opcode
결과> 0) key|ttl
1) myname1|86500
2) mylist1|86300
3) mylist2|86400
4) myname2|86600
5) myint2|86200
6) myset2|86800
7) myset1|86700
8) myint1|86100
명령>select key, ttl(key) from all.* where ttl(key) > 0;   opcode
결과> 0) key|ttl(key)
1) myset2|86800
2) mylist2|86400
3) mylist1|86300
4) myname2|86600
5) myint1|86100
6) myint2|86200
7) myname1|86500
8) myset1|86700

ORDER, LIMIT

  • Order by, limit를 사용할 수 있습니다.
  • 키가 정렬(sort)되어 있지 않습니다. 필요하면 order by key를 사용하세요.
    Expire는 순서없이 저장되는 구조인 dict(hash table)을 사용합니다.

Example

명령>select * from expires.* order by key;   opcode
결과> 0) key|ttl
1) myint1|86100
2) myint2|86200
3) mylist1|86300
4) mylist2|86400
5) myname1|86500
6) myname2|86600
7) myset1|86700
8) myset2|86800
명령>select * from expires.* order by key desc;   opcode
결과> 0) key|ttl
1) myset2|86800
2) myset1|86700
3) myname2|86600
4) myname1|86500
5) mylist2|86400
6) mylist1|86300
7) myint2|86200
8) myint1|86100
명령>select * from expires.* limit 5;   opcode
결과> 0) key|ttl
1) myname1|86500
2) mylist1|86300
3) mylist2|86400
4) myname2|86600
5) myint2|86200
명령>select * from expires.* order by key limit 5;   opcode
결과> 0) key|ttl
1) myint1|86100
2) myint2|86200
3) mylist1|86300
4) mylist2|86400
5) myname1|86500
명령>select * from expires.* order by key limit 3,4;   opcode
결과> 0) key|ttl
1) mylist2|86400
2) myname1|86500
3) myname2|86600
4) myset1|86700

FUNCTIONS

Min(), max(), upper(), length() 등 일반적인 function을 사용할 수 있습니다.

Example

명령>select min(key), max(key) from expires.*;   opcode
결과> 0) min(key)|max(key)
1) myint1|myset2
명령>select key, upper(key), length(key) from expires.*;   opcode
결과> 0) key|upper(key)|length(key)
1) myname1|MYNAME1|7
2) mylist1|MYLIST1|7
3) mylist2|MYLIST2|7
4) myname2|MYNAME2|7
5) myint2|MYINT2|6
6) myset2|MYSET2|6
7) myset1|MYSET1|6
8) myint1|MYINT1|6

WHERE

Expires에서는 expires.key*와 같이 사용할 수 없습니다.
Where key = 'key1' or key glob 'key*'와 같이 사용하세요.

Example

명령>select * from expires.* where key <= 'myint2';   opcode
결과> 0) key|ttl
1) myint2|86200
2) myint1|86100
명령>select * from expires.* where key > 'myint2';   opcode
결과> 0) key|ttl
1) myname1|86500
2) mylist1|86300
3) mylist2|86400
4) myname2|86600
5) myset2|86800
6) myset1|86700
명령>select * from expires.* where key = 'myint2';   opcode
결과> 0) key|ttl
1) myint2|86200
명령>select * from expires.* where key != 'myint2';   opcode
결과> 0) key|ttl
1) myname1|86500
2) mylist1|86300
3) mylist2|86400
4) myname2|86600
5) myset2|86800
6) myset1|86700
7) myint1|86100

GLOB, LIKE

  • Glob는 와일드카드(wildcard)로 '*'를 사용하고, 대소문자를 구분합니다.
  • Like는 '%'를 사용하고 대소문자 구분없이 비교합니다.

Example

명령>select * from expires.* where key glob 'myset*';   opcode
결과> 0) key|ttl
1) myset2|86800
2) myset1|86700
명령>select * from expires.* where key like 'myset%';   opcode
결과> 0) key|ttl
1) myset2|86800
2) myset1|86700

BETWEEN, IN

  • Between, Not between 사용 가능합니다.
  • IN, Not in 사용할 수 있습니다.

Example

명령>select * from expires.* where key between 'mylist1' and 'myname2';   opcode
결과> 0) key|ttl
1) myname1|86500
2) mylist1|86300
3) mylist2|86400
4) myname2|86600
명령>select * from expires.* where key not between 'mylist1' and 'myname2';   opcode
결과> 0) key|ttl
1) myint2|86200
2) myset2|86800
3) myset1|86700
4) myint1|86100
명령>select * from expires.* where key in ('myset1','myset2');   opcode
결과> 0) key|ttl
1) myset2|86800
2) myset1|86700
명령>select * from expires.* where key not in ('myset1','myset2');   opcode
결과> 0) key|ttl
1) myname1|86500
2) mylist1|86300
3) mylist2|86400
4) myname2|86600
5) myint2|86200
6) myint1|86100

GROUP

Example

명령>select left(key,5), count(*) from expires.* group by left(key,5);   opcode
결과> 0) left(key,5)|count(*)
1) myint|2
2) mylis|2
3) mynam|2
4) myset|2
명령>select left(key,5), min(key), max(key) from expires.* group by left(key,5);   opcode
결과> 0) left(key,5)|min(key)|max(key)
1) myint|myint1|myint2
2) mylis|mylist1|mylist2
3) mynam|myname1|myname2
4) myset|myset1|myset2

REDIS FUNCTIONS

  • updatetime(): 키 생성/수정 일시를 리턴합니다.
  • type(): 키의 datatype을 리턴합니다.
  • encoding(): 키의 내부 datatype을 리턴합니다.
  • memory(): 키의 메모리 사용량(value 포함)을 리턴합니다.
  • 기타 여러 function을 사용할 수 있습니다.

Example

명령>select key, updatetime(key) from expires.*;   opcode
결과> 0) key|updatetime(key)
1) myname1|2022-04-07 18:01:13
2) mylist1|2022-04-07 18:01:13
3) mylist2|2022-04-07 18:01:13
4) myname2|2022-04-07 18:01:13
5) myint2|2022-04-07 18:01:13
6) myset2|2022-04-07 18:01:13
7) myset1|2022-04-07 18:01:13
8) myint1|2022-04-07 18:01:13
명령>select key, type(key), encoding(key) from expires.*;   opcode
결과> 0) key|type(key)|encoding(key)
1) myname1|hash|ziplist
2) mylist1|list|quicklist
3) mylist2|list|quicklist
4) myname2|hash|ziplist
5) myint2|string|int
6) myset2|set|intset
7) myset1|set|hashtable
8) myint1|string|int
명령>select key, type(key), encoding(key) from expires.* order by type(key), encoding(key);   opcode
결과> 0) key|type(key)|encoding(key)
1) myname1|hash|ziplist
2) myname2|hash|ziplist
3) mylist1|list|quicklist
4) mylist2|list|quicklist
5) myset1|set|hashtable
6) myset2|set|intset
7) myint2|string|int
8) myint1|string|int
명령>select key, memory(key) from expires.*;   opcode
결과> 0) key|memory(key)
1) myname1|122
2) mylist1|185
3) mylist2|158
4) myname2|125
5) myint2|56
6) myset2|74
7) myset1|408
8) myint1|56
명령>select key, memory(key) from expires.* order by memory(key);   opcode
결과> 0) key|memory(key)
1) myint2|56
2) myint1|56
3) myset2|74
4) myname1|122
5) myname2|125
6) mylist2|158
7) mylist1|185
8) myset1|408

TTLDATE()

  • TTLDATE(ttl): 만료 시각을 일시로 리턴합니다. 예) 2022-04-08 18:02:53
    ttl은 초로 표시되기 때문에 실제 멤버가 삭제될 일시를 환산해 보아야 하는 불편함이 있습니다. 그래서 ttldate() function을 제공합니다.

Example

명령>select key, ttl, ttldate(ttl) from expires.*;   opcode
결과> 0) key|ttl|ttldate(ttl)
1) myname1|86500|2022-04-08 18:02:53
2) mylist1|86300|2022-04-08 17:59:33
3) mylist2|86400|2022-04-08 18:01:13
4) myname2|86600|2022-04-08 18:04:33
5) myint2|86200|2022-04-08 17:57:53
6) myset2|86800|2022-04-08 18:07:53
7) myset1|86700|2022-04-08 18:06:13
8) myint1|86100|2022-04-08 17:56:13
명령>select key, ttl, ttldate(ttl) from expires.* where ttl > 0;   opcode
결과> 0) key|ttl|ttldate(ttl)
1) myname1|86500|2022-04-08 18:02:53
2) mylist1|86300|2022-04-08 17:59:33
3) mylist2|86400|2022-04-08 18:01:13
4) myname2|86600|2022-04-08 18:04:33
5) myint2|86200|2022-04-08 17:57:53
6) myset2|86800|2022-04-08 18:07:53
7) myset1|86700|2022-04-08 18:06:13
8) myint1|86100|2022-04-08 17:56:13

Expires 내부 구조

Expires는 Hash table이라고 하는 배열(array)에 저장됩니다. Hash table이라고 하는 이유는 hash 값으로 배열의 어느 위치에 할당되지 때문입니다. 따라서 일정한 순서가 없습니다.

만료 시간이 지난 키를 삭제하는 방법

  • 레디스 서버는 1초에 10번(100ms 마다) expires에 키가 있는지 검사합니다. Cycle 시작.
  • Expires(hash table)에 키가 있으면 하나씩 차례로 expire time이 현재 시각을 지났는지 확인합니다.
  • Expire time이 현재 시각을 지났으면 해당 키를 삭제하고 hash table에서도 삭제합니다.
  • 종료 조건 1(삭제 비율 기준): 검사한 개수에 비해서 삭제한 비율이 10% 이하면 종료한다.
  • 종료 조건 2(소요 시간 기준): 최대 25ms까지 사용한다.
  • 다음 cycle에서는 이번 cycle에서 검사한 이후 키부터 검사합니다.
  • 삭제할 key가 많을 경우 해당 시각이 지나도 삭제되지 않을 수 있기 때문에 키를 읽을 때마다 check해서 삭제한다.

동영상 설명

Redis SQL Select Expires


OPCODE


OPCODE는 SQL의 실행 계획(execution plan)입니다.

select count(*) from expires.*;

select count(key) from expires.*;

select * from expires.*;

select key, ttl from expires.*;

select key, ttl(key) from all.* where ttl(key) > 0;

select * from expires.* order by key;

select * from expires.* order by key desc;

select * from expires.* limit 5;

select * from expires.* order by key limit 5;

select * from expires.* order by key limit 3,4;

select min(key), max(key) from expires.*;

select key, upper(key), length(key) from expires.*;

select * from expires.* where key <= 'myint2';

select * from expires.* where key > 'myint2';

select * from expires.* where key = 'myint2';

select * from expires.* where key != 'myint2';

select * from expires.* where key between 'mylist1' and 'myname2';

select * from expires.* where key not between 'mylist1' and 'myname2';

select * from expires.* where key glob 'myset*';

select * from expires.* where key like 'myset%';

select * from expires.* where key in ('myset1','myset2');

select * from expires.* where key not in ('myset1','myset2');

select left(key,5), count(*) from expires.* group by left(key,5);

select left(key,5), min(key), max(key) from expires.* group by left(key,5);

select key, updatetime(key) from expires.*;

select key, type(key), encoding(key) from expires.*;

select key, type(key), encoding(key) from expires.* order by type(key), encoding(key);

select key, memory(key) from expires.*;

select key, memory(key) from expires.* order by memory(key);

select key, ttl, ttldate(ttl) from expires.*;

select key, ttl, ttldate(ttl) from expires.* where ttl > 0;


<< Select ALL Select Expires Select Expire Members >>

Email 답글이 올라오면 이메일로 알려드리겠습니다.