select_expires
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
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 >> |
---|