2011-01-18 4 views
1

MySQLのこのテーブルでは、どのような種類のPKを選択する必要があるのでしょうか。ほとんどすべてのSELECT操作にはDATETIME(日付範囲、特定の日付など)が含まれます。DATETIME colがほぼすべてのSELECT操作で使用されるテーブルのプライマリキー

これにはベストプラクティスがありますか?

+0

MyISAMまたはInnoDB?プライマリキーとセレクトとは何が関係していますか?または、クラスタ化インデックスを意味しますか? –

+0

あなたのテーブルで一意のカラムはありますか?感覚的なキーの選択は、データとビジネスルールの分析と理解に基づいて行う必要があります。 – sqlvogel

答えて

4

私はDATETIMEがあなたのPKであることはお勧めしませんが、確かにその列にcreate an indexを置くべきです。

+0

はい、私はその 'col'でINDEXを作成しました。 –

0

安全面を確保するために自動番号を選択してください。同じ日時の2つ以上の行を持つことができます。

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) 

かなりパフォーマンスの高い2万行がある考慮...

ほしいと思っています。

+0

これは、クラスタード・インデックスを主キーにすることの制限を管理する優れた解決策です。クラスタ化されたインデックスは、範囲クエリに最適です。 –

関連する問題