【问题标题】:Is a SQL trigger faster than a if statement on a interface [closed]SQL触发器是否比接口上的if语句更快[关闭]
【发布时间】:2021-09-10 01:26:57
【问题描述】:

在大数据场景中,一段代码必须运行数万次,检查接口上值的完整性(使用 switch 语句或 if 等)比插入后检查更快带有触发器的数据库上的值(技术上是在插入之前,但从人类的角度来看,在这种情况下,触发器会在输入值之前验证一切是否正确)?

所以基本上我和我的一个朋友对一个涉及收集大量数据的主题有着共同的兴趣,因为我们试图测量的波动非常抽象,只有在很长一段时间内普通人才能注意到一段时间。

问题是没有人提供这些数据,所以我们决定编写一些爬虫来为我们收集值。我们正在谈论数千个具有 7-8 个属性的“对象”来提取,因为我们不仅破产而且不耐烦,等待是一个不可取的选择,因为代码可能每天都必须一遍又一遍地运行才能收集任何东西类似于有用的推断。

话虽如此,当我们在 python 中对接口进行编程以填充 PostgreSQL 数据库时,我建议应该将单位转换作为触发器来完成,因为大多数时候(50-80%)插入的数据不会需要转换。

我认为如果转换不需要转换,触发器不会“浪费时间”,因为我认为触发器是一个多线程过程,其中一个线程休眠,直到触发某些东西导致性能略有提高.我还记得我课堂上展示的这张图表

虽然这有点牵强,因为这个金字塔旨在用于在填充表后检查完整性,因此一个接口不仅必须连接到数据库、读取列、获取一个决定,然后执行它将是最后使用的东西。

我的朋友们认为,我们开发触发器所花费的时间太痛苦了,也太费时了。不仅如此,它还会放大复杂性,众所周知,简单明了的代码总是可取的。不仅如此,即使触发器在最好的情况下工作,就像我说的那样,它们将是多线程的并且能够非常高效,同样可以在带有线程的 python 中复制,它仍然会更快。

他的论点很扎实,尤其是第一部分,因为即使我对 python 很烂,当你像我这样的菜鸟时,在没有图形帮助的情况下更正、更改甚至添加触发器可能会永远持续下去,所以即使我决定了废弃 python 代码不会像浪费时间在触发器上那样大

以下是我们最终使用的代码:

 for tile in tiles:
            nameElement = tile.find_element_by_css_selector('.ct-tile--description')
            priceElement = tile.find_element_by_css_selector('.ct-price-formatted')
            #Elements because its a sneaky way to prevent a failed search, since it may not exist
            discountElements = tile.find_elements_by_css_selector('.ct-discount-amount')
            quantityElement = tile.find_element_by_css_selector('.ct-tile--quantity')
            #Url has been "historically" fetched as a hyperlink from clicking the title
            measureKey = quantityElement.text[-2:]
            rawQuantity = float(quantityElement.text.split()[1].replace(',','.'))
            measures={
                "lt":(1,'l'),
                "dl":(10,'l'),
                "cl":(100,'l'),
                "ml":(1000,'l'),
                "kg":(1,'kg'),
                "gr":(1000,'kg'),
                "un":(1,'un')
            }
            data = {
                "url": nameElement.get_attribute('href'),
                "name": nameElement.text,
                "price": priceElement.text[1:],
                #For this website "Desconto Imediato: " precedes the actual discount and it comes in percentage not the decimal value for analitical purposes
                "discount": 0 if len(discountElements)==0 else float(discountElements[0].text[19:-1])/100,
                #TODO multithreading theres no way the crawler gonna do a switch/if statement for each element when most of the time its gonna be measure in the right measurment
                "measure": measures[measureKey][1],
                "quantity": rawQuantity/measures[measureKey][0]
            }
            
            #print(data)
            #urls.append(url)
            print('collected: '+ str(data))

由于这个项目是朋友之间的项目,所以通常写得不好,所以在评论中我提到我们使用了一个 if/switch 案例,实际上我们只用它来检查折扣。我们最终使用了字典,以便我们可以轻松地在度量之间进行转换(它还没有完成,因为转换可能取决于数量的“前缀”)

您可以将图块视为我们从中提取重要属性的对象

【问题讨论】:

  • 好吧,它并不完全基于意见......我认为触发器是异步调用,因此理论上更快性能不是“意见”......它最终会更快地做到这一点蟒蛇

标签: python sql postgresql


【解决方案1】:

触发器是同步执行的,也就是说,INSERT 必须在触发器运行时等待。调用触发器也有不可忽略的开销,因此在表上带有触发器的INSERTs 肯定会更慢。但是,运行执行检查的应用程序代码也需要时间,因此您必须衡量哪个更快。

最终,如果您想编写一些东西作为触发器或应用程序代码,这是一个品味问题。

我不完全清楚你需要这两件事中的哪一个(也许两者都需要):

  1. 在插入数据之前进行单位转换

  2. 检查数据是否正常,如果不正常则报错

首先,我个人会使用应用程序代码,因为它只是一个简单的计算,在数据库代码中做得并不比在应用程序代码中好,而且客户端代码的调试更容易。

对于第二个,我更喜欢触发器,因为它与INSERT 在同一个事务中运行,并且触发器中发生的任何错误都将保证INSERT 被回滚。这是关于数据完整性的,最好在尽可能靠近数据的地方进行检查。

如果您使用触发器,并且希望避免在您知道没有必要的情况下调用触发器,您可以使用 CREATE TRIGGERWHEN 子句来避免调用触发器的开销那些案例。

【讨论】:

  • 我会认为触发器是异步执行的,就像它的名字暗示的那样,排除了这个问题,因为现在我只打算在插入数据之前执行单位转换,不仅 sql 触发器编码需要更长的时间,但我认为它会更慢
猜你喜欢
  • 2020-02-15
  • 1970-01-01
  • 2015-12-23
  • 2012-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多