1

DB 内のユーザーのリストを表示するクエリに速度の問題があります。交通情報を含むユーザーのリストと、そのユーザーと一緒に働いた最後の従業員を表示したいと考えています。

DB は次のようになります。

users テーブル (ユーザー情報を含む):

CREATE TABLE `users` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `ip` tinytext NOT NULL,
 `name` varchar(64) NOT NULL,

... some other fields

 PRIMARY KEY (`id`),
 UNIQUE KEY `name` (`name`),
 KEY `ip` (`ip`(15)) USING BTREE,
)

users_trf テーブル (ユーザーのトラフィックに関する情報が含まれています。uid - users テーブルからのユーザーの ID):

CREATE TABLE `users_trf` (
 `uid` int(11) unsigned NOT NULL,
 `uip` varchar(15) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
 `in` bigint(20) NOT NULL DEFAULT '0',
 `out` bigint(20) NOT NULL DEFAULT '0',
 `test` tinyint(4) NOT NULL,
 UNIQUE KEY `uid` (`uid`),
 KEY `test` (`test`)
)

すべての従業員のリストを持つ従業員:

CREATE TABLE `employees` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `full_name` varchar(16) NOT NULL,
 PRIMARY KEY (`id`)
)

そして、従業員がクライアントで行ったジョブに関するデータを保存するログテーブル (uid - users テーブルからのクライアントの ID、mid - 従業員テーブルからの従業員の ID):

CREATE TABLE `employees_log` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `uid` int(10) unsigned NOT NULL,
 `mid` int(10) unsigned NOT NULL,
 `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 `note` text NOT NULL,
 PRIMARY KEY (`id`)
)

私のクエリ:

SELECT SQL_CALC_FOUND_ROWS *
FROM users u
LEFT JOIN users_trf t ON u.id = t.uid
LEFT JOIN (

SELECT e2.full_name, e1.uid, e1.mid AS moid
FROM employees_log e1
LEFT JOIN employees e2 ON e1.mid = e2.id
WHERE NOT
EXISTS (

SELECT *
FROM employees_log e3
WHERE e1.uid = e3.uid
AND e1.id < e3.id
)
) e ON e.uid = u.id
LIMIT 0 , 50

動作が非常に遅いです。これの理由はこのサブクエリだと思います (クライアントと一緒に働いた最後の従業員を選択しようとしています):

SELECT e2.full_name, e1.uid, e1.mid AS moid
FROM employees_log e1
LEFT JOIN employees e2 ON e1.mid = e2.id
WHERE NOT
EXISTS (

SELECT *
FROM employees_log e3
WHERE e1.uid = e3.uid
AND e1.id < e3.id
)

クエリを高速化することはできますか?

UPD: インデックスを追加するALTER TABLE employees_log ADD INDEX ( uid, id );とクエリが 2 倍速くなりましたが、もっと速くすることはできますか?

+----+--------------------+------------+--------+---------------+---------+---------+-------------+-------+--------------------------+
| id | select_type        | table      | type   | possible_keys | key     | key_len | ref         | rows  | Extra                    |
+----+--------------------+------------+--------+---------------+---------+---------+-------------+-------+--------------------------+
|  1 | PRIMARY            | u          | ALL    | NULL          | NULL    | NULL    | NULL        | 12029 |                          |
|  1 | PRIMARY            | t          | eq_ref | uid           | uid     | 4       | bill.u.id   |     1 |                          |
|  1 | PRIMARY            | <derived2> | ALL    | NULL          | NULL    | NULL    | NULL        |  2239 |                          |
|  2 | DERIVED            | e1         | ALL    | NULL          | NULL    | NULL    | NULL        |  2288 | Using where              |
|  2 | DERIVED            | e2         | eq_ref | PRIMARY       | PRIMARY | 4       | bill.e1.mid |     1 |                          |
|  3 | DEPENDENT SUBQUERY | e3         | ref    | PRIMARY,uid   | uid     | 4       | bill.e1.uid |     1 | Using where; Using index |
+----+--------------------+------------+--------+---------------+---------+---------+-------------+-------+--------------------------+
4

4 に答える 4

1

新しい MySQL テーブルを作成する場合は、INDEX 用語を使用してインデックスを作成する列を指定できます。インデックスは、パフォーマンスを向上させるために MySQL テーブルで有効にできる特別なものです http://www.databasejournal.com/features/mysql/ article.php/1382791/Optimizing-MySQL-Queries-and-Indexes.htm
http://www.tutorialspoint.com/mysql/mysql-indexes.htmこれを見ると、多くのアイデアが得られます..

于 2013-08-30T09:34:35.383 に答える
0

employees_log の MID 列と UID 列にインデックスを追加することを検討してください。説明では、この結合がインデックスを使用していないことが示唆されています。

そのように:employees_log(mid、uid)にインデックスコンパウンドを作成します

于 2013-08-30T15:16:17.637 に答える
0

(少なくともキーに基づいて) ログ テーブル内のそのユーザーの最後の従業員のログに参加しようとするという目標がある場合は、単に ? の= <subquery>代わりにNOT EXISTS?を試してみてください。

SELECT e2.full_name, e1.uid, e1.mid AS moid
FROM employees_log e1
LEFT JOIN employees e2 ON e1.mid = e2.id
WHERE e1.id = (
  SELECT MAX(e3.id)
  FROM employees_log e3
  WHERE e1.uid = e3.uid
)
于 2013-08-30T09:35:05.383 に答える