tableA
有大约2.5亿行,如:
A_id thing_id thing
---- -------- -----
001 345 foo
002 567 bar
003 678 poo
004 789 gar
和
tableB
有大约5000万行,如:
B_id thing_id user_id action
---- -------- ------- -----
001 123 001 some
002 234 002 thing
003 345 001 dont
004 567 002 matter
现在: thing_id
一次只能tableB
次
稍后:我需要能够在thing_id
user_id
中拥有多个tableB
现在:从thing_id
中选择tableA
tableB
稍后:从thing_id
中tableA
选择一个tableB
<{1}}
自学SQL,我无法找到一种方法来有效地使用非常大的表。也许我只是没有索引吗?我一直在测试MariaDB是否有所作为。
**
**
/*Table: TEST_tableA*/
----------------------
/*Column Information*/
----------------------
Field Type Collation Null Key Default Extra Privileges Comment
--------- ----------- ----------- ------ ------ ------- -------------- ------------------------------- ---------
tableA_id int(11) (NULL) NO PRI (NULL) auto_increment select,insert,update,references
thing_id int(11) (NULL) YES UNI (NULL) select,insert,update,references
thing varchar(32) utf8mb4_bin YES MUL (NULL) select,insert,update,references
/*Index Information*/
---------------------
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
----------- ---------- -------- ------------ ----------- --------- ----------- -------- ------ ------ ---------- ------- ---------------
TEST_tableA 0 PRIMARY 1 tableA_id A 97561 (NULL) (NULL) BTREE
TEST_tableA 0 thing_id 1 thing_id A 97561 (NULL) (NULL) YES BTREE
TEST_tableA 1 thing 1 thing A 97561 (NULL) (NULL) YES BTREE
/*DDL Information*/
-------------------
CREATE TABLE `TEST_tableA` (
`tableA_id` int(11) NOT NULL AUTO_INCREMENT,
`thing_id` int(11) DEFAULT NULL,
`thing` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`tableA_id`),
UNIQUE KEY `thing_id` (`thing_id`),
KEY `thing` (`thing`)
) ENGINE=InnoDB AUTO_INCREMENT=2050005 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
/*Column Information*/
----------------------
Field Type Collation Null Key Default Extra Privileges Comment
--------- ----------- ----------- ------ ------ ------- -------------- ------------------------------- ---------
tableB_id int(11) (NULL) NO PRI (NULL) auto_increment select,insert,update,references
thing_id int(11) (NULL) YES MUL (NULL) select,insert,update,references
user_id int(11) (NULL) YES MUL (NULL) select,insert,update,references
action varchar(32) utf8mb4_bin YES (NULL) select,insert,update,references
/*Index Information*/
---------------------
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
----------- ---------- -------- ------------ ----------- --------- ----------- -------- ------ ------ ---------- ------- ---------------
TEST_tableB 0 PRIMARY 1 tableB_id A 25092 (NULL) (NULL) BTREE
TEST_tableB 1 thing_id 1 thing_id A 25092 (NULL) (NULL) YES BTREE
TEST_tableB 1 user_id 1 user_id A 25092 (NULL) (NULL) YES BTREE
/*DDL Information*/
-------------------
CREATE TABLE `TEST_tableB` (
`tableB_id` int(11) NOT NULL AUTO_INCREMENT,
`thing_id` int(11) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`action` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`tableB_id`),
KEY `thing_id` (`thing_id`),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=25001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
SELECT a.thing_id
FROM TEST_tableA a
LEFT JOIN TEST_tableB b ON a.thing_id = b.thing_id
WHERE b.thing_id IS NULL
LIMIT 1
答案 0 :(得分:0)
这两张表似乎都不需要AUTO_INCREMENT
。它会使磁盘变得混乱并减慢查询速度(对于此大小的表)。
CREATE TABLE `TEST_tableA` (
`thing_id` int(11) DEFAULT NULL,
`thing` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`thing_id`),
KEY `thing` (`thing`)
) ENGINE=InnoDB;
CREATE TABLE `TEST_tableB` (
`thing_id` int(11) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`action` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL,
PRIMARY KEY (`thing_id`, user_id),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB
如果其中任何一个真的是很多:许多映射表,请参阅我的many:many tips。
注意:我建议的PK允许你的“稍后”
现在:从tableA中选择一个尚未在tableB中的thing_id
SELECT A.thing_id
FROM A
LEFT JOIN B ON A.thing_id = B.thing_id
WHERE B.thing_id IS NULL; -- meaning that it is missing from B
稍后:从tableA中选择一个少于X次的table_中的thing_id
SELECT A.thing_id
FROM A
LEFT JOIN B ON A.thing_id = B.thing_id
GROUP BY A.thing_id
HAVING COUNT(*) < X ;
我认为这两个都涉及到A的全表扫描,探测到B。
(提示:不要使用不必要的前缀使表名或列名混乱。)