質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

4回答

3302閲覧

大量データの検索速度を上げる適切なチューニングについて

test_87097

総合スコア45

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2019/08/30 07:31

編集2019/08/30 08:17

いつもお世話になっております。
大量のデータ(1億とか)から1件のデータを検索する際に何かしら早く検索する方法はないのか知りたくて質問をさせて頂きます

SQL

1CREATE TABLE IF NOT EXISTS `serials` ( 2 `id` int(11) NOT NULL auto_increment, 3 `serial_code` char(12) BINARY NOT NULL, 4 PRIMARY KEY (`id`), 5 UNIQUE KEY `serial_code` (`serial_code`) 6) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

このテーブルにcsvデータの流し込みで1億件のデータがあるとします。
普通に

SQL

1SELECT * FROM `serials` where serial_code=1111111111111;

で検索すると検索に時間がかかってしまいます。explainで確認したところ

+----+-------------+---------+-------+---------------+------------+---------+------+----------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------+-------+---------------+------------+---------+------+----------+--------------------------+ | 1 | SIMPLE | serials | index | serial_code |serial_code | 36 | NULL | 40413015 | Using where; Using index | +----+-------------+---------+-------+---------------+------------+---------+------+----------+--------------------------+

typeがindexとなりフルスキャンではないですがやはり遅くはなってしまいます。
これをidで検索すると一瞬で表示され、typeもconstになります。

だいたい大量のデータから検索する場合はINDEXを貼るのが有効みたいな記事をよく見るのですが、numberをユニークキーに設定しているのでINDEXを貼っている認識ですが間違いないでしょうか?
また何か出来る設定でnumberの検索を早く出来る方法があればご教授頂きたいと思います。

なお、実際はPHPでシステムを組んでいて、シリアルナンバーをフォームで入力してそのシリアルがserialsテーブルとserial_registration_historiesテーブルに存在しているかどうかのチェックを行っています。ですので

SQL

1CREATE TABLE IF NOT EXISTS `serials` ( 2 `id` int(11) NOT NULL auto_increment, 3 `serial_code` char(12) BINARY NOT NULL, 4 PRIMARY KEY (`id`), 5 UNIQUE KEY `serial_code` (`serial_code`) 6) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 7 8CREATE TABLE IF NOT EXISTS `serial_registration_histories` ( 9 `id` int(11) NOT NULL auto_increment, 10 `serial_id` int(11) NOT NULL, 11 `created` datetime default NULL, 12 `modified` datetime default NULL, 13 PRIMARY KEY (`id`), 14 UNIQUE KEY `serial_id` (`serial_id`) 15) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

このテーブルにserialsテーブルにはデータを流し込み、serial_registration_historiesにはserialsテーブルには存在して

SELECT文

1`serial_registration_histories`にはないシリアル情報を格納するデータが存在しているのですが、この複数のテーブルに対して 2SELECT `Serial`.`id`, `SerialRegistrationHistory`.`id` FROM `テーブル名`.`serials` AS `Serial` LEFT JOIN `テーブル名`.`serial_registration_histories` AS `SerialRegistrationHistory` ON (`Serial`.`id` = `SerialRegistrationHistory`.`serial_id`) WHERE `Serial`.`serial_code` = '719653552612' LIMIT 1

このSQLを投げています。このSQLが遅くならなければいいのですが、これをexplainをつけると

+----+-------------+---------------------------+-------+---------------+------------+---------+-------+------+----------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------------------------+-------+---------------+------------+---------+-------+------+----------------------+ | 1 | SIMPLE | Serial | const | serial_code | serial_code| 36 | const | 1 | Using index | | 1 | SIMPLE | SerialRegistrationHistory | const | serial_id | serial_id | 4 | const | 0 | unique row not found | +----+-------------+---------------------------+-------+---------------+------------+---------+-------+------+----------------------+

このような結果になってtypeがconstになっているのでそこまで遅くならないとは思うのですが正直なんで単純なsqlはindexでこれがconstになっているのか不明です。

質問が多くなって申し訳ありませんが、よろしくお願いします

※修正点
命名が良くないと指摘を受けたので修正しました。(number→serial_code)
頂いた回答から上半分の単純なSELECT文の検索が遅いと言う点は型変換を行って検索を行っているので遅いというのがわかりましたので解決済みです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Orlofsky

2019/08/30 07:35

>`number` char(12) BINARY NOT NULL, 文字型のカラムに数値型のカラム名を付けるのは止めませんか?ネーミングのセンスがないし、コードを追う気が失せます。
test_87097

2019/08/30 07:43

確かに命名って大事ですよね。次回から気をつけます。不快にさせてしまったら申し訳ないです
Orlofsky

2019/08/30 07:56 編集

だから、 >SELECT * FROM serials where number=1111111111111; で型変換に気が付かない墓穴を掘っているんです。 今回から直すという選択肢もあります。
guest

回答4

0

ベストアンサー

型変換が入っているためにインデックスが正しく使えない、なんてことはないでしょうか。

試しにSELECT * FROM serials where number='1111111111111';と、文字列として検索してみてください。

投稿2019/08/30 07:39

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2019/08/30 07:41

実データの方は文字列で検索してconstになっているので、この線が有力な気もします。
test_87097

2019/08/30 07:42

ありがとうございます。完全にそのとおりでした。 上記のSELECT文でしたら一瞬で表示されました。
guest

0

serial_idがセカンダリだからじゃないでしょうか
serial_idは**UNIQUE **で NOT NULLなんだから、**PRIMARY KEY **にすれば、改善されないでしょうか。

SQL

1CREATE TABLE IF NOT EXISTS `serial_registration_histories` ( 2 `serial_id` int(11) NOT NULL, 3 `created` datetime default NULL, 4 `modified` datetime default NULL, 5 PRIMARY KEY (`serial_id`) 6)

投稿2019/08/30 08:48

sazi

総合スコア25173

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

シンプルに

SQL

1SELECT `S`.`id` 2 , `SRH`.`id` 3FROM `serials` AS `S` 4LEFT JOIN `serial_registration_histories` AS `SRH` 5ON `S`.`id` = `SRH`.`serial_id` 6WHERE `S`.`serial_code` = '719653552612' LIMIT 1

投稿2019/08/30 08:29

Orlofsky

総合スコア16415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

知って得するInnoDBセカンダリインデックス活用術!を見るとプライマリキーと他のインデックスとの違いが分かると思います。

・・・ってか、numberって文字列だったんかーーーいっ!
同じ数値でも、「数値として」と「文字列として」の長さが違うので、検索が遅くなるのは当たり前です。

投稿2019/08/30 07:42

yoorwm

総合スコア1305

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

test_87097

2019/08/30 07:50

参考サイトありがとうございます。 すいません、上記の単純なSQLに関しては単純なミスで恥ずかしいです… numberが文字列もおかしいので今後気をつけます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問