草庐IT

mysql - 无法使连接正常工作

coder 2023-10-13 原文

我有以下数据:

customer
+---------------------------------------------------------------------------------------------+
| id    | email             | firstname     | lastname      | no_pub    | customer_address    |
|---------------------------------------------------------------------------------------------|
| 1     | martin@domain.com | Martin        | Scorcese      | 0         | 4                   |
| 2     | robert@domain.com | Robert        | De Niro       | 0         | 7                   |
| 3     | bruce@domain;com  | Bruce         | Willis        | 0         | 10                  |
+---------------------------------------------------------------------------------------------+

address
+------------------------------------------+
| id    | city             | zipcode       |
|------------------------------------------|
| 4     | Paris            | 75001         |
| 7     | Marseille        | 13000         |
| 10    | Bordeaux         | 33000         |
+------------------------------------------+

sf_geo_cities
+------------------------------------------+
| id    | region_id    | zipcode           |
|------------------------------------------|
| 1     | 1            | 75001             |
| 2     | 2            | 13000             |
| 2     | 3            | 33000             |
+------------------------------------------+

sf_geo_regions
+------------------------------------------+
| id    | name             | zipcode       |
|------------------------------------------|
| 1     | Ile-de-France    | 75001         |
| 2     | Cote d'Azur      | 13000         |
| 2     | Gironde          | 33000         |
+------------------------------------------+

这是一个示例,这些表中显然有更多数据(客户 300k+,地址 400k+) 最后,我想获得以下数据:

+---------------------------------------------------------------------------------------------+
| id    | email             | firstname     | lastname      | city          | region          |
|---------------------------------------------------------------------------------------------|
| 1     | martin@domain.com | Martin        | Scorcese      | Paris         | Ile-de-France   |
| 2     | robert@domain.com | Robert        | De Niro       | Marseille     | Cote d'Azur     |
| 3     | bruce@domain;com  | Bruce         | Willis        | NULL          | NULL            |
+---------------------------------------------------------------------------------------------+

我尝试了以下 SQL 查询:

SELECT c.id, c.email, c.firstname, c.lastname, gc.name, gr.name
FROM customer c
LEFT JOIN address ad ON ad.id = c.customer_address
JOIN sf_geo_cities gc ON gc.zipcode = ad.zipcode
JOIN sf_geo_regions gr ON gr.id = gc.region_id
WHERE no_pub = 0

但这需要很长时间,我必须关闭 mysql 服务。联接乘以行可能存在问题。

是否有一个简单的查询来获取我期望的数据?

更新#1: 这是在下面的评论中询问的解释:

id  select_type     table   type    possible_keys                                           key         key_len     ref                         rows    Extra   
1   SIMPLE          c       ref     PRIMARY,UNIQ_81398E097D3656A4,UNIQ_81398E09E7927C7...   no_pub      1           const                       136220  Using where
1   SIMPLE          a       eq_ref  PRIMARY                                                 PRIMARY     8           evotest.c.account           1       Using index
1   SIMPLE          ad      eq_ref  PRIMARY                                                 PRIMARY     8           evotest.c.customer_address  1       NULL
1   SIMPLE          gc      ALL     zipcode                                                 NULL        NULL        NULL                        38194   Range checked for each record (index map: 0x8)
1   SIMPLE          gr      eq_ref  PRIMARY                                                 PRIMARY     4           evotest.gc.region_id        1       NULL

更新 #2: 数据库示例 这是我的数据库,样本数据最少。

--
-- Structure de la table `account`
--

CREATE TABLE IF NOT EXISTS `account` (
`id` bigint(20) unsigned NOT NULL,
  `identifier` varchar(255) COLLATE utf8_bin NOT NULL
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=315688 ;

--
-- Structure de la table `customer`
--

CREATE TABLE IF NOT EXISTS `customer` (
`id` bigint(20) unsigned NOT NULL,
  `account` bigint(20) unsigned NOT NULL,
  `customer_address` bigint(20) unsigned DEFAULT NULL,
  `email` varchar(255) COLLATE utf8_bin NOT NULL,
  `lastname` varchar(255) COLLATE utf8_bin NOT NULL,
  `firstname` varchar(255) COLLATE utf8_bin NOT NULL,
  `no_pub` tinyint(1) NOT NULL DEFAULT '0'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=315224 ;

--
-- Structure de la table `address`
--

CREATE TABLE IF NOT EXISTS `address` (
`id` bigint(20) unsigned NOT NULL,
  `city` varchar(64) COLLATE utf8_bin DEFAULT NULL,
  `street` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  `complement` varchar(128) COLLATE utf8_bin DEFAULT NULL,
  `zipcode` varchar(16) COLLATE utf8_bin DEFAULT NULL,
  `country_id` int(11) DEFAULT NULL,
  `cedex` tinyint(1) NOT NULL DEFAULT '0',
  `abroad` tinyint(1) NOT NULL DEFAULT '0'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=442743 ;

--
-- Structure de la table `sf_geo_cities`
--

CREATE TABLE IF NOT EXISTS `sf_geo_cities` (
`id` int(11) NOT NULL,
  `region_id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `slug` varchar(255) NOT NULL,
  `zipcode` varchar(5) NOT NULL,
  `insee_code` int(11) NOT NULL,
  `latitude` float NOT NULL,
  `longitude` float NOT NULL
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=38106 ;

CREATE TABLE IF NOT EXISTS `sf_geo_regions` (
`id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=25 ;

CREATE TABLE IF NOT EXISTS `sf_geo_countries` (
`id` int(11) NOT NULL,
  `code` int(11) NOT NULL,
  `alpha2` varchar(2) NOT NULL,
  `alpha3` varchar(3) NOT NULL,
  `name_en` varchar(45) NOT NULL,
  `name_fr` varchar(45) NOT NULL,
  `is_default` tinyint(1) NOT NULL
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=242 ;

CREATE TABLE IF NOT EXISTS `sf_user_data` (
`id` int(11) NOT NULL,
  `user_id` bigint(20) unsigned NOT NULL,
  `main_activity_type_id` int(11) DEFAULT NULL,
  `main_activity_id` int(11) DEFAULT NULL
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=19001 ;


CREATE TABLE IF NOT EXISTS `sf_activity_types` (
`id` int(11) NOT NULL,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `identifier` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT 'Ne doit pas être modifié, il s agit de la clé dans le tableau de constantes $constants stockant les taux dans l entité Calculator'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3 ;

CREATE TABLE IF NOT EXISTS `sf_activities` (
`id` int(11) NOT NULL,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `asks_for_custom` tinyint(1) NOT NULL DEFAULT '0'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=27 ;

--
-- Index pour les tables exportées
--

ALTER TABLE `account`
 ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `identifier_UNIQUE` (`identifier`);

ALTER TABLE `customer`
 ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `UNIQ_81398E097D3656A4` (`account`), ADD UNIQUE KEY `UNIQ_81398E09E7927C74` (`email`), ADD UNIQUE KEY `UNIQ_81398E091193CB3F` (`customer_address`), ADD KEY `no_pub` (`no_pub`);

ALTER TABLE `address`
 ADD PRIMARY KEY (`id`), ADD KEY `IDX_D4E6F81F92F3E70` (`country_id`), ADD KEY `zipcode` (`zipcode`); 

ALTER TABLE `sf_geo_cities`
 ADD PRIMARY KEY (`id`), ADD KEY `IDX_B56556A198260155` (`region_id`), ADD KEY `zipcode` (`zipcode`);

ALTER TABLE `sf_geo_regions`
 ADD PRIMARY KEY (`id`);

ALTER TABLE `sf_geo_countries`
 ADD PRIMARY KEY (`id`), ADD KEY `IDX_F86325E277153098` (`code`), ADD KEY `IDX_F86325E2B762D672` (`alpha2`), ADD KEY `IDX_F86325E2C065E6E4` (`alpha3`);

ALTER TABLE `sf_user_data`
 ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `UNIQ_E904BFD1A76ED395` (`user_id`), ADD KEY `IDX_E904BFD12E864BE8` (`main_activity_type_id`), ADD KEY `IDX_E904BFD15543A800` (`main_activity_id`);

ALTER TABLE `sf_activity_types`
 ADD PRIMARY KEY (`id`);

ALTER TABLE `sf_activities`
 ADD PRIMARY KEY (`id`); 

--
-- Contraintes pour les tables exportées
--

ALTER TABLE `customer`
ADD CONSTRAINT `FK_81398E091193CB3F` FOREIGN KEY (`customer_address`) REFERENCES `address` (`id`),
ADD CONSTRAINT `FK_81398E097D3656A4` FOREIGN KEY (`account`) REFERENCES `account` (`id`);

ALTER TABLE `address`
ADD CONSTRAINT `FK_D4E6F81F92F3E70` FOREIGN KEY (`country_id`) REFERENCES `sf_geo_countries` (`id`);

ALTER TABLE `sf_geo_cities`
ADD CONSTRAINT `FK_B56556A198260155` FOREIGN KEY (`region_id`) REFERENCES `sf_geo_regions` (`id`);

ALTER TABLE `sf_user_data`
ADD CONSTRAINT `FK_E904BFD12E864BE8` FOREIGN KEY (`main_activity_type_id`) REFERENCES `sf_activity_types` (`id`),
ADD CONSTRAINT `FK_E904BFD15543A800` FOREIGN KEY (`main_activity_id`) REFERENCES `sf_activities` (`id`),
ADD CONSTRAINT `FK_E904BFD1A76ED395` FOREIGN KEY (`user_id`) REFERENCES `account` (`id`);


INSERT INTO `account` (`id`, `identifier`) VALUES ('1', 'martin@domain.com'), ('2', 'robert@domain.com'), ('3', 'bruce@domain.com');

INSERT INTO `sf_geo_countries` (`id`, `code`, `alpha2`, `alpha3`, `name_en`, `name_fr`, `is_default`) VALUES ('1', '1', 'FR', 'FRA', 'France', 'France', '1');

INSERT INTO `address` (`id`, `city`, `street`, `complement`, `zipcode`, `country_id`, `cedex`, `abroad`) VALUES ('1', 'Paris', '1 rue de Paris', NULL, '75001', '1', '0', '0'), ('2', 'Marseille', '1 rue de Marseille', NULL, '13000', '1', '0', '0');

INSERT INTO `customer` (`id`, `account`, `customer_address`, `email`, `lastname`, `firstname`, `no_pub`) VALUES ('1', '1', '1', 'martin@domain.com', 'Scorcese', 'Martin', '0'), ('2', '2', '2', 'robert@domain.com', 'De Niro', 'Robert', '0'), ('3', '3', NULL, 'bruce@domain.com', 'Willis', 'Bruce', '0');

INSERT INTO `sf_activities` (`id`, `name`, `asks_for_custom`) VALUES ('1', 'Activity #1', '0'), ('2', 'Activity #2', '0');

INSERT INTO `sf_activity_types` (`id`, `name`, `identifier`) VALUES ('1', 'Activity Type #1', 'activity-type-1'), ('2', 'Activity Type #2', 'activity-type-2');

INSERT INTO `sf_geo_regions` (`id`, `name`) VALUES ('1', 'Ile-de-France'), ('2', 'Cote d''Azur');

INSERT INTO `sf_geo_cities` (`id`, `region_id`, `name`, `slug`, `zipcode`, `insee_code`, `latitude`, `longitude`) VALUES ('1', '1', 'Paris', 'paris', '75001', '1', '0', '0'), ('2', '2', 'Marseille', 'marseille', '13000', '2', '0', '0');

INSERT INTO `sf_user_data` (`id`, `user_id`, `main_activity_type_id`, `main_activity_id`) VALUES ('1', '1', '1', '1'), ('2', '3', '2', '2');

使用最少的数据,我可以运行以下查询,返回我想要的一切。但是这个查询在我拥有 300k+ 客户和 400k+ 地址的真实数据库中运行了很长时间

SELECT c.id, c.email, c.firstname, c.lastname, acttypes.name AS activity_type, act.name AS activity, gc.name AS city, gr.name AS region
FROM customer c
JOIN account a ON a.id = c.account
LEFT JOIN sf_user_data ud ON ud.user_id = a.id
LEFT JOIN sf_activity_types acttypes ON acttypes.id = ud.main_activity_type_id
LEFT JOIN sf_activities act ON act.id = ud.main_activity_id
LEFT JOIN address ad ON ad.id = c.customer_address
LEFT JOIN sf_geo_cities gc ON gc.zipcode = ad.zipcode
LEFT JOIN sf_geo_regions gr ON gr.id = gc.region_id
WHERE no_pub = 0

更新#3:跟踪加入问题

这个查询运行得很快:

SELECT 
    c.id 
    ,c.email 
    ,c.firstname 
    ,c.lastname 
    ,acttypes.name AS activity_type 
    ,act.name AS activity 
    ,ad.zipcode AS address_zipcode
--    ,gc.name AS city 
--    ,gr.name AS region    
FROM  
    customer c 
JOIN account a ON a.id = c.account
    LEFT JOIN sf_user_data ud ON ud.user_id = a.id
    LEFT JOIN sf_activity_types acttypes ON acttypes.id = ud.main_activity_type_id
    LEFT JOIN sf_activities act ON act.id = ud.main_activity_id
    LEFT JOIN address ad ON ad.id = c.customer_address
--    LEFT JOIN sf_geo_cities gc ON gc.zipcode = ad.zipcode
--    LEFT JOIN sf_geo_regions gr ON gr.id = gc.region_id
WHERE 
    no_pub = 0 

这个查询运行得也很快:

SELECT 
    c.id 
    ,c.email 
    ,c.firstname 
    ,c.lastname 
--    ,acttypes.name AS activity_type 
--    ,act.name AS activity 
    ,ad.zipcode AS address_zipcode
    ,gc.name AS city 
--    ,gr.name AS region    
FROM  
    customer c 
JOIN account a ON a.id = c.account
--    LEFT JOIN sf_user_data ud ON ud.user_id = a.id
--    LEFT JOIN sf_activity_types acttypes ON acttypes.id = ud.main_activity_type_id
--    LEFT JOIN sf_activities act ON act.id = ud.main_activity_id
    LEFT JOIN address ad ON ad.id = c.customer_address
    LEFT JOIN sf_geo_cities gc ON gc.zipcode = ad.zipcode
--    LEFT JOIN sf_geo_regions gr ON gr.id = gc.region_id
WHERE 
    no_pub = 0 

这个查询永远运行:

SELECT 
    c.id 
    ,c.email 
    ,c.firstname 
    ,c.lastname 
    ,acttypes.name AS activity_type 
    ,act.name AS activity 
    ,ad.zipcode AS address_zipcode
    ,gc.name AS city 
--    ,gr.name AS region    
FROM  
    customer c 
JOIN account a ON a.id = c.account
    LEFT JOIN sf_user_data ud ON ud.user_id = a.id
    LEFT JOIN sf_activity_types acttypes ON acttypes.id = ud.main_activity_type_id
    LEFT JOIN sf_activities act ON act.id = ud.main_activity_id
    LEFT JOIN address ad ON ad.id = c.customer_address
    LEFT JOIN sf_geo_cities gc ON gc.zipcode = ad.zipcode
--    LEFT JOIN sf_geo_regions gr ON gr.id = gc.region_id
WHERE 
    no_pub = 0

事件上的联接没问题,地址上的联接没问题,但是尝试将所有这些联接一起使用是行不通的。

最佳答案

正如我在评论中提到的,非常重要的一点是返回了多少条记录。一个语句中的记录太多可能会导致问题,如果您对结果进行分页,一次选择 n 条记录,可能会更好。

要对查询进行故障排除,请逐个连接地构建它,以尝试确定性能何时跌落悬崖。开始于:

SELECT 
    c.id 
    ,c.email 
    ,c.firstname 
    ,c.lastname 
--    ,acttypes.name AS activity_type 
--    ,act.name AS activity 
--    ,gc.name AS city 
--    ,gr.name AS region    
FROM  
    customer c 
--    JOIN account a ON a.id = c.account
--    LEFT JOIN sf_user_data ud ON ud.user_id = a.id
--    LEFT JOIN sf_activity_types acttypes ON acttypes.id = ud.main_activity_type_id
--    LEFT JOIN sf_activities act ON act.id = ud.main_activity_id
--    LEFT JOIN address ad ON ad.id = c.customer_address
--    LEFT JOIN sf_geo_cities gc ON gc.zipcode = ad.zipcode
--    LEFT JOIN sf_geo_regions gr ON gr.id = gc.region_id
WHERE 
    no_pub = 0

然后一次取消对一个联接的注释,直到您的查询执行得非常慢。分析该查询并查看是否可以使用索引对其进行改进。然后继续取消对联接的注释,直到您获得完整的查询。

关于mysql - 无法使连接正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31673960/

有关mysql - 无法使连接正常工作的更多相关文章

  1. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  2. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  3. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  4. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  5. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

  6. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  7. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  8. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

  9. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  10. ruby - 无法覆盖 irb 中的 to_s - 2

    我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)

随机推荐