プロの興味が私の週末を盗んだ方法

すべての人に良い一日を! この記事( オンラインフラワーショップ、またはバレンタインデーに失敗した方法)を読んだ後、Bitrixのサイトの1つを最適化した経験を共有することにしました。 不明な理由で、彼らの経験を共有する決定的なキックを与えたのはこの記事でした。 私のストーリーが誰かの貴重な時間を節約してくれると信じたい(私の「終わらせる」特性のため、私は目標を達成するために2日間休みを過ごした。週末にクライアントを職場に残したくない)同僚が私の間違いを指摘します。



金曜日に、3.2 GBの自動車部品とデータベースを備えたBitrix Webサイトを入手しました。 問題:サイトがページをまったく表示しなかったか、待機中にこのサイトにアクセスした理由を忘れることがありました。 私が何を試みたのか、最終的に何を成し遂げたのかをカットの下で説明します。



したがって、より詳細には、古いホスティングのパラメーター:





通常、次の手順を実行してサイトをBitrix(VDS)用に最適化しますが、今回は具体的な結果を生成しませんでした。





ローカルバージョンを展開することに決めたとき、3.2 GBのデータベースサイト、特に訪問者のバスケットを担当するb_sale_fuserテーブル(2.4 GB)に非常に驚きました。 判明したように、2014年のデータが含まれていました。 この表を見ると、いくつかの機能に気付きました。













この段階では、追加パラメーターなしでCsaleBasket :: GetBasketUserID(bSkipFUserInit)メソッドを使用することに問題があると仮定しました。 ニュアンスは、クライアントがまだバスケットに何も入れていない場合でも、 bSkipFUserInitパラメーターテーブルにレコードを作成することです。 ファイルの1つで、 result_modifier.phpが必須パラメーターなしで不運なメソッドへの呼び出しを見つけたときに、私の推測が確認されました。 この点を修正し、無関係なデータのテーブルをクリアします(筋肉が絶えず落ち、関連テーブルからデータを削除する必要があるため、約3時間。これはすべて、後悔した標準のbitrixメソッドを使用して行われました。クリーニング後、レコードの数は1,900万から400,000に減少しました。これはローカルバージョンに有益な効果がありましたが、それでも機能しませんでした。ページは20〜30秒で表示され始めました。



次に、遅いクエリを検索することにしました。 なぜなら bitrixenvを使用するため、マッスル設定を編集するためのコマンドの順序は次のようになります。



nano /etc/mysql/bx/bvxat.cnf #     log_slow_queries = /var/log/mysql/mysql-slow.log long_query_time = 1 service mysqld restart
      
      





経過後、300秒以上実行された2つのリクエストが見つかりました(以下を参照)。 それらの1つは、カタログ全体から4つのランダムな商品を示しました。 その時、私はより良い時までこのコンポーネントの呼び出しについてコメントすることにしました。 しかし、2番目のメニューは、メインメニューの作成を担当しているため、そのように除外することはできません(以下を参照)。



SQLクエリ
 Tcp port: 3306 Unix socket: /var/lib/mysqld/mysqld.sock Time Id Command Argument # Time: 180318 18:30:07 # User@Host: bitrix[bitrix] @ localhost [] # Thread_id: 96 Schema: testdb QC_hit: No # Query_time: 301.414008 Lock_time: 0.000324 Rows_sent: 13 Rows_examined: 260456 use testdb; SET timestamp=1521387007; SELECT DISTINCT BS.*, B.LIST_PAGE_URL, B.SECTION_PAGE_URL, B.IBLOCK_TYPE_ID, B.CODE as IBLOCK_CODE, B.XML_ID as IBLOCK_EXTERNAL_ID, BS.XML_ID as EXTERNAL_ID, DATE_FORMAT(BS.TIMESTAMP_X, '%d.%m.%Y %H:%i:%s') as TIMESTAMP_X, DATE_FORMAT(BS.DATE_CREATE, '%d.%m.%Y %H:%i:%s') as DATE_CREATE ,COUNT(DISTINCT BE.ID) as ELEMENT_CNT FROM b_iblock_section BS INNER JOIN b_iblock B ON BS.IBLOCK_ID = B.ID INNER JOIN b_iblock_section BSTEMP ON BSTEMP.IBLOCK_ID = BS.IBLOCK_ID LEFT JOIN b_iblock_section_element BSE ON BSE.IBLOCK_SECTION_ID=BSTEMP.ID LEFT JOIN b_iblock_element BE ON (BSE.IBLOCK_ELEMENT_ID=BE.ID AND ((BE.WF_STATUS_ID=1 AND BE.WF_PARENT_ELEMENT_ID IS NULL ) AND BE.IBLOCK_ID = BS.IBLOCK_ID ) AND BE.ACTIVE='Y' AND (BE.ACTIVE_TO >= now() OR BE.ACTIVE_TO IS NULL) AND (BE.ACTIVE_FROM <= now() OR BE.ACTIVE_FROM IS NULL)) WHERE 1=1 AND BSTEMP.IBLOCK_ID = BS.IBLOCK_ID AND BSTEMP.LEFT_MARGIN >= BS.LEFT_MARGIN AND BSTEMP.RIGHT_MARGIN <= BS.RIGHT_MARGIN AND BSTEMP.GLOBAL_ACTIVE = 'Y' AND ((((BS.ACTIVE='Y')))) AND ((((BS.GLOBAL_ACTIVE='Y')))) AND ((((BS.IBLOCK_ID = '9')))) AND ((((BS.DEPTH_LEVEL <= '1')))) AND ((((B.ID = '9')))) AND (( B.ID IN ( SELECT IBLOCK_ID FROM b_iblock_group IBG WHERE IBG.GROUP_ID IN (2) AND IBG.PERMISSION >= 'R' AND (IBG.PERMISSION='X' OR B.ACTIVE='Y') ) OR (B.RIGHTS_MODE = 'E' AND EXISTS ( SELECT SR.SECTION_ID FROM b_iblock_section_right SR INNER JOIN b_iblock_right IBR ON IBR.ID = SR.RIGHT_ID INNER JOIN b_user_access UA ON UA.ACCESS_CODE = IBR.GROUP_CODE AND UA.USER_ID = 0 WHERE SR.SECTION_ID = BS.ID AND IBR.OP_SREAD = 'Y' )) )) GROUP BY BS.ID, B.ID ORDER BY BS.LEFT_MARGIN asc;
      
      







最初は、戦闘サーバーではこのリクエストが300秒以上で完了し、ローカルマシンでは20秒以上で完了したことを恥ずかしく思いませんでした。この理由はサイトの負荷が不十分であると考えました。 つまり 戦闘サイトの1分あたりの訪問数は1分あたり20人であり、ローカルコピーの場合、リクエストを行うのは私だけでした。 Jmeterユーティリティを使用することにしました(以下を参照)。







20回のクエリでこのテストを実行した後、ブラウザーでサイトを開くことにし、すぐに次のエラーを受け取りました: テーブル / tmp / *のキーファイルが正しくありません 。 判明したように、各sql要求に対して、マッスルは一時フォルダー内のディスクに一時テーブルを作成しましたが、十分なスペースがありませんでした。 なぜなら 原則的に強力ではないので、MySqlはすべてを知っているGoogleに質問をしました(そして、検索に頼らずに少なくとも1日はありましたか?!)。



サンプルにTEXT / BLOB型のフィールドが含まれている場合、データベースはディスク上に一時テーブルを作成します



そして、偉大なヘルパーは、いつものように正しかった! b_iblock_sectionテーブルには、そのようなフィールドが2つ(右を参照)、つまりDESCRIPTIONSEARCHABLE_CONTENTがありました







これらのフィールドをリクエストから削除して書き換えると(以下を参照)、何倍もの速度で勝ちました! その結果、ローカルマシンの20秒以上のクエリではなく、1.5秒後に結果が返され始めました。 しかし、喜ぶには早すぎました。 データベース内のこのリクエストはシステムbitrixファイル/bitrix/modules/iblock/classes/mysql/iblocksection.phpで生成されたためです。 残念ながら、私はそれを修正するよりも良いものを見つけることができませんでしたが、Bitrixカーネルの最初の更新で編集が失われる可能性があることを認識しています。 しかし、その時、私はすでにこのサイトで3日間連続で苦労していました、そして、日曜日の夕方までに時間が過ぎました。 そしてこの農場を去り......



だった
 BS.*, ...
      
      







になっています
 BS.ID, BS.TIMESTAMP_X, BS.MODIFIED_BY, BS.DATE_CREATE, BS.CREATED_BY, BS.IBLOCK_ID, BS.IBLOCK_SECTION_ID, BS.ACTIVE, BS.GLOBAL_ACTIVE, BS.SORT, BS.NAME, BS.PICTURE, BS.LEFT_MARGIN, BS.RIGHT_MARGIN, BS.DEPTH_LEVEL, BS.CODE, BS.XML_ID, BS.TMP_ID, BS.DETAIL_PICTURE, BS.SOCNET_GROUP_ID, ...
      
      







しかし、喜ぶには早すぎました。 編集内容を戦闘サイトにアップロードすると、結果は良くなりましたが、望みとはほど遠いものでした(300秒-> 100+秒)。 困惑してしばらく自分自身に呪いをかけた後、バトルサーバーとローカルマシンのmysqlバージョンの違いについての仮定を立てようとすることにしました。 この問題はデータベース自体の設定にあると思われるかもしれませんが、戦闘車両と同じ設定を設定するときに、この項目を途中で切り取ります。 バージョン5.5からのアップグレードのみが残っていました*サーバー上の5.6.35 (マシン上のmysqlの最新バージョン)。 彼はこのステップに大きな期待を抱いていた。なぜなら、考えられることのアイデアと仮定が尽きていたからだ。 はい、週末に問題の発見と解決に費やしたのは残念でした。 週末とともに、私の神経は終わった...しかし、更新後、データベースが正常に機能し、リクエストログの数値がローカルマシンの数値と一致し、サイトが飛び始めたとき、私はどれほど嬉しかったです。 喜びの制限はなく、2人で十分でした。私と彼女は、週末の残りをモニター画面の後ろではなく彼女と過ごすことに気づきました。



自分にとってどのような方法でしたか:





時間を割いてくださった皆さんに感謝します。 建設的な批判やアドバイスを残せば素晴らしいことです。



PS拷問の2日目の終わりに、私は「老人と海」という話を思い出し、私の試みも報われないと思ったが、何も起こらなかった。



PPS b_sale_fuserテーブルおよび他の関連テーブルからのデータ削除のレートを上げるために、それらからインデックスを削除し、更新後に再度追加することができました。



All Articles