• ベストアンサー
  • 困ってます

mysqlのインデックスについて質問です。

mysqlのインデックスについて質問です。 http://archiva.jp/web/server-side/sql_02.html に、 『mysqlでは1つのクエリ実行で、1つのテーブルにつき1つのインデックスしか使用できない』 とあります。 よく以下のようなテーブル定義を見かけますが、 CREATE TABLE IF NOT EXISTS `data` ( `id` int(10) NOT NULL default '0', `user_id` int(10) NOT NULL default '0', `file_id` int(10) NOT NULL default '0', `name` text collate utf8_unicode_ci NOT NULL default '', PRIMARY KEY (`id`), KEY `user_id` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; idとuser_idを条件にするクエリであれば、上記制約を満たすため、 KEY `id_user_id_idx` (`id`,`user_id`) の複合クエリを定義すれば良いのでしょうか? また、idとuser_idとfile_idを条件にするクエリも考慮に入れた場合、 テーブル定義は以下のようにするのでしょうか? CREATE TABLE IF NOT EXISTS `data` ( `id` int(10) NOT NULL default '0', `user_id` int(10) NOT NULL default '0', `file_id` int(10) NOT NULL default '0', `name` text collate utf8_unicode_ci NOT NULL default '', PRIMARY KEY (`id`), KEY `user_id` (`user_id`), KEY `id_user_id_idx` (`id`,`user_id`), KEY `id_user_id_file_id_idx` (`id`,`user_id`,`file_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 最後に、create table 時のインデックスの指定は、 INDEX `user_id` (`user_id`), のようにもできますが、INDEXとKEYの違いは何かあるのでしょうか。

共感・応援の気持ちを伝えよう!

  • 回答数1
  • 閲覧数2254
  • ありがとう数5

質問者が選んだベストアンサー

  • ベストアンサー
  • 回答No.1
  • spieder
  • ベストアンサー率59% (13/22)

古いMySQLなら"1つのクエリで1テーブルにつき1インデックスしか使われない"というのは正しいです。しかし、新しいMySQL(ver.5.0以降)ならインデックスマージが行われるので、もし複数のIndexが使えるとオプティマイザが判断をした場合には、複数のインデックスが使われます。 ただ、例で挙がられた"idとuser_idを条件にするクエリ"の場合、PRIMARY KEYであるidカラムで1行のみに絞り込めます。わざわざ複数のIndexを使わずに、PRIMARY KEYを使って対象の1行を取り出してから"指定されたuser_idと一致するかどうか判断する"という最適化をオプティマイザが判断してしまうとuser_idのインデックスは利用されません。 また、検索条件に完全に一致したインデックスが無くても、対象行の絞込みが行える場合には、オプティマイザはインデックスを利用して対象行の絞込みを行ないます。インデックスで絞り込んだ中から条件に一致した結果を返すので、インデックスだけで絞り込んだ場合より多少遅くなりますが、まったくインデックスが無かった場合より早く結果を返せます。 また、複合カラムインデックスは、初めのカラムだけが条件に指定された場合でも有効に活用されますので、検索条件次第ですが、同じカラムの並びでインデックスを複数作成する必要はありません。 http://dev.mysql.com/doc/refman/5.1/ja/mysql-indexes.html インデックスを大量に作成すると更新時の処理が重くなるので、更新と参照のバランスを考えて必要なインデックスを作成してください。 "INDEXとKEYの違いは?"については、同じINDEX作成用の定義文なので、好みにあわせて好きなほうを使ってもらってかまいません。

参考URL:
http://dev.mysql.com/doc/refman/5.1/ja/index-merge-optimization.html

共感・感謝の気持ちを伝えよう!

関連するQ&A

  • usersテーブルの構成カラムについて

    MySQLバージョン4.1.16を使用しています。 このジャンルでお願いします。 よく全ての基本となるusersテーブル(IDとパスワードを入れるユーザの基本テーブル) があると思うのですが、それを構成するカラムはどのような感じにするのが良いのでしょうか? 自分は、 CREATE TABLE `users` ( `user_id` varchar(16), `password` varchar(255) default NULL, `col1` varchar(255) NOT NULL, `col2` varchar(255) NOT NULL, PRIMARY KEY (`user_id`), ) ENGINE=InnoDB; このように代替キー(連番)を使わずにuser_idを主キー(unique)にして構成します。 理由としては、uniqueな列があるなら、わざわざ連番を割り当てる必要もないし、 他のテーブルがuser_idを外部キーとして持った時に、その表の外部キーの列が 数字であるよりも見やすいかなと思ったからです。 ただ一般的に出まわっているPHPフレームワークなどのテーブル構成ではusersテーブルというか ほとんどのテーブルに連番を使っている例があります。 次のusersテーブルは、PHPフレームワークのCakePHPで使われるusersテーブルの構成の例で、 連番を使用しています。 CREATE TABLE `users` ( `id` int(11) NOT NULL auto_increment, `username` varchar(255) collate utf8_unicode_ci default NULL, `password` varchar(255) collate utf8_unicode_ci default NULL, `group_id` int(11) NOT NULL, `disabled` tinyint(1) NOT NULL, `created` datetime default NULL, `modified` datetime default NULL, PRIMARY KEY (`id`), KEY `group_id` (`group_id`), KEY `disabled` (`disabled`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 使用状況によって、どちらが良い悪いというのは変わるのでしょうけど 基本的にusersテーブルというのはどのような構成にすべきなのでしょうか? ちなみに自分は連番は○○_seqというカラム名にしてます(ただこれも 一般的には○○idを連番にしてるケースが多いので、どうすべきか迷っています・・・)

    • ベストアンサー
    • MySQL
  • tableをつくれない

    CREATE TABLE `db31_dev`.`db31_dev` ( `keyword_id` SERIAL NOT NULL , `bc_guid` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `bc_wbs` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `keyword_h1_url` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `keyword_wording_in_bc` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `keywords` VARCHAR( 511 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `description` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `last_modified` DATETIME NOT NULL , `changefreq` VARCHAR( 15 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `pri` INT( 5 ) NOT NULL , `noLocalNavi` BOOLEAN NOT NULL , PRIMARY KEY ( `keyword_id` ) , UNIQUE ( `bc_guid` , `bc_wbs` , `keyword_h1_url` , `keywords` , `description` ) ) ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci; とphpmyadminでうったら(正確にはテキストボックスに入力) priの部分がエラーと言われて、 MySQLのメッセージ: ドキュメント #1071 - Specified key was too long; max key length is 767 bytes だそうです。 どうすればいいのでしょうか? よろしくお願い申し上げます。

    • ベストアンサー
    • MySQL
  • create時にFOREIGN KEYでエラー

    以下のSQL文を実行すると CREATE TABLE if not exists table_A ( id int(11) not null auto_increment, company_id int(11) not null, created_at datetime NOT NULL, updated_at timestamp NOT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; CREATE TABLE if not exists table_B ( id int(11) not null auto_increment, from_id int(11) not null, company_id int(11) not null, created_at datetime NOT NULL, updated_at timestamp NOT NULL, PRIMARY KEY (id) FOREIGN KEY (from_id) REFERENCES table_A(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 上記を実行すると以下のエラーがでます。 #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FOREIGN KEY (from_id) REFERENCES table_A(id) ON DELETE CASCADE ) ENGINE=Inn' at line 8 解決方法をご存知の方はご教示頂けますと幸いです。 宜しくお願いいたします。

    • ベストアンサー
    • MySQL
  • MySQL SELECTの指定について

    まず、御覧頂きありがとうございます。 早速質問なのですが、 CREATE TABLE `hoge` ( `id` int(8) NOT NULL, `name` varchar(30) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `hoge` (`id`, `name`) VALUES (1, 'hogeA'), (2, 'hogeB'), (3, 'hogeC'), (4, 'hogeD'); CREATE TABLE `test` ( `id` int(8) NOT NULL, `name` varchar(30) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `test` (`id`, `name`) VALUES (1, 'testA'), (4, 'testD'); という値が入ってるテーブルがあるとします。(長くなってすみません) で、 hoge.id と test.id が重複した場合 test.name を表示させたいです。 期待値としては id,name 1.testA 2,hogeB 3,hogeC 4,testD になります。 業務でJoinを使うようなテーブル構造にそもそもしないというのもあり、クリティカルなSQLコードに不慣れで御知恵を借りたく質問させて頂きました。 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • 2つのテーブルからデータ取得

    いつもお世話になっております。 以下のようなテーブルがあります。 ---------- CREATE TABLE IF NOT EXISTS `students` ( `id` int(11) NOT NULL AUTO_INCREMENT, `student_number` bigint(20) DEFAULT NULL, `name` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, PRIMARY KEY (`id`) ) ---------- CREATE TABLE IF NOT EXISTS `student_upload` ( `student_number` bigint(20) NOT NULL, `upload_id` int(11) NOT NULL ) ---------- データは以下のように登録されています。 students ---------- id|student_number|name 1 |11111     |いちろう 2 |22222     |じろう 3 |33333     |さぶろう student_upload ---------- student_number|upload_id 11111     |1 11111     |2 22222     |1 22222     |2 ---------- student_upload.upload_id=1 のデータを取得したいので 下記のようなSQL文を発行しているのですが、student_upload.upload_id=2 の データも取得されてしまいます。 select * from students s, student_upload up where up.upload_id=1 and up.student_number=s.student_number よろしくご教示お願いいたします。 <環境>  PHP:5.3.5  MySQL:5.0.7

    • ベストアンサー
    • MySQL
  • Data too long for column 'id' at row 1とエラー

    MySQLを3.27から2.0に変えたのですが、 Data too long for column 'id' at row 1 というエラーが表示されて困っています。 エラー 実行した SQL: ALTER TABLE `account` CHANGE `id` `id` VARCHAR( 3 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL , CHANGE `pass` `pass` VARCHAR( 3 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL , CHANGE `mail` `mail` VARCHAR( 16 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL , CHANGE `name` `name` VARCHAR( 6 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL , CHANGE `host` `host` VARCHAR( 10 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL MySQLのメッセージ: #1406 - Data too long for column 'id' at row 1 いきなりでどう対処していいか困っています。 どこを変更すればよいのでしょうか・・・?

  • postgres table作成時にindex付与

    MySQLでは以下のようにテーブル作成時にインデックス付与ができます。 CREATE TABLE test ( a int(11) NOT NULL DEFAULT '0', b int(11) DEFAULT NULL, PRIMARY KEY (a), KEY test_idx (b), -- ★インデックス その1 KEY test_idx2 (a) -- ★インデックス その2 ); ポスグレではできませんか?

  • PHPとMysqlを使用した集計表の作り方

    --------------媒体-------------- CREATE TABLE IF NOT EXISTS `media` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; INSERT INTO `media` (`id`, `name`) VALUES (1, 'yahoo'), (2, '楽天'), (3, '電話'), (4, 'メール'), (5, 'その他'); --------------店舗-------------- CREATE TABLE IF NOT EXISTS `shop` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; INSERT INTO `shop` (`id`, `name`) VALUES (1, '新宿'), (2, '池袋'), (3, '渋谷'), (4, '博多'), (5, '梅田'); --------------来客数-------------- CREATE TABLE IF NOT EXISTS `raikyakusuu` ( `id` int(11) NOT NULL AUTO_INCREMENT, `date` date DEFAULT NULL, `shop_id` int(2) DEFAULT NULL, `media_id` int(2) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8; INSERT INTO `raikyakusuu` (`id`, `date`, `shop_id`, `media_id`) VALUES (1, '2013-11-01', 1, 1), (2, '2013-11-01', 1, 1), (3, '2013-11-01', 1, 2), (4, '2013-11-01', 4, 4), (5, '2013-11-01', 1, 2), (6, '2013-11-02', 3, 1), (8, '2013-11-02', 3, 4), (9, '2013-11-02', 2, 2), (10, '2013-11-02', 2, 4), (11, '2013-11-03', 1, 4), (12, '2013-11-03', 3, 1), (13, '2013-11-05', 4, 3), (14, '2013-11-05', 1, 3), (15, '2013-11-06', 2, 2), (16, '2013-11-06', 3, 3), (17, '2013-11-06', 1, 5); select DATE_FORMAT(r.`date`,'%d日') as DayTime, count(*) as cnt, s.`name` as s_name, m.`name` as m_name from raikyakusuu r LEFT JOIN shop s ON s.`id` = r.`shop_id` LEFT JOIN media m ON m.`id` = r.`media_id` WHERE DATE_FORMAT(r.`date`, '%Y-%m') = '2013-11' GROUP BY DayTime, m.`name` 上記のセレクト文で取れた結果をPHPにて 新宿 媒体 |01日|02日|03日|04日|05日|06日|07日|08日|・・・ yahoo | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 楽天 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 電話 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | メール | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | その他 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 池袋 媒体 |01日|02日|03日|04日|05日|06日|07日|08日|・・・ yahoo | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 楽天 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 電話 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | メール | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | その他 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 渋谷 媒体 |01日|02日|03日|04日|05日|06日|07日|08日|・・・ yahoo | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 楽天 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 電話 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | メール | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | その他 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | といったようにtableにて表示を考えておりますが、 うまくだせずに困っております。 条件といたしましては、 結果で取れていない媒体、日付も表示させ、cntには0と表示させたいです。 お分かりの方がいらっしゃいましたらご教示お願いいたします。 端折らせていただいている部分も御座いますが、宜しくお願いいたします。

    • ベストアンサー
    • PHP
  • データベースのインポートができません(MySQL)

    ●質問の主旨 下記のサイトを見ながら、データベースのテーブルを インポートしようとしていますが、エラーが出ます。 この場合、phpmyadminのどこを確認すればよいでしょうか? ご存知の方、ご教示願います。 http://www.dbonline.jp/phpmyadmin/export-import/index3.html ●開発環境 windows8 xammp1.8.1 ●エラーの内容(添付画像) エラー 実行した SQL: -- -- データベース: `mydb10` -- CREATE DATABASE `mydb10` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; MySQL のメッセージ: #1007 - Can't create database 'mydb10'; database exists ●インポートの内容(mydb.sql) -- phpMyAdmin SQL Dump -- version 3.5.2.2 -- http://www.phpmyadmin.net -- -- ホスト: 127.0.0.1 -- 生成日時: 2013 年 4 月 20 日 08:27 -- サーバのバージョン: 5.5.27 -- PHP のバージョン: 5.4.7 SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; SET time_zone = "+00:00"; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; -- -- データベース: `mydb10` -- CREATE DATABASE `mydb10` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; USE `mydb10`; -- -------------------------------------------------------- -- -- テーブルの構造 `db10` -- CREATE TABLE IF NOT EXISTS `db10` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` text NOT NULL, `address` text NOT NULL, `tel` text NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ; -- -- テーブルのデータのダンプ `db10` -- INSERT INTO `db10` (`id`, `name`, `address`, `tel`) VALUES (1, 'あああ', 'いいい', '111'), (2, 'ううう', 'えええ', '222'), (3, 'おおお', 'かかか', '333'); /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

    • ベストアンサー
    • MySQL
  • MySQLのテーブル設計で迷っています(桁数)

    MySQLのテーブル設計で迷っています。 クリエイト文のカッコの中は桁数を表しているのでしょうか?それともバイト数でしょうか?桁数であれば、それぞれの型で何桁まで設定できますでしょうか? int型のnoを18桁に変更したいのですが、調べているうちに迷ってしまいました。 型 バイト 最小値 最大値 TINYINT 1 -128 127 SMALLINT 2 -32768 32767 MEDIUMINT 3 -8388608 8388607 INT 4 -2147483648 2147483647 BIGINT 8 -9223372036854775808 9223372036854775807 CREATE TABLE `user` ( `no` int(8) unsigned NOT NULL auto_increment, `id` varchar(24) NOT NULL default '', `email` varchar(255) NOT NULL default '', `reg_date` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`no`) ) TYPE=MyISAM;

    • ベストアンサー
    • MySQL