2011-01-18 2 views
1

MySQL에서이 테이블에 대해 어떤 종류의 PK를 선택해야하는지 궁금합니다. 거의 모든 SELECT 연산에는 DATETIME (날짜 범위, 특정 날짜 등)이 포함됩니다.DATETIME col이 거의 모든 SELECT 작업에 사용되는 테이블의 기본 키

모범 사례가 있습니까?

+0

MyISAM 또는 InnoDB? 기본 키는 선택과 어떤 관련이 있습니까? 아니면 클러스터 된 인덱스를 의미합니까? –

+0

테이블에서 어떤 열이 고유합니까? 현명한 키 선택은 데이터와 비즈니스 규칙에 대한 분석과 이해를 기반으로해야합니다. – sqlvogel

답변

4

DATETIME이 (가) 귀하의 PK가되지는 않을 것이지만 해당 열에 대해서는 반드시 create an index이어야합니다.

+0

예, 해당'col'에 INDEX를 만들었습니다. –

0

안전 측면을 위해 자동 번호를 선택하십시오. 동일한 날짜 시간을 가진 두 개 이상의 행을 가질 수 있습니다.

1

특히 innodb를 사용하고 클러스터 된 기본 키 인덱스를 활용하여 최대 읽기 성능을 얻으려면 복합 기본 키의 일부를 형성하는 데 날짜를 사용하는 것이 좋습니다. 주의하는 것이

http://dev.mysql.com/doc/refman/5.0/en/innodb-index-types.html

http://www.xaprb.com/blog/2006/07/04/how-to-exploit-mysql-index-optimizations/

MySQL의 스크립트

것들 :

  • INNO을

    는 다음에 봐 db는 auto_increment 복합 기본 키를 지원하지 않으므로 시퀀스 테이블을 사용합니다.

  • 기본 키의 auto_increment 부분은 고유성을 보장하는 데 도움이됩니다. 키의 바깥 부분은 중요한 부분 즉 날짜입니다. 여기

전체 스크립트를 http://pastie.org/1475625 또는 계속 읽고 ...

drop table if exists foo_seq; 
create table foo_seq 
(
next_val int unsigned not null default 0 
) 
engine = innodb; 

insert into foo_seq values (0); 

drop table if exists foo; 
create table foo 
(
foo_date datetime not null, 
foo_id int unsigned not null, -- auto inc field which just guarantees uniqueness 
primary key (foo_date, foo_id) -- clustered composite PK (innodb only) 
) 
engine=innodb; 

delimiter # 
create trigger foo_before_ins_trig before insert on foo 
for each row 
begin 
declare v_id int unsigned default 0; 
    select next_val+1 into v_id from foo_seq; 
    set new.foo_id = v_id; 
    update foo_seq set next_val = v_id; 
end# 

delimiter ; 

통계 :

select count(*) as counter from foo; -- count(*) under innodb always slow 
+---------+ 
| counter | 
+---------+ 
| 2000000 | 
+---------+ 

select min(foo_date) as min_foo_date from foo; 
+---------------------+ 
| min_foo_date  | 
+---------------------+ 
| 1782-11-21 16:32:00 | 
+---------------------+ 
1 row in set (0.00 sec) 

select max(foo_date) as max_foo_date from foo; 
+---------------------+ 
| max_foo_date  | 
+---------------------+ 
| 2011-01-18 23:06:04 | 
+---------------------+ 
1 row in set (0.00 sec) 


select count(*) as counter from foo where foo_date between 
    '2009-01-01 00:00:00' and '2011-01-01 00:00:00'; 

+---------+ 
| counter | 
+---------+ 
| 17520 | 
+---------+ 
1 row in set (0.01 sec) 

select * from foo where foo_date between 
    '2009-01-01 00:00:00' and '2011-01-01 00:00:00' order by 1 desc limit 10; 

+---------------------+--------+ 
| foo_date   | foo_id | 
+---------------------+--------+ 
| 2010-12-31 23:06:04 | 433 | 
| 2010-12-31 22:06:04 | 434 | 
| 2010-12-31 21:06:04 | 435 | 
| 2010-12-31 20:06:04 | 436 | 
| 2010-12-31 19:06:04 | 437 | 
| 2010-12-31 18:06:04 | 438 | 
| 2010-12-31 17:06:04 | 439 | 
| 2010-12-31 16:06:04 | 440 | 
| 2010-12-31 15:06:04 | 441 | 
| 2010-12-31 14:06:04 | 442 | 
+---------------------+--------+ 
10 rows in set (0.00 sec) 

explain 
select * from foo where foo_date between 
    '2009-01-01 00:00:00' and '2011-01-01 00:00:00' order by 1 desc limit 10; 
+----+-------------+-------+-------+---------------+---------+---------+------+-------+--------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref |rows | Extra     | 
+----+-------------+-------+-------+---------------+---------+---------+------+-------+--------------------------+ 
| 1 | SIMPLE  | foo | range | PRIMARY  | PRIMARY | 8  | NULL |35308 | Using where; Using index | 
+----+-------------+-------+-------+---------------+---------+---------+------+-------+--------------------------+ 
1 row in set (0.00 sec) 

예쁜 확대됨가 200 만 개 행이 고려 ...

희망이 있습니다.

+0

클러스터 된 인덱스를 기본 키로 사용하는 데 따른 제한 사항을 관리하므로 좋은 솔루션입니다. 클러스터 된 인덱스는 범위 쿼리에 유용합니다. –

관련 문제