MYSQL数据库设计,大表之间的查询

时间:2017-02-04 21:12:23

标签: mysql sql database database-design database-performance

我拥有的:

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_idtableA选择一个tableB <{1}}

自学SQL,我无法找到一种方法来有效地使用非常大的表。也许我只是没有索引吗?我一直在测试MariaDB是否有所作为。

**

编辑(根据要求)

**

TEST_tableA:

/*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

TEST_tableB:

/*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

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。

(提示:不要使用不必要的前缀使表名或列名混乱。)