私は、次の表を持っている:このクエリを自己結合で最適化するにはどうすればよいですか?
CREATE TABLE lab_data (
id int(11) NOT NULL,
patient_sid int(11) DEFAULT NULL,
double_value double DEFAULT NULL,
string_value varchar(7) DEFAULT NULL,
data_type_id int(11) DEFAULT NULL,
event_date datetime DEFAULT NULL,
attribute_id int(11) DEFAULT NULL,
lft int(11) DEFAULT NULL,
rgt int(11) DEFAULT NULL,
parent int(11) DEFAULT NULL,
num_children int(11) DEFAULT NULL,
PRIMARY KEY (id),
KEY idx_bucket (attribute_id,string_value),
KEY idx_test (attribute_id,double_value,event_date,patient_id,lft,rgt)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
は、これは非常に大きなテーブル(12万行)であり、私は本当に、次の自己結合クエリを最適化する必要があります。
SELECT distinct(patient_sid) as patient_sid
FROM lab_data l1
LEFT JOIN (SELECT patient_sid, lft, rgt
FROM lab_data
WHERE attribute_id = 36 AND double_value >= 1.2 AND event_date >= '1776-01-01'
) AS l2
ON l1. patient_sid = l2.patient_sid AND l1.lft >= l2.lft AND l1.rgt <= l2.rgt
WHERE l1.attribute_id = 33 AND l1.string_value = '2160-0'
(私が持っていますの範囲検索を外側のwhere節に移動しようとしましたが、大きな違いは見られませんでした。)
idx_bucketは外部クエリに正しく使用されていますが、idx_testは内部サブクエリwh EXPLAINクエリプランを実行します。代わりに、idx_bucketも使用しています。
# id, select_type, table, partitions, type, possible_keys, key, key_len, ref, rows, filtered, Extra
'1', 'SIMPLE', 'l1', NULL, 'ref', 'idx_bucket,idx_test', 'idx_bucket', '29', 'const,const', '517298', '100.00', 'Using temporary'
'1', 'SIMPLE', 'lab_data', NULL, 'ref', 'idx_bucket,idx_test', 'idx_bucket', '5', 'const', '13657', '100.00', 'Using where; Distinct'
私はidx_test使用する内部サブクエリを強制する場合、私は次のクエリプランを取得する:
# id, select_type, table, partitions, type, possible_keys, key, key_len, ref, rows, filtered, Extra
'1', 'SIMPLE', 'l1', NULL, 'ref', 'idx_bucket,idx_test', 'idx_bucket', '29', 'const,const', '517298', '100.00', 'Using temporary'
'1', 'SIMPLE', 'lab_data', NULL, 'ref', 'idx_test', 'idx_test', '5', 'const', '21808', '100.00', 'Using where; Distinct'
とJSON出力から、私はこのインデックスを使用used_key_parts
下attribute_id
を参照してください? MySQLのドキュメント(B-Tree Index Characteristics)によれば、btreeインデックスは、 "Bツリーインデックスは、=、>、> =、<、< =、またはBETWEEN演算子を使用する式の列比較に使用できます。
"table": {
"table_name": "lab_data",
"access_type": "ref",
"possible_keys": [
"idx_test"
],
"key": "idx_test",
"used_key_parts": [
"attribute_id"
],
"key_length": "5",
"ref": [
"const"
],
"rows_examined_per_scan": 8898041,
"rows_produced_per_join": 988473,
"filtered": "11.11",
"index_condition": "((`ns_large2_2016`.`lab_data`.`double_value` >= 1.2) and (`ns_large2_2016`.`lab_data`.`event_date` >= '1776-01-01'))",
"cost_info": {
"read_cost": "339069.00",
"eval_cost": "197694.69",
"prefix_cost": "2118677.20",
"data_read_per_join": "82M"
},
"used_columns": [
"patient_sid",
"double_value",
"event_date",
"attribute_id",
"lft",
"rgt"
]
私は何を誤解していますかused_key_parts
ですか?私はこれらが使用されているインデックスの列であると仮定しています。 Bツリー索引のドキュメントでは、範囲の比較を含める必要があると私は考えています。
何ですか?なぜ私はそれを掲示するとすぐにdownvotedされましたか?私の質問にはあいまいさやあいまいさがありませんか?オイ! –
理由はわかりませんが、クエリ形式を改善することができますが、多くのpplがjsonのexplain planを読むことはできません。 –
フィードバックを歓迎します。時々、ここで何が起きているのか不思議です! (私は質問を受けて、説明計画に取り組んでいます...) –